efi_image_authenticate() accepts every image, so with signed images forced, a verified payload can still load unsigned images through LoadImage(). systemd-stub does exactly that for the addons it finds next to a UKI, PE files carrying .cmdline, .dtb and .initrd sections, without shim through plain LoadImage(). An unsigned addon could thus replace the kernel command line or devicetree of a signed UKI.
With signed images forced, verify images in LoadImage() against the "efi" keyring, and have StartImage() refuse images that failed: as the UEFI specification has it, LoadImage() still creates the handle when it returns EFI_SECURITY_VIOLATION. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Johannes Schneider <[email protected]> --- efi/loader/Kconfig | 3 ++- efi/loader/boot.c | 3 +++ efi/loader/pe.c | 7 ++++++- include/efi/loader/authenticode.h | 11 +++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/efi/loader/Kconfig b/efi/loader/Kconfig index 8345fccd1a..156123212b 100644 --- a/efi/loader/Kconfig +++ b/efi/loader/Kconfig @@ -33,7 +33,8 @@ config EFI_LOADER_AUTHENTICODE image booted with bootm against the keys compiled into the "efi" keyring (CONFIG_CRYPTO_PUBLIC_KEYS, keyring=efi). With signed images forced, an EFI image then boots only if one of those keys verifies - it, the same way a FIT image must carry a valid signature. + it, the same way a FIT image must carry a valid signature, and so + do the images an EFI payload loads through LoadImage(). X.509 certificates in the signature are not evaluated: trust is anchored in the keyring. barebox does not report UEFI Secure Boot diff --git a/efi/loader/boot.c b/efi/loader/boot.c index 2d98c95b5c..3c9489e951 100644 --- a/efi/loader/boot.c +++ b/efi/loader/boot.c @@ -3098,6 +3098,9 @@ efi_status_t __efi_start_image(efi_handle_t image_handle, if (image_obj->header.type != EFI_OBJECT_TYPE_LOADED_IMAGE) return EFI_EXIT(EFI_INVALID_PARAMETER); + if (image_obj->auth_status != EFI_IMAGE_AUTH_PASSED) + return EFI_EXIT(EFI_SECURITY_VIOLATION); + ret = EFI_CALL(efi_open_protocol(image_handle, &efi_loaded_image_protocol_guid, (void **)&info, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)); diff --git a/efi/loader/pe.c b/efi/loader/pe.c index 827b50378c..efec38b111 100644 --- a/efi/loader/pe.c +++ b/efi/loader/pe.c @@ -18,6 +18,8 @@ #include <efi/memory.h> #include <efi/loader.h> #include <efi/loader/pe.h> +#include <efi/loader/authenticode.h> +#include <bootm.h> #include <efi/guid.h> #include <efi/error.h> #include <pe.h> @@ -895,7 +897,10 @@ const void *efi_pe_find_section(void *efi, size_t len, const char *name, #ifdef CONFIG_EFI_LOADER static bool efi_image_authenticate(void *efi, size_t efi_size) { - return true; + if (!IS_ENABLED(CONFIG_BOOTM) || !bootm_signed_images_are_forced()) + return true; + + return !efi_authenticode_verify(efi, efi_size, EFI_AUTHENTICODE_KEYRING); } /** diff --git a/include/efi/loader/authenticode.h b/include/efi/loader/authenticode.h index 24c46ca7cf..df4fb7eab0 100644 --- a/include/efi/loader/authenticode.h +++ b/include/efi/loader/authenticode.h @@ -3,7 +3,18 @@ #define __EFI_LOADER_AUTHENTICODE_H #include <linux/types.h> +#include <linux/errno.h> +#define EFI_AUTHENTICODE_KEYRING "efi" + +#ifdef CONFIG_EFI_AUTHENTICODE int efi_authenticode_verify(void *efi, size_t len, const char *keyring); +#else +static inline int efi_authenticode_verify(void *efi, size_t len, + const char *keyring) +{ + return -ENOSYS; +} +#endif #endif -- 2.43.0
