-
Notifications
You must be signed in to change notification settings - Fork 667
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
37eb2b3
commit b972cde
Showing
8 changed files
with
368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
repo_dir=$1 | ||
input_image=$2 | ||
output_file=$3 | ||
cert_file=$4 | ||
key_file=$5 | ||
tmp_dir= | ||
clean_up() | ||
{ | ||
sudo rm -rf $tmp_dir | ||
sudo rm -rf $output_file | ||
exit $1 | ||
} | ||
|
||
DIR="$(dirname "$0")" | ||
|
||
tmp_dir=$(mktemp -d) | ||
sha1=$(cat $input_image | sha1sum | awk '{print $1}') | ||
echo -n "." | ||
cp $repo_dir/installer/sharch_body.sh $output_file || { | ||
echo "Error: Problems copying sharch_body.sh" | ||
clean_up 1 | ||
} | ||
# Replace variables in the sharch template | ||
sed -i -e "s/%%IMAGE_SHA1%%/$sha1/" $output_file | ||
echo -n "." | ||
tar_size="$(wc -c < "${input_image}")" | ||
cat $input_image >> $output_file | ||
sed -i -e "s|%%PAYLOAD_IMAGE_SIZE%%|${tar_size}|" ${output_file} | ||
CMS_SIG="${tmp_dir}/signature.sig" | ||
|
||
echo "$0 CMS signing ${input_image} with ${key_file}. Output file ${output_file}" | ||
. $repo_dir/scripts/sign_image_dev.sh | ||
sign_image_dev ${cert_file} ${key_file} $output_file ${CMS_SIG} || clean_up 1 | ||
|
||
cat ${CMS_SIG} >> ${output_file} | ||
echo "Signature done." | ||
# append signature to binary | ||
sudo rm -rf ${CMS_SIG} | ||
sudo rm -rf $tmp_dir | ||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
repo_dir=$1 | ||
out_dir=$2 | ||
mock_image="mock_img.bin" | ||
output_file=$out_dir/output_file.bin | ||
cert_file=$3 | ||
other_cert_file=$4 | ||
tmp_dir= | ||
clean_up() | ||
{ | ||
sudo rm -rf $tmp_dir | ||
sudo rm -rf $mock_image | ||
exit $1 | ||
} | ||
DIR="$(dirname "$0")" | ||
[ -d $out_dir ] || rm -rf $out_dir | ||
mkdir $out_dir | ||
tmp_dir=$(mktemp -d) | ||
#generate self signed keys and certificate | ||
key_file=$tmp_dir/private-key.pem | ||
pub_key_file=$tmp_dir/public-key.pem | ||
openssl ecparam -name secp256r1 -genkey -noout -out $key_file | ||
openssl ec -in $key_file -pubout -out $pub_key_file | ||
openssl req -new -x509 -key $key_file -out $cert_file -days 360 -subj "/C=US/ST=Test/L=Test/O=Test/CN=Test" | ||
alt_key_file=$tmp_dir/alt-private-key.pem | ||
alt_pub_key_file=$tmp_dir/alt-public-key.pem | ||
openssl ecparam -name secp256r1 -genkey -noout -out $alt_key_file | ||
openssl ec -in $alt_key_file -pubout -out $alt_pub_key_file | ||
openssl req -new -x509 -key $alt_key_file -out $other_cert_file -days 360 -subj "/C=US/ST=Test/L=Test/O=Test/CN=Test" | ||
|
||
echo "this is a mock image\nThis is another line !2#4%6\n" > $mock_image | ||
echo "Created a mock image with following text:" | ||
cat $mock_image | ||
# create signed mock image | ||
|
||
sh $DIR/create_mock_image.sh $repo_dir $mock_image $output_file $cert_file $key_file || { | ||
echo "Error: unable to create mock image" | ||
clean_up 1 | ||
} | ||
|
||
[ -f "$output_file" ] || { | ||
echo "signed mock image not created - exiting without testing" | ||
clean_up 1 | ||
} | ||
|
||
test_image_1=$out_dir/test_image_1.bin | ||
cp -v $output_file $test_image_1 || { | ||
echo "Error: Problems copying image" | ||
clean_up 1 | ||
} | ||
|
||
# test_image_1 = modified image size to something else - should fail on signature verification | ||
image_size=$(sed -n 's/^payload_image_size=\(.*\)/\1/p' < $test_image_1) | ||
sed -i "/payload_image_size=/c\payload_image_size=$(($image_size - 5))" $test_image_1 | ||
|
||
test_image_2=$out_dir/test_image_2.bin | ||
cp -v $output_file $test_image_2 || { | ||
echo "Error: Problems copying image" | ||
clean_up 1 | ||
} | ||
|
||
# test_image_2 = modified image sha1 to other sha1 value - should fail on signature verification | ||
im_sha=$(sed -n 's/^payload_sha1=\(.*\)/\1/p' < $test_image_2) | ||
sed -i "/payload_sha1=/c\payload_sha1=2f1bbd5a0d411253103e688e4e66c00c94bedd40" $test_image_2 | ||
|
||
tmp_image=$tmp_dir/"tmp_image.bin" | ||
echo "this is a different image now" >> $mock_image | ||
sh $DIR/create_mock_image.sh $repo_dir $mock_image $tmp_image $cert_file $key_file || { #TODO modify mock image instead of adding new signature | ||
echo "Error: unable to create mock image" | ||
clean_up 1 | ||
} | ||
# test_image_3 = original mock image with wrong signature | ||
# Extract cms signature from signed file | ||
test_image_3=$out_dir/"test_image_3.bin" | ||
tmp_sig="${tmp_dir}/tmp_sig.sig" | ||
TMP_TAR_SIZE=$(head -n 50 $tmp_image | grep "payload_image_size=" | cut -d"=" -f2- ) | ||
sed -e '1,/^exit_marker$/d' $tmp_image | tail -c +$(( $TMP_TAR_SIZE + 1 )) > $tmp_sig | ||
|
||
TAR_SIZE=$(head -n 50 $output_file | grep "payload_image_size=" | cut -d"=" -f2- ) | ||
SHARCH_SIZE=$(sed '/^exit_marker$/q' $output_file | wc -c) | ||
SIG_PAYLOAD_SIZE=$(($TAR_SIZE + $SHARCH_SIZE )) | ||
head -c $SIG_PAYLOAD_SIZE $output_file > $test_image_3 | ||
sudo rm -rf $tmp_image | ||
|
||
cat ${tmp_sig} >> ${test_image_3} | ||
|
||
# test_image_4 = modified image with original mock image signature | ||
test_image_4=$out_dir/"test_image_4.bin" | ||
tmp_sig2="${tmp_dir}/tmp_sig2.sig" | ||
head -c $SIG_PAYLOAD_SIZE $output_file > $test_image_4 | ||
echo "this is additional line" >> $test_image_4 | ||
sed -e '1,/^exit_marker$/d' $output_file | tail -c +$(( $TAR_SIZE + 1 )) > $tmp_sig2 | ||
cat ${tmp_sig} >> ${test_image_4} | ||
clean_up 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#!/bin/sh | ||
image_file="${1}" | ||
cms_sig_file="sig.cms" | ||
lines_for_lookup=50 | ||
SECURE_UPGRADE_ENABLED=0 | ||
DIR="$(dirname "$0")" | ||
if [ -d "/sys/firmware/efi/efivars" ]; then | ||
if ! [ -n "$(ls -A /sys/firmware/efi/efivars 2>/dev/null)" ]; then | ||
mount -t efivarfs none /sys/firmware/efi/efivars 2>/dev/null | ||
fi | ||
SECURE_UPGRADE_ENABLED=$(bootctl status 2>/dev/null | grep -c "Secure Boot: enabled") | ||
else | ||
echo "efi not supported - exiting without verification" | ||
exit 0 | ||
fi | ||
|
||
. /usr/local/bin/verify_image_common.sh | ||
|
||
if [ ${SECURE_UPGRADE_ENABLED} -eq 0 ]; then | ||
echo "secure boot not enabled - exiting without image verification" | ||
exit 0 | ||
fi | ||
|
||
clean_up () | ||
{ | ||
if [ -d ${EFI_CERTS_DIR} ]; then rm -rf ${EFI_CERTS_DIR}; fi | ||
if [ -d "${TMP_DIR}" ]; then rm -rf ${TMP_DIR}; fi | ||
exit $? | ||
} | ||
|
||
TMP_DIR=$(mktemp -d) | ||
DATA_FILE="${TMP_DIR}/data.bin" | ||
CMS_SIG_FILE="${TMP_DIR}/${cms_sig_file}" | ||
TAR_SIZE=$(head -n $lines_for_lookup $image_file | grep "payload_image_size=" | cut -d"=" -f2- ) | ||
SHARCH_SIZE=$(sed '/^exit_marker$/q' $image_file | wc -c) | ||
SIG_PAYLOAD_SIZE=$(($TAR_SIZE + $SHARCH_SIZE )) | ||
# Extract cms signature from signed file | ||
# Add extra byte for payload | ||
sed -e '1,/^exit_marker$/d' $image_file | tail -c +$(( $TAR_SIZE + 1 )) > $CMS_SIG_FILE | ||
# Extract image from signed file | ||
head -c $SIG_PAYLOAD_SIZE $image_file > $DATA_FILE | ||
# verify signature with certificate fetched with efi tools | ||
EFI_CERTS_DIR=/tmp/efi_certs | ||
[ -d $EFI_CERTS_DIR ] && rm -rf $EFI_CERTS_DIR | ||
mkdir $EFI_CERTS_DIR | ||
efi-readvar -v db -o $EFI_CERTS_DIR/db_efi >/dev/null || | ||
{ | ||
echo "Error: unable to read certs from efi db: $?" | ||
clean_up 1 | ||
} | ||
# Convert one file to der certificates | ||
sig-list-to-certs $EFI_CERTS_DIR/db_efi $EFI_CERTS_DIR/db >/dev/null|| | ||
{ | ||
echo "Error: convert sig list to certs: $?" | ||
clean_up 1 | ||
} | ||
for file in $(ls $EFI_CERTS_DIR | grep "db-"); do | ||
LOG=$(openssl x509 -in $EFI_CERTS_DIR/$file -inform der -out $EFI_CERTS_DIR/cert.pem 2>&1) | ||
if [ $? -ne 0 ]; then | ||
logger "cms_validation: $LOG" | ||
fi | ||
# Verify detached signature | ||
LOG=$(verify_image_sign_common $image_file $DATA_FILE $CMS_SIG_FILE) | ||
VALIDATION_RES=$? | ||
if [ $VALIDATION_RES -eq 0 ]; then | ||
RESULT="CMS Verified OK this is using efi keys" | ||
echo "verification ok:$RESULT" | ||
# No need to continue. | ||
# Exit without error if any success signature verification. | ||
clean_up 0 | ||
fi | ||
done | ||
echo "Error: image not verified $LOG" | ||
|
||
clean_up 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#!/bin/bash | ||
verify_image_sign_common() { | ||
image_file="${1}" | ||
cms_sig_file="sig.cms" | ||
TMP_DIR=$(mktemp -d) | ||
DATA_FILE="${2}" | ||
CMS_SIG_FILE="${3}" | ||
|
||
openssl version | awk '$2 ~ /(^0\.)|(^1\.(0\.|1\.0))/ { exit 1 }' | ||
if [ $? -eq 0 ]; then | ||
# for version 1.1.1 and later | ||
no_check_time="-no_check_time" | ||
else | ||
# for version older than 1.1.1 use noattr | ||
no_check_time="-noattr" | ||
fi | ||
|
||
# making sure image verification is supported | ||
EFI_CERTS_DIR=/tmp/efi_certs | ||
RESULT="CMS Verification Failure" | ||
LOG=$(openssl cms -verify $no_check_time -noout -CAfile $EFI_CERTS_DIR/cert.pem -binary -in ${CMS_SIG_FILE} -content ${DATA_FILE} -inform pem 2>&1 > /dev/null ) | ||
VALIDATION_RES=$? | ||
if [ $VALIDATION_RES -eq 0 ]; then | ||
RESULT="CMS Verified OK this is using efi keys" | ||
if [ -d "${TMP_DIR}" ]; then rm -rf ${TMP_DIR}; fi | ||
echo "verification ok:$RESULT" | ||
# No need to continue. | ||
# Exit without error if any success signature verification. | ||
return 0 | ||
fi | ||
|
||
if [ -d "${TMP_DIR}" ]; then rm -rf ${TMP_DIR}; fi | ||
return 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/bin/bash | ||
image_file="${1}" | ||
cert_path="${2}" | ||
cms_sig_file="sig.cms" | ||
TMP_DIR=$(mktemp -d) | ||
DATA_FILE="${TMP_DIR}/data.bin" | ||
CMS_SIG_FILE="${TMP_DIR}/${cms_sig_file}" | ||
lines_for_lookup=50 | ||
|
||
TAR_SIZE=$(head -n $lines_for_lookup $image_file | grep "payload_image_size=" | cut -d"=" -f2- ) | ||
SHARCH_SIZE=$(sed '/^exit_marker$/q' $image_file | wc -c) | ||
SIG_PAYLOAD_SIZE=$(($TAR_SIZE + $SHARCH_SIZE )) | ||
# Extract cms signature from signed file - exit marker marks last sharch prefix + number of image lines + 1 for next linel | ||
# Add extra byte for payload - extracting image signature from line after data file | ||
sed -e '1,/^exit_marker$/d' $image_file | tail -c +$(( $TAR_SIZE + 1 )) > $CMS_SIG_FILE | ||
# Extract image from signed file | ||
head -c $SIG_PAYLOAD_SIZE $image_file > $DATA_FILE | ||
EFI_CERTS_DIR=/tmp/efi_certs | ||
[ -d $EFI_CERTS_DIR ] && rm -rf $EFI_CERTS_DIR | ||
mkdir $EFI_CERTS_DIR | ||
cp $cert_path $EFI_CERTS_DIR/cert.pem | ||
|
||
DIR="$(dirname "$0")" | ||
. $DIR/verify_image_sign_common.sh | ||
verify_image_sign_common $image_file $DATA_FILE $CMS_SIG_FILE | ||
VERIFICATION_RES=$? | ||
if [ -d "${TMP_DIR}" ]; then rm -rf ${TMP_DIR}; fi | ||
[ -d $EFI_CERTS_DIR ] && rm -rf $EFI_CERTS_DIR | ||
exit $VERIFICATION_RES |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
|
||
import subprocess | ||
import os | ||
import sys | ||
import shutil | ||
|
||
|
||
class TestSignVerify(object): | ||
def _run_verification_script_and_check(self, image, cert_file_path, success_str, expected_value=0): | ||
res = subprocess.run(['sh', self._verification_script, image, cert_file_path]) | ||
assert res.returncode == expected_value | ||
print(success_str) | ||
|
||
def test_basic_signature_verification(self): | ||
self._run_verification_script_and_check(os.path.join(self._out_dir_path, 'output_file.bin'), | ||
self._cert_file_path, "test case 1 - basic verify signature - SUCCESS") | ||
|
||
# change image size to something else - should fail on signature verification | ||
def test_modified_image_size(self): | ||
self._run_verification_script_and_check(os.path.join(self._out_dir_path, 'test_image_1.bin'), | ||
self._cert_file_path, "test case 2 - modified image size - SUCCESS", 1) | ||
|
||
def test_modified_image_sha1(self): | ||
self._run_verification_script_and_check(os.path.join(self._out_dir_path, 'test_image_2.bin'), | ||
self._cert_file_path, "test case 3 - modified image sha1 - SUCCESS", 1) | ||
|
||
def test_modified_image_data(self): | ||
self._run_verification_script_and_check(os.path.join(self._out_dir_path, 'test_image_3.bin'), | ||
self._cert_file_path, "test case 4 - modified image data - SUCCESS", 1) | ||
|
||
def test_modified_image_signature(self): | ||
self._run_verification_script_and_check(os.path.join(self._out_dir_path, 'test_image_4.bin'), | ||
self._cert_file_path, "test case 5 - modified image data - SUCCESS", 1) | ||
|
||
def test_verify_image_with_wrong_certificate(self): | ||
self._run_verification_script_and_check(os.path.join(self._out_dir_path, 'output_file.bin'), | ||
self._alt_cert_path, "test case 6 - verify with wrong signature - SUCCESS", 1) | ||
|
||
def __init__(self): | ||
self._test_path = os.path.dirname(os.path.abspath(__file__)) | ||
self._modules_path = os.path.dirname(self._test_path) | ||
self._repo_path = os.path.join(self._modules_path, '../..') | ||
self._scripts_path = os.path.join(self._modules_path, "scripts") | ||
sys.path.insert(0, self._test_path) | ||
sys.path.insert(0, self._modules_path) | ||
sys.path.insert(0, self._scripts_path) | ||
script_path = os.path.join(self._scripts_path, 'create_sign_and_verify_test_files.sh') | ||
self._verification_script = os.path.join(self._scripts_path, 'verify_image_sign_test.sh') | ||
self._out_dir_path = '/tmp/sign_verify_test' | ||
self._cert_file_path = os.path.join(self._out_dir_path, 'self_certificate.pem') | ||
self._alt_cert_path = os.path.join(self._out_dir_path, 'alt_self_certificate.pem') | ||
create_files_result = subprocess.run(['sh', script_path, self._repo_path, self._out_dir_path, | ||
self._cert_file_path, | ||
self._alt_cert_path]) | ||
print(create_files_result) | ||
assert create_files_result.returncode == 0 | ||
|
||
def __del__(self): | ||
shutil.rmtree(self._out_dir_path) | ||
|
||
|
||
if __name__ == '__main__': | ||
t = TestSignVerify() | ||
t.test_basic_signature_verification() | ||
subprocess.run(['ls', '/tmp/sign_verify_test']) | ||
t.test_modified_image_data() | ||
t.test_modified_image_sha1() | ||
t.test_modified_image_signature() | ||
t.test_modified_image_size() | ||
t.test_verify_image_with_wrong_certificate() |