new file mode 100644
@@ -0,0 +1,31 @@
+# Sign binaries for UEFI Secure Boot
+#
+# Usage in recipes:
+#
+# Set binary to sign per recipe:
+# SBSIGN_TARGET_BINARY = "${B}/binary_to_sign"
+#
+# Then call do_sbsign() in correct stage of the build
+# do_compile:append() {
+# do_sbsign
+# }
+
+DEPENDS += 'gen-sbkeys'
+DEPENDS += "sbsigntool-native"
+
+SBSIGN_KEY = "${SBSIGN_KEYS_DIR}/db.key"
+SBSIGN_CERT = "${SBSIGN_KEYS_DIR}/db.crt"
+SBSIGN_TARGET_BINARY ?= "binary_to_sign"
+
+# Not adding as task since recipes may need to sign binaries at different
+# stages. Instead they can call this function when needed by calling this function
+do_sbsign() {
+ bbnote "Signing ${PN} binary ${SBSIGN_TARGET_BINARY} with ${SBSIGN_KEY} and ${SBSIGN_CERT}"
+ ${STAGING_BINDIR_NATIVE}/sbsign \
+ --key "${SBSIGN_KEY}" \
+ --cert "${SBSIGN_CERT}" \
+ --output "${SBSIGN_TARGET_BINARY}.signed" \
+ "${SBSIGN_TARGET_BINARY}"
+ cp "${SBSIGN_TARGET_BINARY}" "${SBSIGN_TARGET_BINARY}.unsigned"
+ cp "${SBSIGN_TARGET_BINARY}.signed" "${SBSIGN_TARGET_BINARY}"
+}
new file mode 100644
@@ -0,0 +1,17 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://uefi-secureboot.cfg"
+
+inherit sbsign
+
+DEPENDS += 'python3-pyopenssl-native'
+
+do_compile:prepend() {
+ export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1
+
+ "${S}"/tools/efivar.py set -i "${S}"/ubootefi.var -n pk -d "${SBSIGN_KEYS_DIR}"/PK.esl -t file
+ "${S}"/tools/efivar.py set -i "${S}"/ubootefi.var -n kek -d "${SBSIGN_KEYS_DIR}"/KEK.esl -t file
+ "${S}"/tools/efivar.py set -i "${S}"/ubootefi.var -n db -d "${SBSIGN_KEYS_DIR}"/db.esl -t file
+ "${S}"/tools/efivar.py set -i "${S}"/ubootefi.var -n dbx -d "${SBSIGN_KEYS_DIR}"/dbx.esl -t file
+ "${S}"/tools/efivar.py print -i "${S}"/ubootefi.var
+}
new file mode 100644
@@ -0,0 +1,10 @@
+CONFIG_CMD_BOOTMENU=y
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="bootmenu"
+CONFIG_USE_PREBOOT=y
+CONFIG_EFI_VAR_BUF_SIZE=65536
+CONFIG_FIT_SIGNATURE=y
+CONFIG_EFI_SECURE_BOOT=y
+CONFIG_EFI_VARIABLES_PRESEED=y
+CONFIG_PREBOOT="setenv bootmenu_0 UEFI Boot Manager=bootefi bootmgr; setenv bootmenu_1 UEFI Maintenance Menu=eficonfig"
+CONFIG_PREBOOT_DEFINED=y
@@ -2,3 +2,5 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append:qemuarm64-secureboot = " file://qemuarm64.cfg"
SRC_URI:append:qemuarm-secureboot = " file://qemuarm.cfg"
+
+require ${@bb.utils.contains('MACHINE_FEATURES', 'uefi-secureboot', 'u-boot-uefi-secureboot.inc', '', d)}
new file mode 100644
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: MIT
+
+SUMMARY = "Generate Signing UEFI keys for Secure Boot"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
+
+DEPENDS += "bash-native"
+DEPENDS += "coreutils-native"
+DEPENDS += "efitools-native"
+DEPENDS += "openssl-native"
+
+SRC_URI = "file://gen_sbkeys.sh"
+
+UNPACKDIR = "${S}"
+
+do_patch[noexec] = "1"
+do_compile[noexec] = "1"
+do_configure[noexec] = "1"
+do_install[nostamp] = "1"
+
+python do_install() {
+ keys_dir = d.getVar('SBSIGN_KEYS_DIR', True)
+
+ keys_to_check = [
+ keys_dir + "/PK.esl",
+ keys_dir + "/KEK.esl",
+ keys_dir + "/db.esl",
+ keys_dir + "/dbx.esl",
+ keys_dir + "/db.key",
+ keys_dir + "/db.crt",
+ ]
+
+ missing_keys = [f for f in keys_to_check if not os.path.exists(f)]
+
+ if not missing_keys:
+ bb.debug(2, "All UEFI keys found in '%s' to sign binaries'" % keys_dir)
+ return
+
+ gen_sbkeys = d.getVar('UNPACKDIR', True) + "/gen_sbkeys.sh"
+
+ import subprocess
+ bb.debug(2, "Calling '%s' to generate UEFI keys in path: '%s'" % (gen_sbkeys, keys_dir))
+ cmd = "%s %s" % (gen_sbkeys, keys_dir)
+ subprocess.Popen(cmd, shell=True)
+}
+
+FILES:${PN} += "${SBSIGN_KEYS_DIR}/db.key"
+FILES:${PN} += "${SBSIGN_KEYS_DIR}/db.crt"
new file mode 100755
@@ -0,0 +1,52 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: MIT
+#
+#
+# Set up UEFI Secure Boot keys. Generate keys and certificates, convert them
+# into EFI Signature Lists, and sign them. By managing these keys, you can
+# control what is considered trusted on your system.
+
+set -eux
+
+KEYS_PATH=${1:-./}
+SUBJECT="/CN=OpenEmbedded/"
+
+# The number used is just a GUID random number that has not special meaning.
+# GUID (Globally Unique Identifier) is associated with the signature list. GUIDs
+# in this context are used to uniquely identify the owner or the purpose of the
+# keys within the EFI environment. This GUID can be used to distinguish
+# different lists or purposes within the UEFI firmware settings
+GUID="11111111-2222-3333-4444-123456789abc"
+
+if [ ! -d "${KEYS_PATH}" ]; then
+ mkdir -p "${KEYS_PATH}"
+fi
+
+if [ -f "${KEYS_PATH}"/PK.crt ]; then
+ exit 0
+fi
+
+# Platform Key (PK): The root key in Secure Boot, which authorizes changes to
+# the KEK
+openssl req -x509 -sha256 -newkey rsa:2048 -subj "${SUBJECT}" \
+ -keyout "${KEYS_PATH}"/PK.key -out "${KEYS_PATH}"/PK.crt \
+ -nodes -days 3650
+cert-to-efi-sig-list -g ${GUID} \
+ "${KEYS_PATH}"/PK.crt "${KEYS_PATH}"/PK.esl
+sign-efi-sig-list -c "${KEYS_PATH}"/PK.crt -k "${KEYS_PATH}"/PK.key \
+ "${KEYS_PATH}"/PK "${KEYS_PATH}"/PK.esl "${KEYS_PATH}"/PK.auth
+
+# Key Exchange Key (KEK): Allows for updates to the db and dbx lists
+#
+# db and dbx: Control lists for allowed and disallowed executable files and
+# drivers
+for key in KEK db dbx; do
+ openssl req -x509 -sha256 -newkey rsa:2048 -subj "${SUBJECT}" \
+ -keyout "${KEYS_PATH}"/${key}.key -out "${KEYS_PATH}"/${key}.crt \
+ -nodes -days 3650
+ cert-to-efi-sig-list -g ${GUID} \
+ "${KEYS_PATH}"/${key}.crt "${KEYS_PATH}"/${key}.esl
+ sign-efi-sig-list -c "${KEYS_PATH}"/PK.crt -k "${KEYS_PATH}"/PK.key \
+ "${KEYS_PATH}"/${key} "${KEYS_PATH}"/${key}.esl "${KEYS_PATH}"/${key}.auth
+done
new file mode 100644
@@ -0,0 +1,7 @@
+inherit sbsign
+
+SBSIGN_TARGET_BINARY = "${B}/src/boot/efi/systemd-boot${EFI_ARCH}.efi"
+
+do_compile:append() {
+ do_sbsign
+}
new file mode 100644
@@ -0,0 +1 @@
+require ${@bb.utils.contains('MACHINE_FEATURES', 'uefi-secureboot', 'systemd-boot-uefi-secureboot.inc', '', d)}
new file mode 100644
@@ -0,0 +1 @@
+PACKAGECONFIG:append = " efi"
new file mode 100644
@@ -0,0 +1 @@
+require ${@bb.utils.contains('MACHINE_FEATURES', 'efi', 'systemd-efi.inc', '', d)}
@@ -25,3 +25,5 @@ SRC_URI:append:qemuarm = " \
FFA_TRANSPORT_INCLUDE = "${@bb.utils.contains('MACHINE_FEATURES', 'arm-ffa', 'arm-ffa-transport.inc', '' , d)}"
require ${FFA_TRANSPORT_INCLUDE}
+
+require ${@bb.utils.contains('MACHINE_FEATURES', 'uefi-secureboot', 'linux-yocto-uefi-secureboot.inc', '', d)}
new file mode 100644
@@ -0,0 +1,14 @@
+KERNEL_FEATURES += "cfg/efi-ext.scc"
+
+inherit sbsign
+
+# shell variable set inside do_compile task
+SBSIGN_TARGET_BINARY = "$KERNEL_IMAGE"
+
+do_compile:append() {
+ KERNEL_IMAGE=$(find ${B} -name ${KERNEL_IMAGETYPE} -print -quit)
+ do_sbsign
+}
+
+RRECOMMENDS:${PN} += "kernel-module-efivarfs"
+RRECOMMENDS:${PN} += "kernel-module-efivars"