Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Makefile.work
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,23 @@ 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_DST)
endif

ifneq ($(SONIC_DPKG_CACHE_SOURCE),)
DOCKER_RUN += -v "$(SONIC_DPKG_CACHE_SOURCE):/dpkg_cache:rw"
endif
Expand Down Expand Up @@ -390,6 +407,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
109 changes: 106 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,22 @@ 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"
if command -v mokutil >/dev/null 2>&1; then
# The command exists, so execute it
secure_boot_state=$(mokutil --sb-state)
else
# The command doesn't exist, so output an error message
echo "mokutil not found, to enable Secure Boot required to update ONIE to at least version 2021.11"
secure_boot_state="SecureBoot disabled"
fi
echo secure_boot_state=$secure_boot_state
if [ "$secure_boot_state" = "SecureBoot enabled" ]; then
echo "UEFI Secure Boot is enabled - Installing shim bootloader"
demo_install_uefi_shim "$demo_mnt" "$blk_dev"
else
echo "UEFI Secure Boot is disabled - Installing regular grub bootloader"
demo_install_uefi_grub "$demo_mnt" "$blk_dev"
fi
else
demo_install_grub "$demo_mnt" "$blk_dev"
fi
Expand Down Expand Up @@ -669,10 +737,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 +774,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 +803,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