From 277021b49b3dec6e886d0cbc46a71521894f82b0 Mon Sep 17 00:00:00 2001 From: ycoheNvidia <99744138+ycoheNvidia@users.noreply.github.com> Date: Mon, 26 Jun 2023 12:04:40 +0300 Subject: [PATCH] Add support for secure upgrade (#11862) - What I did Added support for secure upgrade. - How I did it During sonic_installer install, added secure upgrade image verification. HLD can be found in the following PR: sonic-net/SONiC#1024 - Why I did it Feature is used to allow image was not modified since built from vendor. During installation, image can be verified with a signature attached to it. - How I did it Feature includes image signing during build (in sonic buildimage repo) and verification during image install (in sonic-utilities). - How to verify it In order for image verification - image must be signed - need to provide signing key and certificate (paths in SECURE_UPGRADE_DEV_SIGNING_KEY and SECURE_UPGRADE_DEV_SIGNING_CERT in rules/config) during build , and during image install, need to enable secure boot flag in bios, and signing_certificate should be available in bios. - Feature dependencies In order for this feature to work smoothly, need to have secure boot feature implemented as well. The Secure boot feature will be merged in the near future. --- build_image.sh | 2 +- installer/sharch_body.sh | 8 +++++-- onie-mk-demo.sh | 48 ++++++++++++++++++++++++++++++++++++++- scripts/sign_image_dev.sh | 11 +++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100755 scripts/sign_image_dev.sh diff --git a/build_image.sh b/build_image.sh index 4b1dfc9582ee..62d03296020e 100755 --- a/build_image.sh +++ b/build_image.sh @@ -86,7 +86,7 @@ generate_onie_installer_image() ## Note: Don't leave blank between lines. It is single line command. ./onie-mk-demo.sh $CONFIGURED_ARCH $TARGET_MACHINE $TARGET_PLATFORM-$TARGET_MACHINE-$ONIEIMAGE_VERSION \ installer platform/$TARGET_MACHINE/platform.conf $output_file OS $IMAGE_VERSION $ONIE_IMAGE_PART_SIZE \ - $ONIE_INSTALLER_PAYLOAD + $ONIE_INSTALLER_PAYLOAD $SECURE_UPGRADE_SIGNING_CERT $SECURE_UPGRADE_DEV_SIGNING_KEY } # Generate asic-specific device list diff --git a/installer/sharch_body.sh b/installer/sharch_body.sh index e6289371cd58..9683b4692dca 100644 --- a/installer/sharch_body.sh +++ b/installer/sharch_body.sh @@ -11,7 +11,9 @@ ## echo -n "Verifying image checksum ..." -sha1=$(sed -e '1,/^exit_marker$/d' "$0" | sha1sum | awk '{ print $1 }') +payload_image_size=%%PAYLOAD_IMAGE_SIZE%% + +sha1=$(sed -e '1,/^exit_marker$/d' "$0" | head -c $payload_image_size | sha1sum | awk '{ print $1 }') payload_sha1=%%IMAGE_SHA1%% @@ -45,7 +47,9 @@ if [ "$(id -u)" = "0" ] ; then fi cd $tmp_dir echo -n "Preparing image archive ..." -sed -e '1,/^exit_marker$/d' $archive_path | tar xf - || exit 1 + +sed -e '1,/^exit_marker$/d' $archive_path | head -c $payload_image_size | tar xf - || exit 1 + echo " OK." cd $cur_wd if [ -n "$extract" ] ; then diff --git a/onie-mk-demo.sh b/onie-mk-demo.sh index 0905673d42cb..b466441ca31b 100755 --- a/onie-mk-demo.sh +++ b/onie-mk-demo.sh @@ -14,6 +14,9 @@ output_file=$6 demo_type=$7 image_version=$8 onie_image_part_size=$9 +onie_installer_payload=${10} +cert_file=${11} +key_file=${12} shift 9 @@ -100,7 +103,7 @@ sed -i -e "s/%%DEMO_TYPE%%/$demo_type/g" \ -e "s@%%OUTPUT_RAW_IMAGE%%@$output_raw_image@" \ $tmp_installdir/install.sh || clean_up 1 echo -n "." -cp -r $* $tmp_installdir || clean_up 1 +cp -r $onie_installer_payload $tmp_installdir || clean_up 1 echo -n "." [ -r "$platform_conf" ] && { cp $platform_conf $tmp_installdir || clean_up 1 @@ -130,7 +133,50 @@ cp $installer_dir/sharch_body.sh $output_file || { # Replace variables in the sharch template sed -i -e "s/%%IMAGE_SHA1%%/$sha1/" $output_file echo -n "." +tar_size="$(wc -c < "${sharch}")" +sed -i -e "s|%%PAYLOAD_IMAGE_SIZE%%|${tar_size}|" ${output_file} cat $sharch >> $output_file +echo "secure upgrade flags: SECURE_UPGRADE_MODE = $SECURE_UPGRADE_MODE, \ +SECURE_UPGRADE_DEV_SIGNING_KEY = $SECURE_UPGRADE_DEV_SIGNING_KEY, SECURE_UPGRADE_SIGNING_CERT = $SECURE_UPGRADE_SIGNING_CERT" + +if [ "$SECURE_UPGRADE_MODE" = "dev" -o "$SECURE_UPGRADE_MODE" = "prod" ]; then + CMS_SIG="${tmp_dir}/signature.sig" + DIR="$(dirname "$0")" + scripts_dir="${DIR}/scripts" + echo "$0 $SECURE_UPGRADE_MODE signing - creating CMS signature for ${output_file}. Output file ${CMS_SIG}" + + if [ "$SECURE_UPGRADE_MODE" = "dev" ]; then + echo "$0 dev keyfile location: ${key_file}." + [ -f ${scripts_dir}/sign_image_dev.sh ] || { + echo "dev sign script ${scripts_dir}/sign_image_dev.sh not found" + rm -rf ${output_file} + } + (${scripts_dir}/sign_image_dev.sh ${cert_file} ${key_file} ${output_file} ${CMS_SIG}) || { + echo "CMS sign error $?" + rm -rf ${CMS_SIG} ${output_file} + } + else # "$SECURE_UPGRADE_MODE" has to be equal to "prod" + [ -f ${scripts_dir}/sign_image_${machine}.sh ] || { + echo "prod sign script ${scripts_dir}/sign_image_${machine}.sh not found" + rm -rf ${output_file} + } + (${scripts_dir}/sign_image_${machine}.sh ${output_file} ${CMS_SIG} ${SECURE_UPGRADE_MODE}) || { + echo "CMS sign error $?" + rm -rf ${CMS_SIG} ${output_file} + } + fi + + [ -f "$CMS_SIG" ] || { + echo "Error: CMS signature not created - exiting without signing" + clean_up 1 + } + # append signature to binary + cat ${CMS_SIG} >> ${output_file} + sudo rm -rf ${CMS_SIG} +elif [ "$SECURE_UPGRADE_MODE" -ne "no_sign" ]; then + echo "SECURE_UPGRADE_MODE not defined or defined as $SECURE_UPGRADE_MODE - build without signing" +fi + rm -rf $tmp_dir echo " Done." diff --git a/scripts/sign_image_dev.sh b/scripts/sign_image_dev.sh new file mode 100755 index 000000000000..668672f49378 --- /dev/null +++ b/scripts/sign_image_dev.sh @@ -0,0 +1,11 @@ +cert_file=$1 +key_file=$2 +image_to_sign=$3 +cms_sig_out=$4 +openssl cms -sign -nosmimecap -signer ${cert_file} -inkey ${key_file} -binary -in $image_to_sign -outform pem -out ${cms_sig_out} || { + echo "$?: CMS sign error" + sudo rm -rf ${cms_sig_out} + exit 1 +} +echo "CMS sign OK" +exit 0