Skip to content

Commit

Permalink
[bluefield] Add secure boot and secure upgrade support (sonic-net#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
ycoheNvidia authored Sep 26, 2023
1 parent 4de6250 commit d914780
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 16 deletions.
7 changes: 5 additions & 2 deletions build_image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,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
Expand Down Expand Up @@ -225,7 +225,10 @@ elif [ "$IMAGE_TYPE" = "aboot" ]; then
fi

elif [[ $CONFIGURED_PLATFORM == nvidia-bluefield ]]; then
sudo --preserve-env /sonic/installer/bluefield/create_sonic_image --kernel $KVERSION
if [[ $SECURE_UPGRADE_MODE != "no_sign" ]]; then
secure_upgrade_keys="--signing-key "$SECURE_UPGRADE_DEV_SIGNING_KEY" --signing-cert "$SECURE_UPGRADE_SIGNING_CERT""
fi
sudo --preserve-env /sonic/installer/bluefield/create_sonic_image --kernel $KVERSION "$secure_upgrade_keys"
if [[ $IMAGE_TYPE != bin ]]; then
sudo chown $USER ./$OUTPUT_BFB_IMAGE
if [[ $IMAGE_TYPE == pxe ]]; then
Expand Down
78 changes: 70 additions & 8 deletions installer/bluefield/create_sonic_image
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ INITRD=
VMLINUZ=
MODULES_DIR=

SIGNING_CERT=
SIGNING_KEY=
CDIR=/sonic/
SDIR=$CDIR/installer/bluefield
DDIR=$CDIR
Expand All @@ -52,11 +54,12 @@ cat << EOF
Usage: `basename $0` [ OPTIONS ]
OPTIONS:
-k, --kernel <kernel version> Kernel version for the SmartNIC.
-sc, --signing-cert Secure upgrade signing certificate.
-sk, --signing-key Secure upgrade signing key.
-v, --verbose Run script in verbose mode. Will print out each step of execution.
-h, --help Display help
EOF
}

parse_args() {
while [[ $@ != "" ]]; do
case $1 in
Expand All @@ -72,6 +75,16 @@ parse_args() {
shift
KERNEL_VERSION=$1
;;
-sc|--signing-cert)
shift
echo "signing cert $1"
SIGNING_CERT="$1"
;;
-sk|--signing-key)
shift
echo "signing key $1"
SIGNING_KEY="$1"
;;
*)
usage
exit 1
Expand Down Expand Up @@ -146,7 +159,56 @@ generate_s2s_installer_image_bluefield()
# Replace variables in the sharch template
sed -i -e "s/%%IMAGE_SHA1%%/$sha1/" /sonic/$OUTPUT_ONIE_IMAGE
echo -n "."
tar_size="$(wc -c < "${sharch}")"
output_file="/sonic/$OUTPUT_ONIE_IMAGE"
sed -i -e "s|%%PAYLOAD_IMAGE_SIZE%%|${tar_size}|" ${output_file}
cat $sharch >> /sonic/$OUTPUT_ONIE_IMAGE
echo "secure upgrade flags: SECURE_UPGRADE_MODE = $SECURE_UPGRADE_MODE, \
SECURE_UPGRADE_DEV_SIGNING_KEY = $SIGNING_KEY, SECURE_UPGRADE_SIGNING_CERT = $SIGNING_CERT"
key_file=${SIGNING_KEY}
cert_file=${SIGNING_CERT}
if [ "$SECURE_UPGRADE_MODE" = "dev" -o "$SECURE_UPGRADE_MODE" = "prod" -o "$signing_keys_path" = "ok" ]; then
CMS_SIG="${tmp_dir}/signature.sig"
scripts_dir="/sonic/scripts"

echo "$0 $SECURE_UPGRADE_MODE signing - creating CMS signature for ${output_file}. Output file ${CMS_SIG}"

if [ "$SECURE_UPGRADE_MODE" = "dev" ]; then
if [[ -z "$key_file" ]] || [[ -z "$cert_file" ]]; then
echo "dev signing key and/or cert not defined. SECURE_UPGRADE_DEV_SIGNING_KEY: $key_file SECURE_UPGRADE_SIGNING_CERT: $cert_file"
clean_dir $tmp_dir 1
fi
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_dir $tmp_dir 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."
Expand Down Expand Up @@ -235,7 +297,7 @@ add_sonic_to_initramfs() {
# Add the logic to put second stage installer into bfb initramfs
mkdir -p debian

j2 ${SDIR}/install.sh.j2 -o ./debian/install.sh
j2 ${SDIR}/install.sh.j2 -o ./debian/install.sh -e SECURE_UPGRADE_MODE="$SECURE_UPGRADE_MODE"
chmod 0755 ./debian/install.sh

# Copy the INSTALLER payload
Expand Down Expand Up @@ -392,6 +454,8 @@ create_bfb_image() {
cp $TMFIFO_DRIVER .
cp $SDHCI_OF_DWCMSHC_DRIVER .
cp $WATCHDOG .
mkdir -p ./secure-boot
cp -r $CDIR/$FILESYSTEM_ROOT/boot/* ./secure-boot

mkdir -p ./lib/firmware/mellanox/boot/
cp /lib/firmware/mellanox/boot/default.bfb ./lib/firmware/mellanox/boot/default.bfb
Expand Down Expand Up @@ -439,7 +503,9 @@ create_pxe_archive(){
pushd $arxiv_wdir

cp /usr/lib/grub/arm64-efi/monolithic/$GRUB_AA64 .

cp $CDIR/$FILESYSTEM_ROOT/boot/shimaa64.efi .
cp $CDIR/$FILESYSTEM_ROOT/boot/mmaa64.efi .
cp $CDIR/$FILESYSTEM_ROOT/boot/grubaa64.efi .
cp $WDIR/vmlinuz Image
cp $WDIR/dump-initramfs-v0 initramfs

Expand All @@ -455,20 +521,16 @@ create_pxe_archive(){
main() {
echo $@
parse_args $@

. $CDIR/onie-image-arm64.conf

# Export ENV Variables for j2cli
CHROOT_DIR=$CDIR/$FILESYSTEM_ROOT
if [[ ! -d "$CHROOT_DIR" ]]; then
echo "[create_sonic_image] Error! Path to CHROOT not found"
exit 1
fi

export GRUB_CFG=$(cat /sonic/installer/bluefield/sonic-grub.cfg)
export IMAGE_VERSION=$(cat $CHROOT_DIR/etc/sonic/sonic_version.yml | grep "build_version" | sed -e "s/build_version: //g;s/'//g")
export BF2_BOOT_ARGS BF3_BOOT_ARGS BF2_GRUB_CFG BF3_GRUB_CFG ONIE_INSTALLER_PAYLOAD FILESYSTEM_DOCKERFS DOCKERFS_DIR FILESYSTEM_SQUASHFS KERNEL_VERSION

export BF2_BOOT_ARGS BF3_BOOT_ARGS BF2_GRUB_CFG BF3_GRUB_CFG ONIE_INSTALLER_PAYLOAD FILESYSTEM_DOCKERFS DOCKERFS_DIR FILESYSTEM_SQUASHFS KERNEL_VERSION SECURE_UPGRADE_MODE SIGNING_KEY SIGNING_CERT
if [[ $IMAGE_TYPE == bin ]]; then
# bluefield Doesn't have ONiE Support yet and this *.bin image generated can only be used for SONiC-SONiC installation
echo "Build SONiC to SONiC installer for Bluefield"
Expand Down
45 changes: 42 additions & 3 deletions installer/bluefield/install.sh.j2
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,34 @@ EOF
chmod a+r /mnt/machine.conf

sync
{% if SECURE_UPGRADE_MODE in ['dev', 'prod'] %}
demo_volume_label="SONiC-OS"
log "creating demo_volume_label=$demo_volume_label dir under EFI partition to include all boot related modules"
mkdir -p /mnt/boot/efi/EFI/$demo_volume_label

if [ ! -f /secure-boot/mmaa64.efi ]; then
echo "ERROR: /secure-boot/mmaa64.efi file does not exist"
exit 1
fi

log "Installing GRUB"
if [ ! -f /secure-boot/shimaa64.efi ]; then
echo "ERROR: /secure-boot/shimaa64.efi file does not exist"
exit 1
fi

if [ ! -f /secure-boot/grubaa64.efi ]; then
echo "ERROR: /secure-boot/grubaa64.efi file does not exist"
exit 1
fi

log "copying signed shim, mm, grub, grub.cfg from /secure-boot to /boot/efi/EFI/$demo_volume_label directory"
MNT_DIR="/mnt/boot/efi/EFI/$demo_volume_label"
cp /secure-boot/shimaa64.efi $MNT_DIR
cp /secure-boot/grubaa64.efi $MNT_DIR
cp /secure-boot/mmaa64.efi $MNT_DIR
{% else %}
log "Installing GRUB"
{% endif %}
# Create a minimal grub.cfg that allows for:
# - configure the serial console
# - allows for grub-reboot to work
Expand Down Expand Up @@ -248,9 +273,13 @@ cat <<EOF >> $grub_cfg
EOF

# Copy the grub.cfg onto the boot-directory as specified in the grub-install
ex mkdir -p /mnt/grub
{% if SECURE_UPGRADE_MODE in ['dev', 'prod'] %}
ex cp $grub_cfg /mnt/boot/efi/EFI/$demo_volume_label/grub.cfg
{% else %}
ex mkdir -p /mnt/grub
ex cp $grub_cfg /mnt/grub/grub.cfg

{% endif %}
sync

log "GRUB CFG Updated"
Expand Down Expand Up @@ -303,7 +332,17 @@ else
fi
ex efibootmgr -c -d "$device" -p 1 -L $device_label -l "\EFI\\$device_label\grubaa64.efi"
fi

{% if SECURE_UPGRADE_MODE in ['dev', 'prod'] %}
uefi_part=1
ex efibootmgr --create \
--label "$demo_volume_label" \
--disk "$device" --part $uefi_part \
--loader "\EFI\$demo_volume_label\shimaa64.efi" || {
echo "ERROR: efibootmgr failed to create new boot variable on: $device"
exit 1
}
echo "uefi_shim: Secure Boot components installed successfully"
{% endif %}
BFCFG=`which bfcfg 2> /dev/null`
if [ -n "$BFCFG" ]; then
# Create PXE boot entries
Expand Down
5 changes: 3 additions & 2 deletions installer/sharch_body.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +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%%

if [ "$sha1" != "$payload_sha1" ] ; then
Expand Down Expand Up @@ -45,7 +46,7 @@ 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
Expand Down
55 changes: 54 additions & 1 deletion onie-mk-demo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -61,6 +64,13 @@ tmp_dir=
clean_up()
{
rm -rf $tmp_dir
if [ -n "$2" ]; then
rm -rf "$2"
if [ -n "$3" ];then
rm -rf "$3"
fi
echo "Error: CMS signature not created - exiting without signing"
fi
exit $1
}

Expand Down Expand Up @@ -100,7 +110,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
Expand Down Expand Up @@ -130,7 +140,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}."
. ${scripts_dir}/sign_image_dev.sh || {
echo "dev sign script ${scripts_dir}/sign_image_dev.sh not found"
clean_up 1 ${output_file}
}
sign_image_dev ${cert_file} ${key_file} ${output_file} ${CMS_SIG} || {
echo "CMS sign error $?"
clean_up 1 ${CMS_SIG} ${output_file}
}
else # "$SECURE_UPGRADE_MODE" has to be equal to "prod"
. ${scripts_dir}/sign_image_${machine}.sh || {
echo "prod sign script ${scripts_dir}/sign_image_${machine}.sh not found"
clean_up 1 ${output_file}
}
sign_image_prod ${output_file} ${CMS_SIG} ${SECURE_UPGRADE_MODE} || {
echo "CMS sign error $?"
clean_up 1 ${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."

Expand Down
11 changes: 11 additions & 0 deletions scripts/sign_image_dev.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit d914780

Please sign in to comment.