Skip to content

Commit

Permalink
[secure boot]Add Secure Boot Feature
Browse files Browse the repository at this point in the history
  • Loading branch information
davidpil2002 committed Nov 13, 2022
1 parent 109020c commit 5cc164f
Show file tree
Hide file tree
Showing 10 changed files with 621 additions and 5 deletions.
3 changes: 3 additions & 0 deletions Makefile.work
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,9 @@ SONIC_BUILD_INSTRUCTION := $(MAKE) \
BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \
SONIC_ENABLE_IMAGE_SIGNATURE=$(ENABLE_IMAGE_SIGNATURE) \
SONIC_ENABLE_SECUREBOOT_SIGNATURE=$(SONIC_ENABLE_SECUREBOOT_SIGNATURE) \
SECURE_UPGRADE_MODE=$(SECURE_UPGRADE_MODE) \
SECURE_UPGRADE_DEV_SIGNING_KEY=$(SECURE_UPGRADE_DEV_SIGNING_KEY) \
SECURE_UPGRADE_DEV_SIGNING_CERT=$(SECURE_UPGRADE_DEV_SIGNING_CERT) \
SONIC_DEFAULT_CONTAINER_REGISTRY=$(DEFAULT_CONTAINER_REGISTRY) \
ENABLE_HOST_SERVICE_ON_START=$(ENABLE_HOST_SERVICE_ON_START) \
SLAVE_DIR=$(SLAVE_DIR) \
Expand Down
53 changes: 52 additions & 1 deletion build_debian.sh
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ if [[ $CONFIGURED_ARCH == amd64 ]]; then
fi

## Sign the Linux kernel
if [ "$SONIC_ENABLE_SECUREBOOT_SIGNATURE" = "y" ]; then
# note: when flag SONIC_ENABLE_SECUREBOOT_SIGNATURE is enabled the Secure Upgrade flags should be disabled (no_sign) to avoid conflict between the features.
if [ "$SONIC_ENABLE_SECUREBOOT_SIGNATURE" = "y" ] && [ "$SECURE_UPGRADE_MODE" != 'dev' ] && [ "$SECURE_UPGRADE_MODE" != "prod" ]; then
if [ ! -f $SIGNING_KEY ]; then
echo "Error: SONiC linux kernel signing key missing"
exit 1
Expand Down Expand Up @@ -622,6 +623,56 @@ then

fi

# #################
# secure boot
# #################
if [[ $SECURE_UPGRADE_MODE == 'dev' || $SECURE_UPGRADE_MODE == "prod" && $SONIC_ENABLE_SECUREBOOT_SIGNATURE != 'y' ]]; then
# note: SONIC_ENABLE_SECUREBOOT_SIGNATURE is a feature that signing just kernel,
# SECURE_UPGRADE_MODE is signing all the boot component including kernel.
# its required to do not enable both features together to avoid conflicts.
echo "Secure Boot support build stage: Starting .."

# debian secure boot dependecies
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \
shim-unsigned \
grub-efi

if [ ! -f $SECURE_UPGRADE_DEV_SIGNING_CERT ]; then
echo "Error: SONiC SECURE_UPGRADE_DEV_SIGNING_CERT=$SECURE_UPGRADE_DEV_SIGNING_CERT key missing"
exit 1
fi

if [[ $SECURE_UPGRADE_MODE == 'dev' ]]; then
# development signing & verification

if [ ! -f $SECURE_UPGRADE_DEV_SIGNING_KEY ]; then
echo "Error: SONiC SECURE_UPGRADE_DEV_SIGNING_KEY=$SECURE_UPGRADE_DEV_SIGNING_KEY key missing"
exit 1
fi

sudo bash scripts/signing_secure_boot_dev.sh $CONFIGURED_ARCH \
$FILESYSTEM_ROOT \
$LINUX_KERNEL_VERSION \
$SECURE_UPGRADE_DEV_SIGNING_CERT \
$SECURE_UPGRADE_DEV_SIGNING_KEY
elif [[ $SECURE_UPGRADE_MODE == "prod" ]]; then
# Here Vendor signing should be implemented
OUTPUT_SEC_BOOT_DIR=$FILESYSTEM_ROOT/boot
sudo bash scripts/signing_secure_boot_prod.sh $CONFIGURED_ARCH $FILESYSTEM_ROOT $LINUX_KERNEL_VERSION $OUTPUT_SEC_BOOT_DIR

# verifying all EFI files and kernel modules in $OUTPUT_SEC_BOOT_DIR
bash scripts/secure_boot_signature_verification.sh -e $OUTPUT_SEC_BOOT_DIR \
-c $SECURE_UPGRADE_DEV_SIGNING_CERT \
-k $FILESYSTEM_ROOT

# verifying vmlinuz file.
bash scripts/secure_boot_signature_verification.sh -e $FILESYSTEM_ROOT/boot/vmlinuz-${LINUX_KERNEL_VERSION}-${CONFIGURED_ARCH} \
-c $SECURE_UPGRADE_DEV_SIGNING_CERT \
-k $FILESYSTEM_ROOT
fi
echo "Secure Boot support build stage: END."
fi

## Update initramfs
sudo chroot $FILESYSTEM_ROOT update-initramfs -u
## Convert initrd image to u-boot format
Expand Down
4 changes: 4 additions & 0 deletions files/build_templates/sonic_debian_extension.j2
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ fi
# Update apt's snapshot of its repos
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get update

# Install efitools to support secure upgrade
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install efitools
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install mokutil

# Apply environtment configuration files
sudo cp $IMAGE_CONFIGS/environment/environment $FILESYSTEM_ROOT/etc/
sudo cp $IMAGE_CONFIGS/environment/motd $FILESYSTEM_ROOT/etc/
Expand Down
111 changes: 107 additions & 4 deletions installer/default_platform.conf
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,78 @@ demo_install_uefi_grub()
}
# Install UEFI BIOS SHIM for DEMO OS
demo_install_uefi_shim()
{
echo "demo_install_uefi_shim(): Installing Secure Boot components"
local demo_mnt="$1"
local blk_dev="$2"
# make sure /boot/efi is mounted
if ! mount | grep -q "/boot/efi"; then
mount /boot/efi
fi
# Look for the EFI system partition UUID on the same block device as
# the ONIE-BOOT partition.
local uefi_part=0
for p in $(seq 8) ; do
if sgdisk -i $p $blk_dev | grep -q C12A7328-F81F-11D2-BA4B-00A0C93EC93B ; then
uefi_part=$p
break
fi
done
[ $uefi_part -eq 0 ] && {
echo "ERROR: Unable to determine UEFI system partition"
exit 1
}
echo "creating demo_volume_label=$demo_volume_label in dir: /boot/efi/EFI/ ."
mkdir -p /boot/efi/EFI/$demo_volume_label
if [ ! -f $demo_mnt/$image_dir/boot/mmx64.efi ]; then
echo "ERROR: $demo_mnt/$image_dir/boot/mmx64.efi file does not exist"
exit 1
fi
if [ ! -f $demo_mnt/$image_dir/boot/shimx64.efi ]; then
echo "ERROR: $demo_mnt/$image_dir/boot/shimx64.efi file does not exist"
exit 1
fi
if [ ! -f $demo_mnt/$image_dir/boot/grubx64.efi ]; then
echo "ERROR: $demo_mnt/$image_dir/boot/grubx64.efi file does not exist"
exit 1
fi
if [ ! -f $demo_mnt/$image_dir/boot/grub.cfg ]; then
echo "ERROR: cp $demo_mnt/$image_dir/boot/grub.cfg file does not exist"
exit 1
fi
echo "copying signed shim, mm, grub, grub.cfg from $demo_mnt/$image_dir/boot/ to /boot/efi/EFI/$demo_volume_label directory"
cp $demo_mnt/$image_dir/boot/mmx64.efi /boot/efi/EFI/$demo_volume_label/mmx64.efi
cp $demo_mnt/$image_dir/boot/shimx64.efi /boot/efi/EFI/$demo_volume_label/shimx64.efi
cp $demo_mnt/$image_dir/boot/grubx64.efi /boot/efi/EFI/$demo_volume_label/grubx64.efi
# cp first grub.cfg as entrypoint to call real grub.cfg in nvos label
mkdir -p /boot/efi/EFI/debian/
echo "cp $demo_mnt/$image_dir/boot/grub.cfg /boot/efi/EFI/debian/"
cp $demo_mnt/$image_dir/boot/grub.cfg /boot/efi/EFI/debian/
# Configure EFI NVRAM Boot variables. --create also sets the
# new boot number as active.
efibootmgr --quiet --create \
--label "$demo_volume_label" \
--disk $blk_dev --part $uefi_part \
--loader "/EFI/$demo_volume_label/shimx64.efi" || {
echo "ERROR: efibootmgr failed to create new boot variable on: $blk_dev"
exit 1
}
echo "demo_install_uefi_shim(): Secure Boot components installed successfully"
}
bootloader_menu_config()
{
Expand All @@ -370,7 +442,15 @@ bootloader_menu_config()
mv $onie_initrd_tmp/tmp/onie-support*.tar.bz2 $demo_mnt/$image_dir/
if [ "$firmware" = "uefi" ] ; then
demo_install_uefi_grub "$demo_mnt" "$blk_dev"
secure_boot_state=$(mokutil --sb-state)
echo secure_boot_state=$secure_boot_state
if [ "$secure_boot_state" = "SecureBoot enabled" ]; then
echo "UEFI Secure Boot is enabled"
demo_install_uefi_shim "$demo_mnt" "$blk_dev"
else
echo "UEFI Secure Boot is disabled"
demo_install_uefi_grub "$demo_mnt" "$blk_dev"
fi
else
demo_install_grub "$demo_mnt" "$blk_dev"
fi
Expand Down Expand Up @@ -405,7 +485,8 @@ bootloader_menu_config()
fi
DEFAULT_GRUB_SERIAL_COMMAND="serial --port=${CONSOLE_PORT} --speed=${CONSOLE_SPEED} --word=8 --parity=no --stop=1"
DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS${CONSOLE_DEV},${CONSOLE_SPEED}n8 quiet $CSTATES"
# DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS${CONSOLE_DEV},${CONSOLE_SPEED}n8 quiet $CSTATES"
DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS${CONSOLE_DEV},${CONSOLE_SPEED}n8 loglevel=7 systemd.log_level=debug $CSTATES"
GRUB_SERIAL_COMMAND=${GRUB_SERIAL_COMMAND:-"$DEFAULT_GRUB_SERIAL_COMMAND"}
GRUB_CMDLINE_LINUX=${GRUB_CMDLINE_LINUX:-"$DEFAULT_GRUB_CMDLINE_LINUX"}
export GRUB_SERIAL_COMMAND
Expand Down Expand Up @@ -472,6 +553,17 @@ EOF
# Add extra linux command line
echo "EXTRA_CMDLINE_LINUX=$extra_cmdline_linux"
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX $extra_cmdline_linux"
GRUB_CFG_LINUX_CMD=""
GRUB_CFG_INITRD_CMD=""
if [ "$firmware" = "uefi" ] ; then
# grub.cfg when BIOS is UEFI and support Secure Boot
GRUB_CFG_LINUX_CMD="linuxefi"
GRUB_CFG_INITRD_CMD="initrdefi"
else
# grub.cfg when BIOS is Legacy
GRUB_CFG_LINUX_CMD="linux"
GRUB_CFG_INITRD_CMD="initrd"
fi
cat <<EOF >> $grub_cfg
menuentry '$demo_grub_entry' {
Expand All @@ -481,13 +573,13 @@ menuentry '$demo_grub_entry' {
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
linux /$image_dir/boot/vmlinuz-5.10.0-12-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \
$GRUB_CFG_LINUX_CMD /$image_dir/boot/vmlinuz-5.10.0-12-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \
net.ifnames=0 biosdevname=0 \
loop=$image_dir/$FILESYSTEM_SQUASHFS loopfstype=squashfs \
systemd.unified_cgroup_hierarchy=0 \
apparmor=1 security=apparmor varlog_size=$VAR_LOG_SIZE usbcore.autosuspend=-1 $ONIE_PLATFORM_EXTRA_CMDLINE_LINUX
echo 'Loading $demo_volume_label $demo_type initial ramdisk ...'
initrd /$image_dir/boot/initrd.img-5.10.0-12-2-amd64
$GRUB_CFG_INITRD_CMD /$image_dir/boot/initrd.img-5.10.0-12-2-amd64
}
EOF
Expand All @@ -510,6 +602,17 @@ EOF
cp $grub_cfg $onie_initrd_tmp/$demo_mnt/grub/grub.cfg
fi
if [ "$secure_boot_state" = "SecureBoot enabled" ]; then
# Secure Boot grub.cfg support
# Saving grub_cfg in the same place where is grubx64.efi,
# this grub_cfg file will be called by first grub.cfg file from: /boot/efi/EFI/debian/grub.cfg
if [ -f $NVOS_BOOT_DIR/grub.cfg ]; then
rm $NVOS_BOOT_DIR/grub.cfg
fi
cp $grub_cfg $NVOS_BOOT_DIR/grub.cfg
fi
cd /
echo "Installed SONiC base image $demo_volume_label successfully"
Expand Down
8 changes: 8 additions & 0 deletions rules/config
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,14 @@ SONIC_ENABLE_IMAGE_SIGNATURE ?= n
# The absolute path should be provided.
SONIC_ENABLE_SECUREBOOT_SIGNATURE ?= n

# Full Secure Boot feature flags.
# SECURE_UPGRADE_DEV_SIGNING_KEY - path to development signing key, used for image signing during build
# SECURE_UPGRADE_DEV_SIGNING_CERT - path to development signing certificate, used for image signing during build
# SECURE_UPGRADE_MODE - enum value for secure upgrade mode, valid options are "dev", "prod" and "no_sign"
SECURE_UPGRADE_DEV_SIGNING_KEY = /sonic/files/nv_onyx_key.pem
SECURE_UPGRADE_DEV_SIGNING_CERT = /sonic/files/nv_onyx_key_certificate.pem
SECURE_UPGRADE_MODE = "no_sign"

# PACKAGE_URL_PREFIX - the package url prefix
PACKAGE_URL_PREFIX ?= https://packages.trafficmanager.net/public/packages

Expand Down
60 changes: 60 additions & 0 deletions scripts/efi-sign.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh

set -e

#
# Sign efi file with secret key and certificate
# - shim
# - grub
# - vmlinuz
#
usage() {
cat <<EOF
$0: Usage
$0 <PRIVATE_KEY_PEM> <CERT_PEM> <EFI_FILE> <EFI_FILE_SIGNED>
Usage example: efi-sign.sh priv-key.pem pub-key.pem shimx64.efi shimx64-signed.efi
EOF
}

if [ "$1" = "-h" -o "$1" = "--help" ]; then
usage
fi

PRIVATE_KEY_PEM="$1"
CERT_PEM="$2"
EFI_FILE="$3"
EFI_FILE_SIGNED="$4"


[ -f "$PRIVATE_KEY_PEM" ] || {
echo "Error: PRIVATE_KEY_PEM file does not exist: $PRIVATE_KEY_PEM"
usage
exit 1
}

[ -f "$CERT_PEM" ] || {
echo "Error: CERT_PEM file does not exist: $CERT_PEM"
usage
exit 1
}

[ -f "$EFI_FILE" ] || {
echo "Error: File for signing does not exist: $EFI_FILE"
usage
exit 1
}

if [ -z ${EFI_FILE_SIGNED} ]; then
echo "ERROR: no arg named <EFI_FILE_SIGNED> supplied"
usage
exit 1
fi

echo "$0 signing $EFI_FILE with ${PRIVATE_KEY_PEM}, ${CERT_PEM} to create $EFI_FILE_SIGNED"
sbsign --key ${PRIVATE_KEY_PEM} --cert ${CERT_PEM} \
--output ${EFI_FILE_SIGNED} ${EFI_FILE} || {
echo "EFI sign error"
exit 1
}
Loading

0 comments on commit 5cc164f

Please sign in to comment.