diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index 7712141c36a..01061943269 100755 --- a/build_library/build_image_util.sh +++ b/build_library/build_image_util.sh @@ -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}) @@ -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 diff --git a/build_library/grub_install.sh b/build_library/grub_install.sh index 052739b1cb6..53427c67013 100755 --- a/build_library/grub_install.sh +++ b/build_library/grub_install.sh @@ -35,6 +35,7 @@ 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}" @@ -42,29 +43,30 @@ 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}" ;; @@ -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}" @@ -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 @@ -163,7 +166,7 @@ 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}" \ @@ -171,7 +174,7 @@ sudo grub-mkimage \ --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 @@ -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 diff --git a/build_library/sbsign_util.sh b/build_library/sbsign_util.sh new file mode 100644 index 00000000000..6352f9efd8c --- /dev/null +++ b/build_library/sbsign_util.sh @@ -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}" \ + "${@}" +}