Skip to content

Commit

Permalink
Refactor SB signing code and sign official builds with Azure Key Vault
Browse files Browse the repository at this point in the history
Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
  • Loading branch information
chewi committed Nov 6, 2024
1 parent cdc71bc commit 08cb93c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 80 deletions.
10 changes: 3 additions & 7 deletions build_library/build_image_util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ BUILD_DIR="${FLAGS_output_root}/${BOARD}/${IMAGE_SUBDIR}"
OUTSIDE_OUTPUT_DIR="../build/images/${BOARD}/${IMAGE_SUBDIR}"

source "${BUILD_LIBRARY_DIR}/reports_util.sh" || exit 1
source "${BUILD_LIBRARY_DIR}/sbsign_util.sh" || exit 1

set_build_symlinks() {
local build=$(basename ${BUILD_DIR})
Expand Down Expand Up @@ -826,13 +827,8 @@ EOF
fi

# Sign the kernel after /usr is in a consistent state and verity is calculated
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
sudo sbsign --key /usr/share/sb_keys/shim.key \
--cert /usr/share/sb_keys/shim.pem \
"${root_fs_dir}/boot/flatcar/vmlinuz-a"
sudo mv "${root_fs_dir}/boot/flatcar/vmlinuz-a.signed" \
"${root_fs_dir}/boot/flatcar/vmlinuz-a"
fi
do_sbsign --output "${root_fs_dir}/boot/flatcar/vmlinuz-a"{,}
cleanup_sbsign_certs

if [[ -n "${image_kernel}" ]]; then
# copying kernel from vfat so ignore the permissions
Expand Down
125 changes: 52 additions & 73 deletions build_library/grub_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,38 @@ switch_to_strict_mode
# must be sourced after flags are parsed.
. "${BUILD_LIBRARY_DIR}/toolchain_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/sbsign_util.sh" || exit 1

# Our GRUB lives under flatcar/grub so new pygrub versions cannot find grub.cfg
GRUB_DIR="flatcar/grub/${FLAGS_target}"

# Modules required to boot a standard CoreOS configuration
CORE_MODULES=( normal search test fat part_gpt search_fs_uuid gzio search_part_label terminal gptprio configfile memdisk tar echo read btrfs )

# Name of the core image, depends on target
CORE_NAME=

SBAT_ARG=()

case "${FLAGS_target}" in
i386-pc)
CORE_MODULES+=( biosdisk serial )
CORE_NAME="core.img"
;;
x86_64-efi)
CORE_MODULES+=( serial linux efi_gop efinet pgp http tftp tpm )
CORE_NAME="core.efi"
SBAT_ARG=( --sbat "${BOARD_ROOT}/usr/share/grub/sbat.csv" )
;;
x86_64-xen)
CORE_NAME="core.elf"
EFI_ARCH="x64"
;;
arm64-efi)
EFI_ARCH="aa64"
;;
esac

case "${FLAGS_target}" in
x86_64-efi|arm64-efi)
GRUB_IMAGE="EFI/boot/grub${EFI_ARCH}.efi"
CORE_MODULES+=( serial linux efi_gop efinet pgp http tftp tpm )
CORE_NAME="core.efi"
SBAT_ARG=( --sbat "${BOARD_ROOT}/usr/share/grub/sbat.csv" )
;;
i386-pc)
GRUB_IMAGE="${GRUB_DIR}/core.img"
CORE_MODULES+=( biosdisk serial )
;;
x86_64-xen)
GRUB_IMAGE="xen/pvboot-x86_64.elf"
;;
*)
die_notrace "Unknown GRUB target ${FLAGS_target}"
;;
Expand All @@ -88,6 +90,7 @@ ESP_DIR=
LOOP_DEV=

cleanup() {
cleanup_sbsign_certs
if [[ -d "${ESP_DIR}" ]]; then
if mountpoint -q "${ESP_DIR}"; then
sudo umount "${ESP_DIR}"
Expand Down Expand Up @@ -121,7 +124,7 @@ done
if [[ -z ${MOUNTED} ]]; then
failboat "${LOOP_DEV}p1 where art thou? udev has forsaken us!"
fi
sudo mkdir -p "${ESP_DIR}/${GRUB_DIR}"
sudo mkdir -p "${ESP_DIR}/${GRUB_DIR}" "${ESP_DIR}/${GRUB_IMAGE%/*}"

info "Compressing modules in ${GRUB_DIR}"
for file in "${GRUB_SRC}"/*{.lst,.mod}; do
Expand Down Expand Up @@ -163,15 +166,15 @@ if [[ ! -f "${ESP_DIR}/flatcar/grub/grub.cfg.tar" ]]; then
-C "${GRUB_TEMP_DIR}" "grub.cfg"
fi

info "Generating ${GRUB_DIR}/${CORE_NAME}"
info "Generating ${GRUB_IMAGE}"
sudo grub-mkimage \
--compression=auto \
--format "${FLAGS_target}" \
--directory "${GRUB_SRC}" \
--config "${ESP_DIR}/${GRUB_DIR}/load.cfg" \
--memdisk "${ESP_DIR}/flatcar/grub/grub.cfg.tar" \
"${SBAT_ARG[@]}" \
--output "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
--output "${ESP_DIR}/${GRUB_IMAGE}" \
"${CORE_MODULES[@]}"

for mod in "${CORE_MODULES[@]}"; do
Expand All @@ -180,77 +183,53 @@ done

# Now target specific steps to make the system bootable
case "${FLAGS_target}" in
i386-pc)
info "Installing MBR and the BIOS Boot partition."
sudo cp "${GRUB_SRC}/boot.img" "${ESP_DIR}/${GRUB_DIR}"
sudo grub-bios-setup --device-map=/dev/null \
--directory="${ESP_DIR}/${GRUB_DIR}" "${LOOP_DEV}"
# boot.img gets manipulated by grub-bios-setup so it alone isn't
# sufficient to restore the MBR boot code if it gets corrupted.
sudo dd bs=448 count=1 status=none if="${LOOP_DEV}" \
of="${ESP_DIR}/${GRUB_DIR}/mbr.bin"
;;
x86_64-efi)
info "Installing default x86_64 UEFI bootloader."
sudo mkdir -p "${ESP_DIR}/EFI/boot"
# Use the test keys for signing unofficial builds
if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
# Sign the GRUB with the shim-embedded key
sudo sbsign --key /usr/share/sb_keys/shim.key \
--cert /usr/share/sb_keys/shim.pem \
"${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}"
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}.signed" \
"${ESP_DIR}/EFI/boot/grubx64.efi"
sudo rm "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}"
# Sign the mokmanager(mm) with the shim-embedded key
sudo sbsign --key /usr/share/sb_keys/shim.key \
--cert /usr/share/sb_keys/shim.pem \
"/usr/lib/shim/mmx64.efi"
sudo cp "/usr/lib/shim/mmx64.efi.signed" \
"${ESP_DIR}/EFI/boot/mmx64.efi"
x86_64-efi|arm64-efi)
info "Installing default ${FLAGS_target} UEFI bootloader."

sudo sbsign --key /usr/share/sb_keys/DB.key \
# Sign GRUB and mokmanager(mm) with the shim-embedded key.
do_sbsign --output "${ESP_DIR}/${GRUB_IMAGE}"{,}
do_sbsign --output "${ESP_DIR}/EFI/boot/mm${EFI_ARCH}.efi" \
"${BOARD_ROOT}/usr/lib/shim/mm${EFI_ARCH}.efi"

if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
# Unofficial build: Sign shim with our development key.
sudo sbsign \
--key /usr/share/sb_keys/DB.key \
--cert /usr/share/sb_keys/DB.crt \
--output "${ESP_DIR}/EFI/boot/bootx64.efi" \
"/usr/lib/shim/shim.efi"
--output "${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi" \
"${BOARD_ROOT}/usr/lib/shim/shim${EFI_ARCH}.efi"
else
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${ESP_DIR}/EFI/boot/grubx64.efi"
sudo cp "/usr/lib/shim/shim.efi" \
"${ESP_DIR}/EFI/boot/bootx64.efi"
sudo cp "/usr/lib/shim/mmx64.efi" \
"${ESP_DIR}/EFI/boot/mmx64.efi"
# Official build: Copy our pre-signed shim.
sudo cp "${BOARD_ROOT}/usr/lib/shim/shim${EFI_ARCH}.efi.signed" \
"${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi"
fi

# copying from vfat so ignore permissions
if [[ -n "${FLAGS_copy_efi_grub}" ]]; then
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/grubx64.efi" \
if [[ -n ${FLAGS_copy_efi_grub} ]]; then
cp --no-preserve=mode "${ESP_DIR}/${GRUB_IMAGE}" \
"${FLAGS_copy_efi_grub}"
fi
if [[ -n "${FLAGS_copy_shim}" ]]; then
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/bootx64.efi" \
if [[ -n ${FLAGS_copy_shim} ]]; then
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/boot${EFI_ARCH}.efi" \
"${FLAGS_copy_shim}"
fi
;;
i386-pc)
info "Installing MBR and the BIOS Boot partition."
sudo cp "${GRUB_SRC}/boot.img" "${ESP_DIR}/${GRUB_DIR}"
sudo grub-bios-setup --device-map=/dev/null \
--directory="${ESP_DIR}/${GRUB_DIR}" "${LOOP_DEV}"
# boot.img gets manipulated by grub-bios-setup so it alone isn't
# sufficient to restore the MBR boot code if it gets corrupted.
sudo dd bs=448 count=1 status=none if="${LOOP_DEV}" \
of="${ESP_DIR}/${GRUB_DIR}/mbr.bin"
;;
x86_64-xen)
info "Installing default x86_64 Xen bootloader."
sudo mkdir -p "${ESP_DIR}/xen" "${ESP_DIR}/boot/grub"
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${ESP_DIR}/xen/pvboot-x86_64.elf"
sudo mkdir -p "${ESP_DIR}/boot/grub"
sudo cp "${BUILD_LIBRARY_DIR}/menu.lst" \
"${ESP_DIR}/boot/grub/menu.lst"
;;
arm64-efi)
info "Installing default arm64 UEFI bootloader."
sudo mkdir -p "${ESP_DIR}/EFI/boot"
#FIXME(andrejro): shim not ported to aarch64
sudo mv "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
"${ESP_DIR}/EFI/boot/bootaa64.efi"
if [[ -n "${FLAGS_copy_efi_grub}" ]]; then
# copying from vfat so ignore permissions
cp --no-preserve=mode "${ESP_DIR}/EFI/boot/bootaa64.efi" \
"${FLAGS_copy_efi_grub}"
fi
;;
esac

cleanup
Expand Down
55 changes: 55 additions & 0 deletions build_library/sbsign_util.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright (c) 2024 The Flatcar Maintainers.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

if [[ ${COREOS_OFFICIAL:-0} -ne 1 ]]; then
SBSIGN_KEY="/usr/share/sb_keys/shim.key"
SBSIGN_CERT="/usr/share/sb_keys/shim.pem"
else
SBSIGN_KEY="pkcs11:token=flatcar-dev-cert"
unset SBSIGN_CERT
fi

PKCS11_MODULE_PATH="/usr/$(get_sdk_libdir)/pkcs11/azure_kms_pkcs11.so"

PKCS11_ENV=(
AZURE_KEYVAULT_URL="https://chewi-test.vault.azure.net/"
PKCS11_MODULE_PATH="${PKCS11_MODULE_PATH}"
AWS_KMS_PKCS11_DEBUG=1
)

get_sbsign_cert() {
if [[ ${SBSIGN_KEY} != pkcs11:* || -s ${SBSIGN_CERT} ]]; then
return
fi

SBSIGN_CERT=$(mktemp -t signing-cert.XXXXXXXXXX.pem)
info "Fetching ${SBSIGN_KEY} from Azure"

# Needs Key Vault Reader role.
env "${PKCS11_ENV[@]}" p11-kit export-object \
--provider "${PKCS11_MODULE_PATH}" \
"${SBSIGN_KEY};type=cert" \
| tee "${SBSIGN_CERT}"
}

cleanup_sbsign_certs() {
if [[ ${SBSIGN_CERT-} = "${TMPDIR-/tmp}"/* ]]; then
rm -f -- "${SBSIGN_CERT}"
fi
}

do_sbsign() {
get_sbsign_cert
info "Signing ${@:$#} with ${SBSIGN_KEY}"

if [[ ${SBSIGN_KEY} == pkcs11:* ]]; then
set -- --engine pkcs11 "${@}"
fi

# Needs Key Vault Crypto User role.
sudo env "${PKCS11_ENV[@]}" sbsign \
--key "${SBSIGN_KEY}" \
--cert "${SBSIGN_CERT}" \
"${@}"
}

0 comments on commit 08cb93c

Please sign in to comment.