Skip to content

Commit

Permalink
backport: secureboot support
Browse files Browse the repository at this point in the history
   Backporting sonic-net#12692 PR on 202205 branch.

   The diffs of sonic-net#12692 does not cleanly gets apply.

   on 202205 branch. Hence the patch sonic-net#12692 slightly

   modified so that it can get applied on 202205 branch

   without functional break.

Signed-off-by: Sachin Naik <sachnaik@cisco.com>
  • Loading branch information
sacnaik committed Mar 15, 2023
1 parent a3ea2e7 commit 5574593
Show file tree
Hide file tree
Showing 12 changed files with 605 additions and 6 deletions.
22 changes: 22 additions & 0 deletions Makefile.work
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,24 @@ ifdef SONIC_BUILD_QUIETER
DOCKER_RUN += -e "SONIC_BUILD_QUIETER=$(SONIC_BUILD_QUIETER)"
endif

# Mount the Signing key and Certificate in the slave container
ifneq ($(SECURE_UPGRADE_DEV_SIGNING_KEY),)
DOCKER_RUN += -v $(SECURE_UPGRADE_DEV_SIGNING_KEY):$(SECURE_UPGRADE_DEV_SIGNING_KEY):ro
endif

ifneq ($(SECURE_UPGRADE_DEV_SIGNING_CERT),)
DOCKER_RUN += -v $(SECURE_UPGRADE_DEV_SIGNING_CERT):$(SECURE_UPGRADE_DEV_SIGNING_CERT):ro
endif

# Mount the Signing prod tool in the slave container
$(info "SECURE_UPGRADE_PROD_SIGNING_TOOL": "$(SECURE_UPGRADE_PROD_SIGNING_TOOL)")

ifneq ($(SECURE_UPGRADE_PROD_SIGNING_TOOL),)
SECURE_UPGRADE_PROD_SIGNING_TOOL_DST = /sonic/scripts/$(shell basename -- $(SECURE_UPGRADE_PROD_SIGNING_TOOL))
DOCKER_RUN += -v $(SECURE_UPGRADE_PROD_SIGNING_TOOL):$(SECURE_UPGRADE_PROD_SIGNING_TOOL_DST):ro
SECURE_UPGRADE_PROD_SIGNING_TOOL := $(SECURE_UPGRADE_PROD_SIGNING_TOOL_SOURCE)
endif

ifneq ($(SONIC_DPKG_CACHE_SOURCE),)
DOCKER_RUN += -v "$(SONIC_DPKG_CACHE_SOURCE):/dpkg_cache:rw"
endif
Expand Down Expand Up @@ -390,6 +408,10 @@ 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) \
SECURE_UPGRADE_PROD_SIGNING_TOOL=$(SECURE_UPGRADE_PROD_SIGNING_TOOL) \
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 @@ -154,7 +154,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 @@ -607,6 +608,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 ./scripts/signing_secure_boot_dev.sh -a $CONFIGURED_ARCH \
-r $FILESYSTEM_ROOT \
-l $LINUX_KERNEL_VERSION \
-c $SECURE_UPGRADE_DEV_SIGNING_CERT \
-p $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 $SECURE_UPGRADE_PROD_SIGNING_TOOL $CONFIGURED_ARCH $FILESYSTEM_ROOT $LINUX_KERNEL_VERSION $OUTPUT_SEC_BOOT_DIR

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

# verifying vmlinuz file.
sudo ./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
102 changes: 99 additions & 3 deletions installer/x86_64/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,59 @@ demo_install_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
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
# 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"
}
# Install UEFI BIOS GRUB for DEMO OS
demo_install_uefi_grub()
{
Expand Down Expand Up @@ -569,7 +622,15 @@ if [ "$install_env" = "onie" ]; then
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 @@ -669,10 +730,34 @@ else # install_env = "onie"
fi
fi
# Make a first grub config file that located in default debian path:/boot/efi/EFI/debian/
# this first grub.cfg will call the complete grub.cfg created below with sonic configuration
tmp_config=$(mktemp)
cat <<EOF > $tmp_config
search --no-floppy --label --set=root $demo_volume_label
set prefix=(\$root)'/grub'
configfile \$prefix/grub.cfg
EOF
# Copy first grub.cfg as entrypoint to default debian path where grubx64.efi expected it.
mkdir -p /boot/efi/EFI/debian/
echo "cp $tmp_config /boot/efi/EFI/debian/grub.cfg"
cp $tmp_config /boot/efi/EFI/debian/grub.cfg
# Add extra linux command line
extra_cmdline_linux=%%EXTRA_CMDLINE_LINUX%%
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 @@ -682,13 +767,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-18-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \
$GRUB_CFG_LINUX_CMD /$image_dir/boot/vmlinuz-5.10.0-18-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-18-2-amd64
$GRUB_CFG_INITRD_CMD /$image_dir/boot/initrd.img-5.10.0-18-2-amd64
}
EOF
Expand All @@ -711,6 +796,17 @@ else
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"
9 changes: 9 additions & 0 deletions rules/config
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ 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_PROD_SIGNING_TOOL - path to a vendor signing tool for production flow.
SECURE_UPGRADE_DEV_SIGNING_KEY = /sonic/your/private/key/path/private_key.pem
SECURE_UPGRADE_DEV_SIGNING_CERT = /sonic/your/certificate/path/cert.pem
SECURE_UPGRADE_MODE = "no_sign"
SECURE_UPGRADE_PROD_SIGNING_TOOL ?= none
# PACKAGE_URL_PREFIX - the package url prefix
PACKAGE_URL_PREFIX ?= https://packages.trafficmanager.net/public/packages

Expand Down
3 changes: 1 addition & 2 deletions rules/linux-kernel.dep
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ DEP_FILES := rules/linux-kernel.mk rules/linux-kernel.dep
SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files))

DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) \
$(KERNEL_PROCURE_METHOD) $(KERNEL_CACHE_PATH)
$(KERNEL_PROCURE_METHOD) $(KERNEL_CACHE_PATH) $(SECURE_UPGRADE_MODE) $(SECURE_UPGRADE_DEV_SIGNING_CERT)

$(LINUX_HEADERS_COMMON)_CACHE_MODE := GIT_CONTENT_SHA
$(LINUX_HEADERS_COMMON)_DEP_FLAGS := $(DEP_FLAGS)
$(LINUX_HEADERS_COMMON)_DEP_FILES := $(DEP_FILES)
$(LINUX_HEADERS_COMMON)_SMDEP_FILES := $(SMDEP_FILES)
$(LINUX_HEADERS_COMMON)_SMDEP_PATHS := $(SPATH)

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

set -e

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

while getopts 'p:c:e:s:hv' flag; do
case "${flag}" in
p) PRIVATE_KEY_PEM="${OPTARG}" ;;
c) CERT_PEM="${OPTARG}" ;;
e) EFI_FILE="${OPTARG}" ;;
s) EFI_FILE_SIGNED="${OPTARG}" ;;
v) VERBOSE='true' ;;
h) print_usage
exit 1 ;;
esac
done
if [ $OPTIND -eq 1 ]; then echo "no options were pass"; print_usage; exit 1 ;fi

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

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

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

if [ -z ${EFI_FILE_SIGNED} ]; then
echo "ERROR: no arg named <EFI_FILE_SIGNED> supplied"
print_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 5574593

Please sign in to comment.