From 00a828377ab9f9fb407b1d18c794c58a0fe3c463 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Wed, 29 Jul 2020 13:16:37 -0400 Subject: [PATCH] import shim-unsigned-x64-15-7.el8 --- ...ings-dprint-instead-of-console_print.patch | 29 + ...-m32-gets-propogated-to-our-gcc-para.patch | 131 +++ ...ollow-a-MokTimeout-var-for-timeout-l.patch | 61 ++ ...EFI_NOT_FOUND-when-it-fails-to-find-.patch | 30 + ...ore-messages-when-it-fails-to-set-IP.patch | 107 ++ ...t-allow-the-IPv4-gateway-to-be-empty.patch | 68 ++ ...he-error-message-for-the-ChildHandle.patch | 30 + ...008-Fix-typo-in-debug-path-in-shim.h.patch | 54 + ...Stop-using-EFI_VARIABLE_APPEND_WRITE.patch | 43 + ...d-invalid-reloc-size-warning-message.patch | 40 + ...1-Add-GRUB-s-PCR-Usage-to-README.tpm.patch | 34 + ...mpile-error-of-mkdir-wrong-directory.patch | 36 + ...nerate-absolute-paths-from-relative-.patch | 52 + ...m-to-set-itself-as-a-second-stage-lo.patch | 77 ++ ...0-has-negative-size-error-when-loadi.patch | 121 +++ ...x-apparent-typo-in-ARM-32-on-64-code.patch | 30 + ...run-git-on-clean-if-there-s-no-.git-.patch | 32 + ...-correct-flags-to-disable-unaligned-.patch | 40 + ...0019-Cryptlib-fix-build-on-32bit-ARM.patch | 34 + ...t-MOK-variables-always-get-mirrored.patch} | 7 +- ...k-fix-the-mirroring-of-RT-variables.patch} | 7 +- ...irroring-code-in-a-helper-instead-o.patch} | 13 +- ...m-only-include-shim_cert.h-in-shim.c.patch | 82 ++ ...o-mirror-the-build-cert-to-MokListRT.patch | 153 +++ SOURCES/0025-mok-minor-cleanups.patch | 37 + ...26-Remove-call-to-TPM2-get_event_log.patch | 91 ++ ...e-copying-fatal-only-on-secureboot-e.patch | 48 + ...ULL-pointer-dereferences-in-V-Sprin.patch} | 22 +- ...ven-harder-to-get-binaries-without-t.patch | 98 ++ ...pause-functions-and-add-read_counter.patch | 280 +++++ ...it-when-shim_lock-protocol-installed.patch | 49 + ...tuff-Waddress-of-packed-member-finds.patch | 89 ++ ...ix-a-use-of-strlen-instead-of-Strlen.patch | 27 + ...ompareMem-on-MokListNode.Type-instea.patch | 72 ++ ...provide-OBJ_create-with-name-strings.patch | 32 + ...e-shebangs-bin-bash-usr-bin-env-bash.patch | 42 + ...ne-error-when-calculating-event-size.patch | 44 + ...ine-EFI_VARIABLE_DATA_TREE-as-packed.patch | 36 + ...le-mode-modification-for-hi-dpi-scre.patch | 223 ++++ ...void-Werror-address-of-packed-member.patch | 111 ++ ...Don-t-log-duplicate-identical-events.patch | 31 + ...2-Slightly-better-debugging-messages.patch | 57 + ...eck-for-errors-from-set_second_stage.patch | 69 ++ ...ashes-don-t-write-to-string-literals.patch | 140 +++ ...LOADED_IMAGE-with-the-second-stage-l.patch | 93 ++ ...rmation-about-PE-COFF-images-in-the-.patch | 124 +++ ...the-license-on-our-buildid-extractor.patch | 27 + SOURCES/0048-Update-README.tpm.patch | 27 + ...ReplyReceived-as-fallback-in-netboot.patch | 61 ++ ...a-couple-of-incorrect-license-claims.patch | 46 + ...1-MokManager-fix-uninitialized-value.patch | 27 + ...some-volatile-usage-gcc-whines-about.patch | 41 + ...fix-a-wrong-allocation-failure-check.patch | 31 + ...uninitialized-variable-unchecked-ret.patch | 33 + SOURCES/0055-Fix-a-broken-tpm-type.patch | 27 + ...6-Make-cert.S-not-impossible-to-read.patch | 279 +++++ ...vendor_db-built-in-shim-authorized-l.patch | 943 +++++++++++++++++ ...le-binaries-with-multiple-signatures.patch | 366 +++++++ ...nssl-accept-the-right-set-of-KU-EKUs.patch | 119 +++ SOURCES/0060-Improve-debug-output-some.patch | 451 ++++++++ ...config-table-to-mirror-mok-variables.patch | 352 +++++++ ...-lennysz-s-suggestions-for-MokListRT.patch | 991 ++++++++++++++++++ SOURCES/redhatsecurebootca5.cer | Bin 0 -> 920 bytes SOURCES/securebootca.cer | Bin 977 -> 0 bytes SPECS/shim-unsigned-x64.spec | 108 +- 65 files changed, 7030 insertions(+), 25 deletions(-) create mode 100644 SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch create mode 100644 SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch create mode 100644 SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch create mode 100644 SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch create mode 100644 SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch create mode 100644 SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch create mode 100644 SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch create mode 100644 SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch create mode 100644 SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch create mode 100644 SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch create mode 100644 SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch create mode 100644 SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch create mode 100644 SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch create mode 100644 SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch create mode 100644 SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch create mode 100644 SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch create mode 100644 SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch create mode 100644 SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch create mode 100644 SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch rename SOURCES/{0001-Make-sure-that-MOK-variables-always-get-mirrored.patch => 0020-Make-sure-that-MOK-variables-always-get-mirrored.patch} (90%) rename SOURCES/{0002-mok-fix-the-mirroring-of-RT-variables.patch => 0021-mok-fix-the-mirroring-of-RT-variables.patch} (89%) rename SOURCES/{0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch => 0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch} (89%) create mode 100644 SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch create mode 100644 SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch create mode 100644 SOURCES/0025-mok-minor-cleanups.patch create mode 100644 SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch create mode 100644 SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch rename SOURCES/{0004-Make-VLogError-behave-as-expected.patch => 0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch} (59%) create mode 100644 SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch create mode 100644 SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch create mode 100644 SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch create mode 100644 SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch create mode 100644 SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch create mode 100644 SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch create mode 100644 SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch create mode 100644 SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch create mode 100644 SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch create mode 100644 SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch create mode 100644 SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch create mode 100644 SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch create mode 100644 SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch create mode 100644 SOURCES/0042-Slightly-better-debugging-messages.patch create mode 100644 SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch create mode 100644 SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch create mode 100644 SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch create mode 100644 SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch create mode 100644 SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch create mode 100644 SOURCES/0048-Update-README.tpm.patch create mode 100644 SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch create mode 100644 SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch create mode 100644 SOURCES/0051-MokManager-fix-uninitialized-value.patch create mode 100644 SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch create mode 100644 SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch create mode 100644 SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch create mode 100644 SOURCES/0055-Fix-a-broken-tpm-type.patch create mode 100644 SOURCES/0056-Make-cert.S-not-impossible-to-read.patch create mode 100644 SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch create mode 100644 SOURCES/0058-Handle-binaries-with-multiple-signatures.patch create mode 100644 SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch create mode 100644 SOURCES/0060-Improve-debug-output-some.patch create mode 100644 SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch create mode 100644 SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch create mode 100644 SOURCES/redhatsecurebootca5.cer delete mode 100644 SOURCES/securebootca.cer diff --git a/SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch b/SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch new file mode 100644 index 0000000..7190954 --- /dev/null +++ b/SOURCES/0001-Make-some-things-dprint-instead-of-console_print.patch @@ -0,0 +1,29 @@ +From 1d50318f448b73b072724eb6664d311e6084a446 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 10 Apr 2018 12:36:34 -0400 +Subject: [PATCH 01/62] Make some things dprint() instead of console_print() + +Signed-off-by: Peter Jones +Upstream-commit-id: dad59f8c0f36 +--- + shim.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index 00155346c12..ff0817009cd 100644 +--- a/shim.c ++++ b/shim.c +@@ -2087,8 +2087,8 @@ static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len) + if (!dppath) + return 0; + +- console_print(L"dppath: %s\n", dppath); +- console_print(L"path: %s\n", path); ++ dprint(L"dppath: %s\n", dppath); ++ dprint(L"path: %s\n", path); + if (StrnCaseCmp(dppath, path, len)) + ret = 0; + +-- +2.26.2 + diff --git a/SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch b/SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch new file mode 100644 index 0000000..94c0c73 --- /dev/null +++ b/SOURCES/0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch @@ -0,0 +1,131 @@ +From 32f71225382ddb7dd1ad51f584bc3d42a7ee39d1 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 12 Apr 2018 13:24:48 -0400 +Subject: [PATCH 02/62] Makefiles: ensure -m32 gets propogated to our gcc + parameter queries + +'gcc -print-file-name=include' and 'gcc -print-libgcc-file-name' both +need -m32 when we're building 32-on-64 on some distros, so ensure that +gets propogated correctly. + +Signed-off-by: Peter Jones +Upstream-commit-id: 104d6e54ac7 +--- + Make.defaults | 66 ++++++++++++++++++++++++++------------------------- + 1 file changed, 34 insertions(+), 32 deletions(-) + +diff --git a/Make.defaults b/Make.defaults +index e11ab5a7f2c..bbfc1d7f77b 100644 +--- a/Make.defaults ++++ b/Make.defaults +@@ -33,66 +33,46 @@ EFI_INCLUDES = -nostdinc -I$(TOPDIR)/Cryptlib -I$(TOPDIR)/Cryptlib/Include \ + -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol \ + -I$(TOPDIR)/include -iquote $(TOPDIR) -iquote $(shell pwd) + +-LIB_GCC = $(shell $(CC) -print-libgcc-file-name) +-EFI_LIBS = -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC) +- + EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o + EFI_LDS = $(TOPDIR)/elf_$(ARCH)_efi.lds + +-CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ +- -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \ +- -Werror=sign-compare -ffreestanding -std=gnu89 \ +- -I$(shell $(CC) -print-file-name=include) \ +- "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \ +- "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \ +- $(EFI_INCLUDES) +- + CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,) + + COMMIT_ID ?= $(shell if [ -e .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo master; fi) + +-ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined) +- CFLAGS += -DOVERRIDE_SECURITY_POLICY +-endif +- +-ifneq ($(origin ENABLE_HTTPBOOT), undefined) +- CFLAGS += -DENABLE_HTTPBOOT +-endif +- +-ifneq ($(origin REQUIRE_TPM), undefined) +- CFLAGS += -DREQUIRE_TPM +-endif +- + ifeq ($(ARCH),x86_64) +- CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \ +- $(CLANG_BUGS) -m64 \ +- -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ +- -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 -DPAGE_SIZE=4096 ++ ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \ ++ $(CLANG_BUGS) -m64 \ ++ -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ ++ -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 \ ++ -DPAGE_SIZE=4096 + LIBDIR ?= $(prefix)/lib64 + ARCH_SUFFIX ?= x64 + ARCH_SUFFIX_UPPER ?= X64 + ARCH_LDFLAGS ?= + endif + ifeq ($(ARCH),ia32) +- CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \ +- $(CLANG_BUGS) -m32 \ +- -DMDE_CPU_IA32 -DPAGE_SIZE=4096 ++ ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \ ++ $(CLANG_BUGS) -m32 \ ++ -DMDE_CPU_IA32 -DPAGE_SIZE=4096 + LIBDIR ?= $(prefix)/lib + ARCH_SUFFIX ?= ia32 + ARCH_SUFFIX_UPPER ?= IA32 + ARCH_LDFLAGS ?= ++ ARCH_CFLAGS ?= -m32 + endif + ifeq ($(ARCH),aarch64) +- CFLAGS += -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align ++ ARCH_CFLAGS ?= -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align + LIBDIR ?= $(prefix)/lib64 + ARCH_SUFFIX ?= aa64 + ARCH_SUFFIX_UPPER ?= AA64 + FORMAT := -O binary + SUBSYSTEM := 0xa + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) ++ ARCH_CFLAGS ?= + endif + ifeq ($(ARCH),arm) +- CFLAGS += -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align ++ ARCH_CFLAGS ?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align + LIBDIR ?= $(prefix)/lib + ARCH_SUFFIX ?= arm + ARCH_SUFFIX_UPPER ?= ARM +@@ -101,6 +81,28 @@ ifeq ($(ARCH),arm) + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) + endif + ++CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ ++ -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \ ++ -Werror=sign-compare -ffreestanding -std=gnu89 \ ++ -I$(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include) \ ++ "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \ ++ "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \ ++ $(EFI_INCLUDES) $(ARCH_CFLAGS) ++ ++ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined) ++ CFLAGS += -DOVERRIDE_SECURITY_POLICY ++endif ++ ++ifneq ($(origin ENABLE_HTTPBOOT), undefined) ++ CFLAGS += -DENABLE_HTTPBOOT ++endif ++ ++ifneq ($(origin REQUIRE_TPM), undefined) ++ CFLAGS += -DREQUIRE_TPM ++endif ++ ++LIB_GCC = $(shell $(CC) $(ARCH_CFLAGS) -print-libgcc-file-name) ++EFI_LIBS = -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC) + FORMAT ?= --target efi-app-$(ARCH) + EFI_PATH ?= $(LIBDIR)/gnuefi + +-- +2.26.2 + diff --git a/SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch b/SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch new file mode 100644 index 0000000..9f6697a --- /dev/null +++ b/SOURCES/0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch @@ -0,0 +1,61 @@ +From 74718677945b1ab825130b317c63f5002876e772 Mon Sep 17 00:00:00 2001 +From: Mathieu Trudel-Lapierre +Date: Thu, 5 Jul 2018 11:28:12 -0400 +Subject: [PATCH 03/62] Let MokManager follow a MokTimeout var for timeout + length for the prompt + +This timeout can have the values [-1,0..0x7fff]; where -1 means "no timeout", +with MokManager going directly to the menu, and is capped to 0x7fff to avoid +unecessary long timeouts. The default remains 10, which will be used whenever +the MokTimeout variable isn't set. + +Signed-off-by: Mathieu Trudel-Lapierre +Upstream-commit-id: 93708c11083 +--- + MokManager.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/MokManager.c b/MokManager.c +index 7e40a38f1d1..0767e4a6cde 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -40,6 +40,10 @@ typedef struct { + CHAR16 Password[SB_PASSWORD_LEN]; + } __attribute__ ((packed)) MokDBvar; + ++typedef struct { ++ INT32 Timeout; ++} __attribute__ ((packed)) MokTimeoutvar; ++ + static EFI_STATUS get_sha1sum(void *Data, int DataSize, UINT8 * hash) + { + EFI_STATUS efi_status; +@@ -2041,7 +2045,24 @@ static int draw_countdown() + UINTN cols, rows; + CHAR16 *title[2]; + CHAR16 *message = L"Press any key to perform MOK management"; +- int timeout = 10, wait = 10000000; ++ void *MokTimeout = NULL; ++ MokTimeoutvar *var; ++ UINTN MokTimeoutSize = 0; ++ int timeout, wait = 10000000; ++ ++ efi_status = get_variable(L"MokTimeout", (UINT8 **) &MokTimeout, ++ &MokTimeoutSize, SHIM_LOCK_GUID); ++ if (EFI_ERROR(efi_status)) { ++ timeout = 10; ++ } else { ++ var = MokTimeout; ++ timeout = (int)var->Timeout; ++ FreePool(MokTimeout); ++ LibDeleteVariable(L"MokTimeout", &SHIM_LOCK_GUID); ++ } ++ ++ if (timeout < 0) ++ return timeout; + + console_save_and_set_mode(&SavedMode); + +-- +2.26.2 + diff --git a/SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch b/SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch new file mode 100644 index 0000000..44de3b7 --- /dev/null +++ b/SOURCES/0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch @@ -0,0 +1,30 @@ +From 8a66f5571bb059d2692e804f4ba9817e978dd103 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Mon, 28 May 2018 16:05:38 +0800 +Subject: [PATCH 04/62] httpboot: return EFI_NOT_FOUND when it fails to find + the NIC handle + +httpboot_fetch_buffer() should return EFI_NOT_FOUND to reflect the error +status when get_nic_handle() returns NULL. + +Signed-off-by: Gary Lin +Upstream-commit-id: 2be5c7dc4b0 +--- + httpboot.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/httpboot.c b/httpboot.c +index 4cfa3aab3b7..d656073c633 100644 +--- a/httpboot.c ++++ b/httpboot.c +@@ -715,6 +715,7 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) + also supports the HTTP service binding protocol */ + nic = get_nic_handle(&mac_addr); + if (!nic) { ++ efi_status = EFI_NOT_FOUND; + goto error; + } + +-- +2.26.2 + diff --git a/SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch b/SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch new file mode 100644 index 0000000..d64a381 --- /dev/null +++ b/SOURCES/0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch @@ -0,0 +1,107 @@ +From 0ba6c87bdf55f749a0ec1c3b0fd24ebb8200d537 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Mon, 28 May 2018 17:24:30 +0800 +Subject: [PATCH 05/62] httpboot: print more messages when it fails to set IP + +We previously only print the return status and it may not be clear +enough in some situations. Print the IP address and the gateway to help +the user to identify the possible errors. + +Signed-off-by: Gary Lin +Upstream-commit-id: 3abe94516c7 +--- + httpboot.c | 45 +++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 41 insertions(+), 4 deletions(-) + +diff --git a/httpboot.c b/httpboot.c +index d656073c633..6f27b01bf71 100644 +--- a/httpboot.c ++++ b/httpboot.c +@@ -311,6 +311,20 @@ is_unspecified_addr (EFI_IPv6_ADDRESS ip6) + return TRUE; + } + ++static inline void ++print_ip6_addr(EFI_IPv6_ADDRESS ip6addr) ++{ ++ perror(L"%x:%x:%x:%x:%x:%x:%x:%x\n", ++ ip6addr.Addr[0] << 8 | ip6addr.Addr[1], ++ ip6addr.Addr[2] << 8 | ip6addr.Addr[3], ++ ip6addr.Addr[4] << 8 | ip6addr.Addr[5], ++ ip6addr.Addr[6] << 8 | ip6addr.Addr[7], ++ ip6addr.Addr[8] << 8 | ip6addr.Addr[9], ++ ip6addr.Addr[10] << 8 | ip6addr.Addr[11], ++ ip6addr.Addr[12] << 8 | ip6addr.Addr[13], ++ ip6addr.Addr[14] << 8 | ip6addr.Addr[15]); ++} ++ + static EFI_STATUS + set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node) + { +@@ -329,8 +343,12 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node) + ip6.IsAnycast = FALSE; + efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeManualAddress, + sizeof(ip6), &ip6); +- if (EFI_ERROR(efi_status)) ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to set IPv6 Address:\nIP: "); ++ print_ip6_addr(ip6.Address); ++ perror(L"Prefix Length: %u\n", ip6.PrefixLength); + return efi_status; ++ } + + gateway = ip6node->GatewayIpAddress; + if (is_unspecified_addr(gateway)) +@@ -338,12 +356,23 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node) + + efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeGateway, + sizeof(gateway), &gateway); +- if (EFI_ERROR(efi_status)) ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to set IPv6 Gateway:\nIP: "); ++ print_ip6_addr(gateway); + return efi_status; ++ } + + return EFI_SUCCESS; + } + ++static inline void ++print_ip4_addr(EFI_IPv4_ADDRESS ip4addr) ++{ ++ perror(L"%u.%u.%u.%u\n", ++ ip4addr.Addr[0], ip4addr.Addr[1], ++ ip4addr.Addr[2], ip4addr.Addr[3]); ++} ++ + static EFI_STATUS + set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node) + { +@@ -361,14 +390,22 @@ set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node) + ip4.SubnetMask = ip4node->SubnetMask; + efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeManualAddress, + sizeof(ip4), &ip4); +- if (EFI_ERROR(efi_status)) ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to Set IPv4 Address:\nIP: "); ++ print_ip4_addr(ip4.Address); ++ perror(L"Mask: "); ++ print_ip4_addr(ip4.SubnetMask); + return efi_status; ++ } + + gateway = ip4node->GatewayIpAddress; + efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeGateway, + sizeof(gateway), &gateway); +- if (EFI_ERROR(efi_status)) ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to Set IPv4 Gateway:\nGateway: "); ++ print_ip4_addr(gateway); + return efi_status; ++ } + + return EFI_SUCCESS; + } +-- +2.26.2 + diff --git a/SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch b/SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch new file mode 100644 index 0000000..4b92fda --- /dev/null +++ b/SOURCES/0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch @@ -0,0 +1,68 @@ +From 80e52895f206fcb40a60f031e7b721627bb193ca Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Mon, 28 May 2018 17:42:56 +0800 +Subject: [PATCH 06/62] httpboot: allow the IPv4 gateway to be empty + +The gateway is not mandatory. + +Signed-off-by: Gary Lin +Upstream-commit-id: 69089e9c678 +--- + httpboot.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/httpboot.c b/httpboot.c +index 6f27b01bf71..16dd6621f66 100644 +--- a/httpboot.c ++++ b/httpboot.c +@@ -299,7 +299,7 @@ out: + } + + static BOOLEAN +-is_unspecified_addr (EFI_IPv6_ADDRESS ip6) ++is_unspecified_ip6addr (EFI_IPv6_ADDRESS ip6) + { + UINT8 i; + +@@ -351,7 +351,7 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node) + } + + gateway = ip6node->GatewayIpAddress; +- if (is_unspecified_addr(gateway)) ++ if (is_unspecified_ip6addr(gateway)) + return EFI_SUCCESS; + + efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeGateway, +@@ -365,6 +365,19 @@ set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node) + return EFI_SUCCESS; + } + ++static BOOLEAN ++is_unspecified_ip4addr (EFI_IPv4_ADDRESS ip4) ++{ ++ UINT8 i; ++ ++ for (i = 0; i<4; i++) { ++ if (ip4.Addr[i] != 0) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ + static inline void + print_ip4_addr(EFI_IPv4_ADDRESS ip4addr) + { +@@ -399,6 +412,9 @@ set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node) + } + + gateway = ip4node->GatewayIpAddress; ++ if (is_unspecified_ip4addr(gateway)) ++ return EFI_SUCCESS; ++ + efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeGateway, + sizeof(gateway), &gateway); + if (EFI_ERROR(efi_status)) { +-- +2.26.2 + diff --git a/SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch b/SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch new file mode 100644 index 0000000..8d42888 --- /dev/null +++ b/SOURCES/0007-httpboot-show-the-error-message-for-the-ChildHandle.patch @@ -0,0 +1,30 @@ +From c2f645c7cd9872585e7b4522b01c368bb545258b Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Mon, 28 May 2018 18:03:39 +0800 +Subject: [PATCH 07/62] httpboot: show the error message for the ChildHandle + +Signed-off-by: Gary Lin +Upstream-commit-id: 0fd3c7e8518 +--- + httpboot.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/httpboot.c b/httpboot.c +index 16dd6621f66..3622e85867c 100644 +--- a/httpboot.c ++++ b/httpboot.c +@@ -696,8 +696,10 @@ http_fetch (EFI_HANDLE image, EFI_HANDLE device, + /* Set the handle to NULL to request a new handle */ + http_handle = NULL; + efi_status = service->CreateChild(service, &http_handle); +- if (EFI_ERROR(efi_status)) ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to create the ChildHandle\n"); + return efi_status; ++ } + + /* Get the http protocol */ + efi_status = gBS->HandleProtocol(http_handle, &EFI_HTTP_PROTOCOL_GUID, +-- +2.26.2 + diff --git a/SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch b/SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch new file mode 100644 index 0000000..be22b83 --- /dev/null +++ b/SOURCES/0008-Fix-typo-in-debug-path-in-shim.h.patch @@ -0,0 +1,54 @@ +From 409b59af29b8749207a527c91dccba7eee98232b Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Wed, 23 May 2018 15:15:56 +0800 +Subject: [PATCH 08/62] Fix typo in debug path in shim.h + +Signed-off-by: Gary Lin +Upstream-commit-id: a98c20bbdbb +--- + shim.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/shim.h b/shim.h +index a25a660df6a..2b359d821e3 100644 +--- a/shim.h ++++ b/shim.h +@@ -43,7 +43,7 @@ + #define EFI_ARCH L"x64" + #endif + #ifndef DEBUGDIR +-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/x64/" ++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/x64/" + #endif + #endif + +@@ -58,7 +58,7 @@ + #define EFI_ARCH L"ia32" + #endif + #ifndef DEBUGDIR +-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/ia32/" ++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/ia32/" + #endif + #endif + +@@ -73,7 +73,7 @@ + #define EFI_ARCH L"aa64" + #endif + #ifndef DEBUGDIR +-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/aa64/" ++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/aa64/" + #endif + #endif + +@@ -88,7 +88,7 @@ + #define EFI_ARCH L"arm" + #endif + #ifndef DEBUGDIR +-#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/arm/" ++#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/arm/" + #endif + #endif + +-- +2.26.2 + diff --git a/SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch b/SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch new file mode 100644 index 0000000..1baa54b --- /dev/null +++ b/SOURCES/0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch @@ -0,0 +1,43 @@ +From 85c837d67fef9cd831a3126398ed8da1421f61c5 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Fri, 11 May 2018 16:59:03 +0800 +Subject: [PATCH 09/62] MokManager: Stop using EFI_VARIABLE_APPEND_WRITE + +When writing MokList with EFI_VARIABLE_APPEND_WRITE, some HP laptops +may just return EFI_SUCCESS without writing the content into the flash, +so we have no way to detect if MokList is updated or not. Now we always +read MokList first and write it back with the new content. + +https://github.com/rhboot/shim/issues/105 + +Signed-off-by: Gary Lin +Upstream-commit-id: f442c8424b4 +--- + MokManager.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 0767e4a6cde..df9b6fe6912 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -880,14 +880,9 @@ static EFI_STATUS write_db(CHAR16 * db_name, void *MokNew, UINTN MokNewSize) + UINTN old_size; + UINTN new_size; + +- efi_status = gRT->SetVariable(db_name, &SHIM_LOCK_GUID, +- EFI_VARIABLE_NON_VOLATILE | +- EFI_VARIABLE_BOOTSERVICE_ACCESS | +- EFI_VARIABLE_APPEND_WRITE, +- MokNewSize, MokNew); +- if (!EFI_ERROR(efi_status) || efi_status != EFI_INVALID_PARAMETER) { +- return efi_status; +- } ++ /* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares. ++ * ref: https://github.com/rhboot/shim/issues/55 ++ * https://github.com/rhboot/shim/issues/105 */ + + efi_status = get_variable_attr(db_name, (UINT8 **)&old_data, &old_size, + SHIM_LOCK_GUID, &attributes); +-- +2.26.2 + diff --git a/SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch b/SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch new file mode 100644 index 0000000..76d26e8 --- /dev/null +++ b/SOURCES/0010-shim-Extend-invalid-reloc-size-warning-message.patch @@ -0,0 +1,40 @@ +From 956717e2b375d7c7f0faafec8f12a7692708eb9a Mon Sep 17 00:00:00 2001 +From: Paul Menzel +Date: Wed, 23 May 2018 12:32:37 +0200 +Subject: [PATCH 10/62] shim: Extend invalid reloc size warning message + +Knowing the value of the reloc directory size is helpful for debugging, +cf. issue #131 [1], + +[1]: https://github.com/rhboot/shim/issues/131 + +Signed-off-by: Paul Menzel +Upstream-commit-id: dd3230d07f3 +--- + shim.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index ff0817009cd..05fc65005d1 100644 +--- a/shim.c ++++ b/shim.c +@@ -280,8 +280,14 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, + while (RelocBase < RelocBaseEnd) { + Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + +- if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > context->RelocDir->Size)) { +- perror(L"Reloc %d block size %d is invalid\n", n, RelocBase->SizeOfBlock); ++ if (RelocBase->SizeOfBlock == 0) { ++ perror(L"Reloc %d block size 0 is invalid\n", n); ++ return EFI_UNSUPPORTED; ++ } else if (RelocBase->SizeOfBlock > context->RelocDir->Size) { ++ perror(L"Reloc %d block size %d greater than reloc dir" ++ "size %d, which is invalid\n", n, ++ RelocBase->SizeOfBlock, ++ context->RelocDir->Size); + return EFI_UNSUPPORTED; + } + +-- +2.26.2 + diff --git a/SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch b/SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch new file mode 100644 index 0000000..25197e0 --- /dev/null +++ b/SOURCES/0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch @@ -0,0 +1,34 @@ +From bd97e72f0490b2be766949f448bf6ea3ec2bba1a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 1 Aug 2018 09:58:09 -0500 +Subject: [PATCH 11/62] Add GRUB's PCR Usage to README.tpm + +This didn't seem to get documented anywhere, and this is as good a place as any. +Upstream-commit-id: 4fab7281a8c +--- + README.tpm | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/README.tpm b/README.tpm +index b7314f12d57..d9c7c53483b 100644 +--- a/README.tpm ++++ b/README.tpm +@@ -19,6 +19,15 @@ PCR7: + - MokSBState will be extended into PCR7 if it is set, logged as + "MokSBState". + ++PCR8: ++- If you're using the grub2 TPM patchset we cary in Fedora, the kernel command ++ line and all grub commands (including all of grub.cfg that gets run) are ++ measured into PCR8. ++ ++PCR9: ++- If you're using the grub2 TPM patchset we cary in Fedora, the kernel, ++ initramfs, and any multiboot modules loaded are measured into PCR9. ++ + PCR14: + - MokList, MokListX, and MokSBState will be extended into PCR14 if they are + set. +-- +2.26.2 + diff --git a/SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch b/SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch new file mode 100644 index 0000000..a71436e --- /dev/null +++ b/SOURCES/0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch @@ -0,0 +1,36 @@ +From c4e3516e303daa42b3381ddd889a90641717f720 Mon Sep 17 00:00:00 2001 +From: TanMing +Date: Tue, 21 Aug 2018 02:25:52 -0400 +Subject: [PATCH 12/62] Fix the compile error of mkdir wrong directory. + +In Ubuntu 14.04, the following code in old Makefile: + mkdir -p Cryptlib/{Hash,Hmac,Cipher,Rand,Pk,Pem,SysCall} +will create a directory named "{Hash,Hmac,Cipher,Rand,Pk,Pem,SysCall}". + +Signed-off-by: Ming Tan +Upstream-commit-id: 39b83455d68 +--- + Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index 115e7f08c0f..3f2105595a6 100644 +--- a/Makefile ++++ b/Makefile +@@ -102,11 +102,11 @@ $(MMSONAME): $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a li + $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a + + Cryptlib/libcryptlib.a: +- mkdir -p Cryptlib/{Hash,Hmac,Cipher,Rand,Pk,Pem,SysCall} ++ for i in Hash Hmac Cipher Rand Pk Pem SysCall; do mkdir -p Cryptlib/$$i; done + $(MAKE) VPATH=$(TOPDIR)/Cryptlib TOPDIR=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile + + Cryptlib/OpenSSL/libopenssl.a: +- mkdir -p Cryptlib/OpenSSL/crypto/{x509v3,x509,txt_db,stack,sha,rsa,rc4,rand,pkcs7,pkcs12,pem,ocsp,objects,modes,md5,lhash,kdf,hmac,evp,err,dso,dh,conf,comp,cmac,buffer,bn,bio,async{,/arch},asn1,aes}/ ++ for i in x509v3 x509 txt_db stack sha rsa rc4 rand pkcs7 pkcs12 pem ocsp objects modes md5 lhash kdf hmac evp err dso dh conf comp cmac buffer bn bio async/arch asn1 aes; do mkdir -p Cryptlib/OpenSSL/crypto/$$i; done + $(MAKE) VPATH=$(TOPDIR)/Cryptlib/OpenSSL TOPDIR=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile + + lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch]) +-- +2.26.2 + diff --git a/SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch b/SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch new file mode 100644 index 0000000..00dfaeb --- /dev/null +++ b/SOURCES/0013-shim-Properly-generate-absolute-paths-from-relative-.patch @@ -0,0 +1,52 @@ +From 79be2af5260b1f2e2a4680e74e14da0fdb42b570 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Fri, 7 Sep 2018 14:11:02 +0200 +Subject: [PATCH 13/62] shim: Properly generate absolute paths from relative + image paths + +The generate_path_from_image_path() doesn't properly handle the case when +shim is invoked using a relative path (e.g: from the EFI shell). In that +function, always the last component is stripped from absolute file path +to calculate the dirname, and this is concatenated with the image path. + +But if the path is a relative one, the function will wrongly concatenate +the dirname with the relative image path, i.e: + + Shell> FS0: + FS0:\> cd EFI + FS0:\EFI\> BOOT\BOOTX64.EFI + Failed to open \EFI\BOOT\BOOT\BOOTX64.EFI - Not found + Failed to load image \EFI\BOOT\BOOT\BOOTX64.EFI: Not found + start_image() returned Not found + +Calculate the image path basename and concatenate that with the dirname. + +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Maran Wilson maran.wilson@oracle.com +Tested-by: Maran Wilson maran.wilson@oracle.com +Upstream-commit-id: a625fa5096c +--- + shim.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index 05fc65005d1..5ab23d03db4 100644 +--- a/shim.c ++++ b/shim.c +@@ -1610,9 +1610,11 @@ static EFI_STATUS generate_path_from_image_path(EFI_LOADED_IMAGE *li, + bootpath[j] = '\0'; + } + +- while (*ImagePath == '\\') +- ImagePath++; ++ for (i = 0, last = 0; i < StrLen(ImagePath); i++) ++ if (ImagePath[i] == '\\') ++ last = i + 1; + ++ ImagePath = ImagePath + last; + *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath)); + + if (!*PathName) { +-- +2.26.2 + diff --git a/SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch b/SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch new file mode 100644 index 0000000..34b9896 --- /dev/null +++ b/SOURCES/0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch @@ -0,0 +1,77 @@ +From 818a0dbd247f7c83d844febfa0a037b396d22701 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Fri, 7 Sep 2018 15:10:51 +0200 +Subject: [PATCH 14/62] shim: Prevent shim to set itself as a second stage + loader + +When shim is invoked from a relative path (e.g: from the UEFI shell), the +Loaded Image handle LoadOptions can be set to the binary relative path. + +But the is_our_path() function only checks if LoadOptions is set to the +absolute path of shim to ignore it. So if a relative path is there, shim +would set itself as the secondary loader and invoke itself in a loop. + +To prevent that, use the path in LoadOptions to calculate the absolute +path and compare it with the one in the Loader Image handle FilePath. + +Resolves: bz#1622485 + +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Maran Wilson maran.wilson@oracle.com +Tested-by: Maran Wilson maran.wilson@oracle.com +Upstream-commit-id: e563bc3dcd1 +--- + shim.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/shim.c b/shim.c +index 5ab23d03db4..ae03da7eddf 100644 +--- a/shim.c ++++ b/shim.c +@@ -2086,21 +2086,32 @@ get_load_option_optional_data(UINT8 *data, UINTN data_size, + return EFI_SUCCESS; + } + +-static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len) ++static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path) + { + CHAR16 *dppath = NULL; ++ CHAR16 *PathName = NULL; ++ EFI_STATUS efi_status; + int ret = 1; + + dppath = DevicePathToStr(li->FilePath); + if (!dppath) + return 0; + ++ efi_status = generate_path_from_image_path(li, path, &PathName); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Unable to generate path %s: %r\n", path, ++ efi_status); ++ goto done; ++ } ++ + dprint(L"dppath: %s\n", dppath); + dprint(L"path: %s\n", path); +- if (StrnCaseCmp(dppath, path, len)) ++ if (StrnCaseCmp(dppath, PathName, strlen(dppath))) + ret = 0; + ++done: + FreePool(dppath); ++ FreePool(PathName); + return ret; + } + +@@ -2289,7 +2300,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + + * which is just cruel... So yeah, just don't use it. + */ +- if (strings == 1 && is_our_path(li, start, loader_len)) ++ if (strings == 1 && is_our_path(li, start)) + return EFI_SUCCESS; + + /* +-- +2.26.2 + diff --git a/SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch b/SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch new file mode 100644 index 0000000..419d841 --- /dev/null +++ b/SOURCES/0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch @@ -0,0 +1,121 @@ +From 3d04aef8d80293d701f7efee6b5300f9f528ddfc Mon Sep 17 00:00:00 2001 +From: Maran Wilson +Date: Tue, 7 Aug 2018 15:32:29 -0700 +Subject: [PATCH 15/62] Fix for "Section 0 has negative size" error when + loading fbaa64.efi + +The current code is incorrectly failing to load the fbaa64.efi image found +in Arm servers even though the UEFI shell code is able to properly load +and execute the same image. + +The problem is due to the presence of a section header that has zero size +and address and marked "discardable" in the fbaa64.efi image. + +Although there is already a check further down in the code to look for +the discardable bit and skip further verification checks if set, we never +get to that point due to the "end < base" check at the start of the loop. + +Here is a dump of the fbaa64.efi image as compiled on an Arm machine +from the latest code in this repo: + +% # First I used hexedit to change header byte from 'AA' to '86' +% # so that objdump was able to correctly parse the file: +% objdump -x -m aarch64 fbaa64.efi + +fbaa64.efi: file format pei-x86-64 +fbaa64.efi +architecture: i386:x86-64, flags 0x00000103: +HAS_RELOC, EXEC_P, D_PAGED +start address 0x0000000000000148 + +Characteristics 0x20e + executable + line numbers stripped + symbols stripped + debugging information removed + +Time/Date Wed Dec 31 16:00:00 1969 +Magic 020b (PE32+) +MajorLinkerVersion 2 +MinorLinkerVersion 20 +SizeOfCode 000b15d0 +SizeOfInitializedData 00000000 +SizeOfUninitializedData 00000000 +AddressOfEntryPoint 0000000000000148 +BaseOfCode 0000000000000148 +ImageBase 0000000000000000 +SectionAlignment 0000000000000020 +FileAlignment 0000000000000008 +MajorOSystemVersion 0 +MinorOSystemVersion 0 +MajorImageVersion 0 +MinorImageVersion 0 +MajorSubsystemVersion 0 +MinorSubsystemVersion 0 +Win32Version 00000000 +SizeOfImage 000b1718 +SizeOfHeaders 00000148 +CheckSum 00000000 +Subsystem 0000000a (EFI application) +DllCharacteristics 00000000 +SizeOfStackReserve 0000000000000000 +SizeOfStackCommit 0000000000000000 +SizeOfHeapReserve 0000000000000000 +SizeOfHeapCommit 0000000000000000 +LoaderFlags 00000000 +NumberOfRvaAndSizes 00000006 + +The Data Directory +Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)] +Entry 1 0000000000000000 00000000 Import Directory [parts of .idata] +Entry 2 0000000000000000 00000000 Resource Directory [.rsrc] +Entry 3 0000000000000000 00000000 Exception Directory [.pdata] +Entry 4 0000000000000000 00000000 Security Directory +Entry 5 0000000000000000 00000000 Base Relocation Directory [.reloc] +Entry 6 0000000000000000 00000000 Debug Directory +Entry 7 0000000000000000 00000000 Description Directory +Entry 8 0000000000000000 00000000 Special Directory +Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls] +Entry a 0000000000000000 00000000 Load Configuration Directory +Entry b 0000000000000000 00000000 Bound Import Directory +Entry c 0000000000000000 00000000 Import Address Table Directory +Entry d 0000000000000000 00000000 Delay Import Directory +Entry e 0000000000000000 00000000 CLR Runtime Header +Entry f 0000000000000000 00000000 Reserved + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .reloc 00000000 0000000000000000 0000000000000000 00000000 2**0 + ALLOC, LOAD, READONLY, DATA + 1 .text 000b15d0 0000000000000148 0000000000000148 00000148 2**4 + CONTENTS, ALLOC, LOAD, CODE +SYMBOL TABLE: +no symbols + +Signed-off-by: Maran Wilson +Reviewed-by: Aaron Young +Reviewed-by: Jack Schwartz +Upstream-commit-id: 6df7a8f5609 +--- + shim.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/shim.c b/shim.c +index ae03da7eddf..d980cadacfc 100644 +--- a/shim.c ++++ b/shim.c +@@ -1347,6 +1347,11 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + */ + Section = context.FirstSection; + for (i = 0; i < context.NumberOfSections; i++, Section++) { ++ /* Don't try to copy discardable sections with zero size */ ++ if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) && ++ !Section->Misc.VirtualSize) ++ continue; ++ + base = ImageAddress (buffer, context.ImageSize, + Section->VirtualAddress); + end = ImageAddress (buffer, context.ImageSize, +-- +2.26.2 + diff --git a/SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch b/SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch new file mode 100644 index 0000000..6163a19 --- /dev/null +++ b/SOURCES/0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch @@ -0,0 +1,30 @@ +From d5b72b322d5b7c6c115833c518e1aa5798076309 Mon Sep 17 00:00:00 2001 +From: dann frazier +Date: Mon, 14 Jan 2019 15:25:11 -0700 +Subject: [PATCH 16/62] Fix apparent typo in ARM 32-on-64 code + +The architecture is aarch64, not arch64. + +Fixes: 750584c20775 ("Make 64-on-32 maybe work on x86_64.") +Signed-off-by: dann frazier +Upstream-commit-id: e9f67aaa75a +--- + shim.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/shim.c b/shim.c +index d980cadacfc..e4d4fea226d 100644 +--- a/shim.c ++++ b/shim.c +@@ -150,7 +150,7 @@ allow_32_bit(void) + #endif + #elif defined(__i386__) || defined(__i686__) + return 1; +-#elif defined(__arch64__) ++#elif defined(__aarch64__) + return 0; + #else /* assuming everything else is 32-bit... */ + return 1; +-- +2.26.2 + diff --git a/SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch b/SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch new file mode 100644 index 0000000..961e531 --- /dev/null +++ b/SOURCES/0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch @@ -0,0 +1,32 @@ +From 8544018093b8aa4311b1e970f8396140c22ede0b Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Mon, 14 Jan 2019 19:29:34 +0000 +Subject: [PATCH 17/62] Makefile: do not run git on clean if there's no .git + directory + +When building in minimal chroot on build workers, like in Debian (where +make clean is called at the beginning of the build process), git will +not be available. Skip the git clean. + +Signed-off-by: Luca Boccassi +Upstream-commit-id: be352762a01 +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 3f2105595a6..fd7e83dc764 100644 +--- a/Makefile ++++ b/Makefile +@@ -225,7 +225,7 @@ clean-shim-objs: + @rm -rvf $(TARGET) *.o $(SHIM_OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME) + @rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid + @rm -vf Cryptlib/*.[oa] Cryptlib/*/*.[oa] +- @git clean -f -d -e 'Cryptlib/OpenSSL/*' ++ @if [ -d .git ] ; then git clean -f -d -e 'Cryptlib/OpenSSL/*'; fi + + clean: clean-shim-objs + $(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean +-- +2.26.2 + diff --git a/SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch b/SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch new file mode 100644 index 0000000..e934fa7 --- /dev/null +++ b/SOURCES/0018-Make.default-use-correct-flags-to-disable-unaligned-.patch @@ -0,0 +1,40 @@ +From 7f080b30f3c3718d6b2533f62a50f373fd2cda21 Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Thu, 10 Jan 2019 23:34:11 +0100 +Subject: [PATCH 18/62] Make.default: use correct flags to disable unaligned + access for 32 bit ARM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The GCC flag to disable unaligned access on 32bit ARM is +-mno-unaligned-access, not -mstrict-align (which is used on aarch64): + +https://lkml.org/lkml/2018/8/3/294 + +Otherwise build dies with: +arm-linux-gnueabihf-gcc: error: unrecognized command line option + ‘-mstrict-align’; did you mean ‘-Wstrict-aliasing’? + +Signed-off-by: Peter Korsgaard +Upstream-commit-id: 41b93358e8c +--- + Make.defaults | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Make.defaults b/Make.defaults +index bbfc1d7f77b..09807bd8108 100644 +--- a/Make.defaults ++++ b/Make.defaults +@@ -72,7 +72,7 @@ ifeq ($(ARCH),aarch64) + ARCH_CFLAGS ?= + endif + ifeq ($(ARCH),arm) +- ARCH_CFLAGS ?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align ++ ARCH_CFLAGS ?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mno-unaligned-access + LIBDIR ?= $(prefix)/lib + ARCH_SUFFIX ?= arm + ARCH_SUFFIX_UPPER ?= ARM +-- +2.26.2 + diff --git a/SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch b/SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch new file mode 100644 index 0000000..9ef4f67 --- /dev/null +++ b/SOURCES/0019-Cryptlib-fix-build-on-32bit-ARM.patch @@ -0,0 +1,34 @@ +From ee832f21c6706d6b3890d82f9d8bcb2bd249ee04 Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Fri, 11 Jan 2019 09:17:42 +0100 +Subject: [PATCH 19/62] Cryptlib: fix build on 32bit ARM + +Pass MDE_CPU_ARM, similar to how it is done for the other supported +architectures, otherwise the build fails in: + +Cryptlib/Include/OpenSslSupport.h:55:2: error: + #error Unknown target architecture + +Signed-off-by: Peter Korsgaard +Upstream-commit-id: cb83c14628b +--- + Cryptlib/Makefile | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile +index 2aa569594a0..5c098f34cec 100644 +--- a/Cryptlib/Makefile ++++ b/Cryptlib/Makefile +@@ -19,6 +19,9 @@ endif + ifeq ($(ARCH),aarch64) + CFLAGS += -DMDE_CPU_AARCH64 + endif ++ifeq ($(ARCH),arm) ++ CFLAGS += -DMDE_CPU_ARM ++endif + LDFLAGS = -nostdlib -znocombreloc + + TARGET = libcryptlib.a +-- +2.26.2 + diff --git a/SOURCES/0001-Make-sure-that-MOK-variables-always-get-mirrored.patch b/SOURCES/0020-Make-sure-that-MOK-variables-always-get-mirrored.patch similarity index 90% rename from SOURCES/0001-Make-sure-that-MOK-variables-always-get-mirrored.patch rename to SOURCES/0020-Make-sure-that-MOK-variables-always-get-mirrored.patch index 0779498..ca6f732 100644 --- a/SOURCES/0001-Make-sure-that-MOK-variables-always-get-mirrored.patch +++ b/SOURCES/0020-Make-sure-that-MOK-variables-always-get-mirrored.patch @@ -1,7 +1,7 @@ -From 9ab0d796bdc9cefdaa3b0df7434845d26c43d894 Mon Sep 17 00:00:00 2001 +From ac0400b20264ef67b67891d2216edd3fe20e5571 Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Mon, 5 Nov 2018 14:51:16 +0100 -Subject: [PATCH 1/3] Make sure that MOK variables always get mirrored +Subject: [PATCH 20/62] Make sure that MOK variables always get mirrored Without this, if a Mok variable doesn't exist in Boot Services, it will also not be copied to Runtime, even if we have data to be added to it (vendor cert). @@ -9,6 +9,7 @@ This patch makes sure that if we have extra data to append, we still mirror the variable. Signed-off-by: Patrick Uiterwijk +Upstream-commit-id: 9ab0d796bdc --- mok.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) @@ -56,5 +57,5 @@ index 38675211e0e..00dd1ad3034 100644 if (v->flags & MOK_VARIABLE_MEASURE && present) { /* -- -2.20.1 +2.26.2 diff --git a/SOURCES/0002-mok-fix-the-mirroring-of-RT-variables.patch b/SOURCES/0021-mok-fix-the-mirroring-of-RT-variables.patch similarity index 89% rename from SOURCES/0002-mok-fix-the-mirroring-of-RT-variables.patch rename to SOURCES/0021-mok-fix-the-mirroring-of-RT-variables.patch index fc2adbc..135788e 100644 --- a/SOURCES/0002-mok-fix-the-mirroring-of-RT-variables.patch +++ b/SOURCES/0021-mok-fix-the-mirroring-of-RT-variables.patch @@ -1,7 +1,7 @@ -From 4b27ae034ba9885960e72f77b3f687a9b7fea824 Mon Sep 17 00:00:00 2001 +From f748139695384fb4e09833898f0b8cb3ab85d810 Mon Sep 17 00:00:00 2001 From: Gary Lin Date: Wed, 21 Nov 2018 12:47:43 +0800 -Subject: [PATCH 2/3] mok: fix the mirroring of RT variables +Subject: [PATCH 21/62] mok: fix the mirroring of RT variables When there is no key in MokList, import_mok_state() just skipped MokList even though it should always mirror the vendor cert. Besides, the faulty @@ -11,6 +11,7 @@ MokSBStateRT, and MokIgnoreDB. https://github.com/rhboot/shim/issues/154 Signed-off-by: Gary Lin +Upstream-commit-id: 4b27ae034ba --- mok.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) @@ -45,5 +46,5 @@ index 00dd1ad3034..41925abbb49 100644 LibDeleteVariable(v->rtname, v->guid); -- -2.20.1 +2.26.2 diff --git a/SOURCES/0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch b/SOURCES/0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch similarity index 89% rename from SOURCES/0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch rename to SOURCES/0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch index caded4e..bd8d9cf 100644 --- a/SOURCES/0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch +++ b/SOURCES/0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch @@ -1,20 +1,21 @@ -From 29c11483101b460869a5e0dba1f425073862127d Mon Sep 17 00:00:00 2001 +From ff6e5cda136c8fd637d3d6b8334f4f221ba2b1ee Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 31 Jan 2019 13:45:30 -0500 -Subject: [PATCH 3/3] mok: consolidate mirroring code in a helper instead of +Subject: [PATCH 22/62] mok: consolidate mirroring code in a helper instead of using goto There's no reason to complicate the logic with a goto here, instead just pull the logic we're jumping to out to a helper function. Signed-off-by: Peter Jones +Upstream-commit-id: 29c11483101 --- - mok.c | 41 ++++++++++++++++++++++++++++------------- + mok.c | 42 +++++++++++++++++++++++++++++------------- shim.h | 2 ++ - 2 files changed, 30 insertions(+), 13 deletions(-) + 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/mok.c b/mok.c -index 41925abbb49..2f495e6cf25 100644 +index 41925abbb49..2b9d796a0e8 100644 --- a/mok.c +++ b/mok.c @@ -130,7 +130,8 @@ struct mok_state_variable mok_state_variables[] = { @@ -105,5 +106,5 @@ index 2b359d821e3..c26d5f06538 100644 #ifdef __x86_64__ -- -2.20.1 +2.26.2 diff --git a/SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch b/SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch new file mode 100644 index 0000000..fce8963 --- /dev/null +++ b/SOURCES/0023-shim-only-include-shim_cert.h-in-shim.c.patch @@ -0,0 +1,82 @@ +From 7a3638173e406ce7cbd682213606e3152244fcb2 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Wed, 19 Dec 2018 11:27:42 +0800 +Subject: [PATCH 23/62] shim: only include shim_cert.h in shim.c + +The shim_cert array was declared as a static array, and every user of +shim_cert.h would create a shim_cert array for its own and grow the file +size. To remove the unnecessary duplicate shim_cert arrays, this commit +declares shim_cert in shim.c while other users still can access the +array through the external variables: build_cert and build_cert_size. + +Signed-off-by: Gary Lin +Upstream-commit-id: 4e2d62f0f4e +--- + shim.c | 11 +++++++++++ + shim.h | 7 ++++--- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/shim.c b/shim.c +index e4d4fea226d..0a95f94b360 100644 +--- a/shim.c ++++ b/shim.c +@@ -34,6 +34,9 @@ + */ + + #include "shim.h" ++#if defined(ENABLE_SHIM_CERT) ++#include "shim_cert.h" ++#endif /* defined(ENABLE_SHIM_CERT) */ + + #include + #include +@@ -75,6 +78,10 @@ UINT32 vendor_cert_size; + UINT32 vendor_dbx_size; + UINT8 *vendor_cert; + UINT8 *vendor_dbx; ++#if defined(ENABLE_SHIM_CERT) ++UINT32 build_cert_size; ++UINT8 *build_cert; ++#endif /* defined(ENABLE_SHIM_CERT) */ + + /* + * indicator of how an image has been verified +@@ -2562,6 +2569,10 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) + vendor_dbx_size = cert_table.vendor_dbx_size; + vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset; + vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset; ++#if defined(ENABLE_SHIM_CERT) ++ build_cert_size = sizeof(shim_cert); ++ build_cert = shim_cert; ++#endif /* defined(ENABLE_SHIM_CERT) */ + CHAR16 *msgs[] = { + L"import_mok_state() failed\n", + L"shim_int() failed\n", +diff --git a/shim.h b/shim.h +index c26d5f06538..e4d40505f09 100644 +--- a/shim.h ++++ b/shim.h +@@ -122,9 +122,6 @@ + #include "include/variables.h" + + #include "version.h" +-#ifdef ENABLE_SHIM_CERT +-#include "shim_cert.h" +-#endif + + INTERFACE_DECL(_SHIM_LOCK); + +@@ -172,6 +169,10 @@ extern UINT32 vendor_cert_size; + extern UINT32 vendor_dbx_size; + extern UINT8 *vendor_cert; + extern UINT8 *vendor_dbx; ++#if defined(ENABLE_SHIM_CERT) ++extern UINT32 build_cert_size; ++extern UINT8 *build_cert; ++#endif /* defined(ENABLE_SHIM_CERT) */ + + extern UINT8 user_insecure_mode; + extern UINT8 ignore_db; +-- +2.26.2 + diff --git a/SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch b/SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch new file mode 100644 index 0000000..d331df4 --- /dev/null +++ b/SOURCES/0024-mok-also-mirror-the-build-cert-to-MokListRT.patch @@ -0,0 +1,153 @@ +From 3d62232feb296b238ca5d7963ba40a2c346767e7 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Wed, 19 Dec 2018 12:40:02 +0800 +Subject: [PATCH 24/62] mok: also mirror the build cert to MokListRT + +If the build cert is enabled, we should also mirror it to MokListRT. + +Signed-off-by: Gary Lin +Upstream-commit-id: aecbe1f99b6 +--- + mok.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 72 insertions(+), 6 deletions(-) + +diff --git a/mok.c b/mok.c +index 2b9d796a0e8..6150d8c8868 100644 +--- a/mok.c ++++ b/mok.c +@@ -68,6 +68,10 @@ struct mok_state_variable { + */ + UINT8 **addend_source; + UINT32 *addend_size; ++#if defined(ENABLE_SHIM_CERT) ++ UINT8 **build_cert; ++ UINT32 *build_cert_size; ++#endif /* defined(ENABLE_SHIM_CERT) */ + UINT32 yes_attr; + UINT32 no_attr; + UINT32 flags; +@@ -90,6 +94,10 @@ struct mok_state_variable mok_state_variables[] = { + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .addend_source = &vendor_cert, + .addend_size = &vendor_cert_size, ++#if defined(ENABLE_SHIM_CERT) ++ .build_cert = &build_cert, ++ .build_cert_size = &build_cert_size, ++#endif /* defined(ENABLE_SHIM_CERT) */ + .flags = MOK_MIRROR_KEYDB | + MOK_VARIABLE_LOG, + .pcr = 14, +@@ -130,6 +138,22 @@ struct mok_state_variable mok_state_variables[] = { + { NULL, } + }; + ++inline BOOLEAN check_vendor_cert(struct mok_state_variable *v) ++{ ++ return (v->addend_source && v->addend_size && ++ *v->addend_source && *v->addend_size) ? TRUE : FALSE; ++} ++#if defined(ENABLE_SHIM_CERT) ++inline BOOLEAN check_build_cert(struct mok_state_variable *v) ++{ ++ return (v->build_cert && v->build_cert_size && ++ *v->build_cert && *v->build_cert_size) ? TRUE : FALSE; ++} ++#define check_addend(v) (check_vendor_cert(v) || check_build_cert(v)) ++#else ++#define check_addend(v) check_vendor_cert(v) ++#endif /* defined(ENABLE_SHIM_CERT) */ ++ + static EFI_STATUS nonnull(1) + mirror_one_mok_variable(struct mok_state_variable *v) + { +@@ -138,15 +162,27 @@ mirror_one_mok_variable(struct mok_state_variable *v) + UINTN FullDataSize = 0; + uint8_t *p = NULL; + +- if ((v->flags & MOK_MIRROR_KEYDB) && +- v->addend_source && *v->addend_source && +- v->addend_size && *v->addend_size) { ++ if ((v->flags & MOK_MIRROR_KEYDB) && check_addend(v)) { + EFI_SIGNATURE_LIST *CertList = NULL; + EFI_SIGNATURE_DATA *CertData = NULL; ++#if defined(ENABLE_SHIM_CERT) ++ FullDataSize = v->data_size; ++ if (check_build_cert(v)) { ++ FullDataSize += sizeof (*CertList) ++ + sizeof (EFI_GUID) ++ + *v->build_cert_size; ++ } ++ if (check_vendor_cert(v)) { ++ FullDataSize += sizeof (*CertList) ++ + sizeof (EFI_GUID) ++ + *v->addend_size; ++ } ++#else + FullDataSize = v->data_size + + sizeof (*CertList) + + sizeof (EFI_GUID) + + *v->addend_size; ++#endif /* defined(ENABLE_SHIM_CERT) */ + FullData = AllocatePool(FullDataSize); + if (!FullData) { + perror(L"Failed to allocate space for MokListRT\n"); +@@ -158,6 +194,35 @@ mirror_one_mok_variable(struct mok_state_variable *v) + CopyMem(p, v->data, v->data_size); + p += v->data_size; + } ++ ++#if defined(ENABLE_SHIM_CERT) ++ if (check_build_cert(v) == FALSE) ++ goto skip_build_cert; ++ ++ CertList = (EFI_SIGNATURE_LIST *)p; ++ p += sizeof (*CertList); ++ CertData = (EFI_SIGNATURE_DATA *)p; ++ p += sizeof (EFI_GUID); ++ ++ CertList->SignatureType = EFI_CERT_TYPE_X509_GUID; ++ CertList->SignatureListSize = *v->build_cert_size ++ + sizeof (*CertList) ++ + sizeof (*CertData) ++ -1; ++ CertList->SignatureHeaderSize = 0; ++ CertList->SignatureSize = *v->build_cert_size + ++ sizeof (EFI_GUID); ++ ++ CertData->SignatureOwner = SHIM_LOCK_GUID; ++ CopyMem(p, *v->build_cert, *v->build_cert_size); ++ ++ p += *v->build_cert_size; ++ ++ if (check_vendor_cert(v) == FALSE) ++ goto skip_vendor_cert; ++skip_build_cert: ++#endif /* defined(ENABLE_SHIM_CERT) */ ++ + CertList = (EFI_SIGNATURE_LIST *)p; + p += sizeof (*CertList); + CertData = (EFI_SIGNATURE_DATA *)p; +@@ -174,6 +239,9 @@ mirror_one_mok_variable(struct mok_state_variable *v) + CertData->SignatureOwner = SHIM_LOCK_GUID; + CopyMem(p, *v->addend_source, *v->addend_size); + ++#if defined(ENABLE_SHIM_CERT) ++skip_vendor_cert: ++#endif /* defined(ENABLE_SHIM_CERT) */ + if (v->data && v->data_size) + FreePool(v->data); + v->data = FullData; +@@ -247,9 +315,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + UINT32 attrs = 0; + BOOLEAN delete = FALSE, present, addend; + +- addend = (v->addend_source && v->addend_size && +- *v->addend_source && *v->addend_size) +- ? TRUE : FALSE; ++ addend = check_addend(v); + + efi_status = get_variable_attr(v->name, + &v->data, &v->data_size, +-- +2.26.2 + diff --git a/SOURCES/0025-mok-minor-cleanups.patch b/SOURCES/0025-mok-minor-cleanups.patch new file mode 100644 index 0000000..98120d3 --- /dev/null +++ b/SOURCES/0025-mok-minor-cleanups.patch @@ -0,0 +1,37 @@ +From ff890cf45224926574eee93b0ea1494468870bd3 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 31 Jan 2019 14:04:57 -0500 +Subject: [PATCH 25/62] mok: minor cleanups + +Signed-off-by: Peter Jones +Upstream-commit-id: 617b9007668 +--- + mok.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/mok.c b/mok.c +index 6150d8c8868..59630e74425 100644 +--- a/mok.c ++++ b/mok.c +@@ -138,13 +138,16 @@ struct mok_state_variable mok_state_variables[] = { + { NULL, } + }; + +-inline BOOLEAN check_vendor_cert(struct mok_state_variable *v) ++static inline BOOLEAN nonnull(1) ++check_vendor_cert(struct mok_state_variable *v) + { + return (v->addend_source && v->addend_size && + *v->addend_source && *v->addend_size) ? TRUE : FALSE; + } ++ + #if defined(ENABLE_SHIM_CERT) +-inline BOOLEAN check_build_cert(struct mok_state_variable *v) ++static inline BOOLEAN nonnull(1) ++check_build_cert(struct mok_state_variable *v) + { + return (v->build_cert && v->build_cert_size && + *v->build_cert && *v->build_cert_size) ? TRUE : FALSE; +-- +2.26.2 + diff --git a/SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch b/SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch new file mode 100644 index 0000000..30b8374 --- /dev/null +++ b/SOURCES/0026-Remove-call-to-TPM2-get_event_log.patch @@ -0,0 +1,91 @@ +From cf3f99c3b1e11c8c83938784975331db5efb410f Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 11 Dec 2018 15:25:44 -0800 +Subject: [PATCH 26/62] Remove call to TPM2 get_event_log() + +Calling the TPM2 get_event_log causes the firmware to start logging +events to the final events table, but implementations may also continue +logging to the boot services event log. Any OS that wishes to +reconstruct the full PCR state must already look at both the final +events log and the boot services event log, so if this call is made +anywhere other than immediately before ExitBootServices() then the OS +must deduplicate events that occur in both, complicating things +immensely. + +Linux already has support for copying up the boot services event log +across the ExitBootServices() boundary, so there's no reason to make +this call. Remove it. + +Signed-off-by: Matthew Garrett +Upstream-commit-id: fd7c3bd920b +--- + tpm.c | 46 ---------------------------------------------- + 1 file changed, 46 deletions(-) + +diff --git a/tpm.c b/tpm.c +index 674e69b715f..f07362c70bb 100644 +--- a/tpm.c ++++ b/tpm.c +@@ -70,41 +70,6 @@ static BOOLEAN tpm2_present(EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps, + return FALSE; + } + +-static inline EFI_TCG2_EVENT_LOG_BITMAP +-tpm2_get_supported_logs(efi_tpm2_protocol_t *tpm, +- EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps, +- BOOLEAN old_caps) +-{ +- if (old_caps) +- return ((TREE_BOOT_SERVICE_CAPABILITY *)caps)->SupportedEventLogs; +- +- return caps->SupportedEventLogs; +-} +- +-/* +- * According to TCG EFI Protocol Specification for TPM 2.0 family, +- * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG +- * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka +- * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the +- * internal switch through calling get_event_log() in order to allow +- * to retrieve the logs from OS runtime. +- */ +-static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2, +- EFI_TCG2_EVENT_LOG_BITMAP supported_logs) +-{ +- EFI_TCG2_EVENT_LOG_FORMAT log_fmt; +- EFI_PHYSICAL_ADDRESS start; +- EFI_PHYSICAL_ADDRESS end; +- BOOLEAN truncated; +- +- if (supported_logs & EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) +- log_fmt = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; +- else +- log_fmt = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; +- +- return tpm2->get_event_log(tpm2, log_fmt, &start, &end, &truncated); +-} +- + static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm, + efi_tpm2_protocol_t **tpm2, + BOOLEAN *old_caps_p, +@@ -166,17 +131,6 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, + #endif + } else if (tpm2) { + EFI_TCG2_EVENT *event; +- EFI_TCG2_EVENT_LOG_BITMAP supported_logs; +- +- supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps); +- +- efi_status = trigger_tcg2_final_events_table(tpm2, +- supported_logs); +- if (EFI_ERROR(efi_status)) { +- perror(L"Unable to trigger tcg2 final events table: %r\n", +- efi_status); +- return efi_status; +- } + + event = AllocatePool(sizeof(*event) + logsize); + if (!event) { +-- +2.26.2 + diff --git a/SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch b/SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch new file mode 100644 index 0000000..d07e6e2 --- /dev/null +++ b/SOURCES/0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch @@ -0,0 +1,48 @@ +From 95bd1d88003a9a7c2732472b061ad2a9c7140419 Mon Sep 17 00:00:00 2001 +From: Patrick Uiterwijk +Date: Thu, 6 Dec 2018 10:08:45 +0100 +Subject: [PATCH 27/62] Make EFI variable copying fatal only on secureboot + enabled systems + +I have come across systems that are unwilling to reserve enough memory for +a MokListRT big enough for big certificates. +This seems to be the case with firmware implementations that do not support +secureboot, which is probably the reason they went with much lower variable +storage. + +This patch set makes sure we can still boot on those systems, by only +making the copy action fatal if the system has secure boot enabled, or if +the error was anything other than EFI_INVALID_PARAMETER. + +Signed-off-by: Patrick Uiterwijk +Upstream-commit-id: 741c61abba7 +--- + shim.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/shim.c b/shim.c +index 0a95f94b360..d4ed332f901 100644 +--- a/shim.c ++++ b/shim.c +@@ -2609,7 +2609,17 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) + * boot-services-only state variables are what we think they are. + */ + efi_status = import_mok_state(image_handle); +- if (EFI_ERROR(efi_status)) { ++ if (!secure_mode() && efi_status == EFI_INVALID_PARAMETER) { ++ /* ++ * Make copy failures fatal only if secure_mode is enabled, or ++ * the error was anything else than EFI_INVALID_PARAMETER. ++ * There are non-secureboot firmware implementations that don't ++ * reserve enough EFI variable memory to fit the variable. ++ */ ++ console_print(L"Importing MOK states has failed: %s: %r\n", ++ msgs[msg], efi_status); ++ console_print(L"Continuing boot since secure mode is disabled"); ++ } else if (EFI_ERROR(efi_status)) { + die: + console_print(L"Something has gone seriously wrong: %s: %r\n", + msgs[msg], efi_status); +-- +2.26.2 + diff --git a/SOURCES/0004-Make-VLogError-behave-as-expected.patch b/SOURCES/0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch similarity index 59% rename from SOURCES/0004-Make-VLogError-behave-as-expected.patch rename to SOURCES/0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch index 2e5ca64..c671a9a 100644 --- a/SOURCES/0004-Make-VLogError-behave-as-expected.patch +++ b/SOURCES/0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch @@ -1,9 +1,25 @@ -From 0bff94b170116737e6e0838c35c0ac376542a5c0 Mon Sep 17 00:00:00 2001 +From 344a8364cb05cdaafc43231d0f73d5217c4e118c Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 12 Feb 2019 18:04:49 -0500 -Subject: [PATCH 4/4] Make VLogError() behave as expected. +Subject: [PATCH 28/62] VLogError(): Avoid NULL pointer dereferences in + (V)Sprint calls + +VLogError() calculates the size of format strings by using calls to +SPrint and VSPrint with a StrSize of 0 and NULL for an output buffer. +Unfortunately, this is an incorrect usage of (V)Sprint. A StrSize +of "0" is special-cased to mean "there is no limit". So, we end up +writing our string to address 0x0. This was discovered because it +causes a crash on ARM where, unlike x86, it does not necessarily +have memory mapped at 0x0. + +Avoid the (V)Sprint calls altogether by using (V)PoolPrint, which +handles the size calculation and allocation for us. Signed-off-by: Peter Jones +Fixes: 25f6fd08cd26 ("try to show errors more usefully.") +[dannf: commit message ] +Signed-off-by: dann frazier +Upstream-commit-id: 20e731f423a --- errlog.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) @@ -46,5 +62,5 @@ index 18be4822d53..eebb266d396 100644 nerrs += 2; -- -2.20.1 +2.26.2 diff --git a/SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch b/SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch new file mode 100644 index 0000000..617ae6a --- /dev/null +++ b/SOURCES/0029-Once-again-try-even-harder-to-get-binaries-without-t.patch @@ -0,0 +1,98 @@ +From 10d6e3d90f1ea504a1dedaea50478c444e92951c Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Mar 2019 09:52:02 -0400 +Subject: [PATCH 29/62] Once again, try even harder to get binaries without + timestamps in them. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +$ objdump -x /builddir/build/BUILDROOT/shim-*/usr/share/shim/*/shimx64.efi | grep 'Time/Date' +Time/Date Thu Jan 1 00:00:08 1970 +$ _ + +"What is despair? I have known it—hear my song. Despair is when you’re +debugging a kernel driver and you look at a memory dump and you see that +a pointer has a value of 7." + - http://scholar.harvard.edu/files/mickens/files/thenightwatch.pdf + +objcopy only knows about -D for some targets. +ld only believes in --no-insert-timestamp in some versions. +dd takes off and nukes the site from orbit. + +It's the only way to be sure. + +Signed-off-by: Peter Jones +Upstream-commit-id: a4a1fbe728c +--- + Make.defaults | 4 ++++ + Makefile | 6 ++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/Make.defaults b/Make.defaults +index 09807bd8108..f0bfa9fd573 100644 +--- a/Make.defaults ++++ b/Make.defaults +@@ -50,6 +50,7 @@ ifeq ($(ARCH),x86_64) + ARCH_SUFFIX ?= x64 + ARCH_SUFFIX_UPPER ?= X64 + ARCH_LDFLAGS ?= ++ TIMESTAMP_LOCATION := 136 + endif + ifeq ($(ARCH),ia32) + ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \ +@@ -60,6 +61,7 @@ ifeq ($(ARCH),ia32) + ARCH_SUFFIX_UPPER ?= IA32 + ARCH_LDFLAGS ?= + ARCH_CFLAGS ?= -m32 ++ TIMESTAMP_LOCATION := 136 + endif + ifeq ($(ARCH),aarch64) + ARCH_CFLAGS ?= -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align +@@ -70,6 +72,7 @@ ifeq ($(ARCH),aarch64) + SUBSYSTEM := 0xa + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) + ARCH_CFLAGS ?= ++ TIMESTAMP_LOCATION := 72 + endif + ifeq ($(ARCH),arm) + ARCH_CFLAGS ?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mno-unaligned-access +@@ -79,6 +82,7 @@ ifeq ($(ARCH),arm) + FORMAT := -O binary + SUBSYSTEM := 0xa + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) ++ TIMESTAMP_LOCATION := 72 + endif + + CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ +diff --git a/Makefile b/Makefile +index fd7e83dc764..49e14a26521 100644 +--- a/Makefile ++++ b/Makefile +@@ -189,11 +189,13 @@ endif + ifneq ($(OBJCOPY_GTE224),1) + $(error objcopy >= 2.24 is required) + endif +- $(OBJCOPY) -j .text -j .sdata -j .data -j .data.ident \ ++ $(OBJCOPY) -D -j .text -j .sdata -j .data -j .data.ident \ + -j .dynamic -j .dynsym -j .rel* \ + -j .rela* -j .reloc -j .eh_frame \ + -j .vendor_cert \ + $(FORMAT) $^ $@ ++ # I am tired of wasting my time fighting binutils timestamp code. ++ dd conv=notrunc bs=1 count=4 seek=$(TIMESTAMP_LOCATION) if=/dev/zero of=$@ + + ifneq ($(origin ENABLE_SHIM_HASH),undefined) + %.hash : %.efi +@@ -204,7 +206,7 @@ endif + ifneq ($(OBJCOPY_GTE224),1) + $(error objcopy >= 2.24 is required) + endif +- $(OBJCOPY) -j .text -j .sdata -j .data \ ++ $(OBJCOPY) -D -j .text -j .sdata -j .data \ + -j .dynamic -j .dynsym -j .rel* \ + -j .rela* -j .reloc -j .eh_frame \ + -j .debug_info -j .debug_abbrev -j .debug_aranges \ +-- +2.26.2 + diff --git a/SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch b/SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch new file mode 100644 index 0000000..ba8c278 --- /dev/null +++ b/SOURCES/0030-shim-Rework-pause-functions-and-add-read_counter.patch @@ -0,0 +1,280 @@ +From 1b382ef850de5a6c59b192c146a0e8d898d2d961 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 23 Oct 2018 18:17:57 -0400 +Subject: [PATCH 30/62] shim: Rework pause functions and add read_counter() + +Signed-off-by: Peter Jones +Upstream-commit-id: fc6b0bca84e +--- + shim.c | 4 +- + include/asm.h | 59 +++++++++++++++++ + include/compiler.h | 156 +++++++++++++++++++++++++++++++++++++++++++++ + shim.h | 1 + + 4 files changed, 217 insertions(+), 3 deletions(-) + create mode 100644 include/asm.h + create mode 100644 include/compiler.h + +diff --git a/shim.c b/shim.c +index d4ed332f901..f69e69487fc 100644 +--- a/shim.c ++++ b/shim.c +@@ -2543,16 +2543,14 @@ debug_hook(void) + #if defined(__x86_64__) || defined(__i386__) || defined(__i686__) + if (x > 4294967294ULL) + break; +- __asm__ __volatile__("pause"); + #elif defined(__aarch64__) + if (x > 1000) + break; +- __asm__ __volatile__("wfi"); + #else + if (x > 12000) + break; +- msleep(5000); + #endif ++ pause(); + } + x = 1; + } +diff --git a/include/asm.h b/include/asm.h +new file mode 100644 +index 00000000000..5e8f9ed9d7c +--- /dev/null ++++ b/include/asm.h +@@ -0,0 +1,59 @@ ++/* ++ * asm.h ++ * Copyright 2018 Peter Jones ++ */ ++ ++#ifndef SHIM_ASM_H_ ++#define SHIM_ASM_H_ ++ ++#define __stringify_1(x...) #x ++#define __stringify(x...) __stringify_1(x) ++ ++static inline uint64_t read_counter(void) ++{ ++ uint64_t val; ++#if defined (__x86_64__) ++ unsigned long low, high; ++ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)); ++ val = (low) | (high) << 32; ++#elif defined(__i386__) || defined(__i686__) ++ __asm__ __volatile__("rdtsc" : "=A" (val)); ++#elif defined(__aarch64__) ++ __asm__ __volatile__ ("mrs %0, pmccntr_el0" : "=r" (val)); ++#elif defined(__arm__) ++ __asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); ++#else ++#error unsupported arch ++#endif ++ return val; ++} ++ ++#if defined(__x86_64__) || defined(__i386__) || defined(__i686__) ++static inline void pause(void) ++{ ++ __asm__ __volatile__("pause"); ++} ++#elif defined(__aarch64__) ++static inline void pause(void) ++{ ++ __asm__ __volatile__("wfi"); ++} ++#else ++static inline void pause(void) ++{ ++ uint64_t a, b; ++ int x; ++ extern void msleep(unsigned long msecs); ++ ++ a = read_counter(); ++ for (x = 0; x < 1000; x++) { ++ msleep(1000); ++ b = read_counter(); ++ if (a != b) ++ break; ++ } ++} ++#endif ++ ++#endif /* !SHIM_ASM_H_ */ ++// vim:fenc=utf-8:tw=75:et +diff --git a/include/compiler.h b/include/compiler.h +new file mode 100644 +index 00000000000..a2a0859379f +--- /dev/null ++++ b/include/compiler.h +@@ -0,0 +1,156 @@ ++/* ++ * compiler.h ++ * Copyright 2019 Peter Jones ++ */ ++ ++#ifndef COMPILER_H_ ++#define COMPILER_H_ ++ ++#ifndef UNUSED ++#define UNUSED __attribute__((__unused__)) ++#endif ++#ifndef HIDDEN ++#define HIDDEN __attribute__((__visibility__ ("hidden"))) ++#endif ++#ifndef PUBLIC ++#define PUBLIC __attribute__((__visibility__ ("default"))) ++#endif ++#ifndef DESTRUCTOR ++#define DESTRUCTOR __attribute__((destructor)) ++#endif ++#ifndef CONSTRUCTOR ++#define CONSTRUCTOR __attribute__((constructor)) ++#endif ++#ifndef ALIAS ++#define ALIAS(x) __attribute__((weak, alias (#x))) ++#endif ++#ifndef NONNULL ++#endif ++#define NONNULL(first, args...) __attribute__((__nonnull__(first, ## args))) ++#ifndef PRINTF ++#define PRINTF(first, args...) __attribute__((__format__(printf, first, ## args))) ++#endif ++#ifndef FLATTEN ++#define FLATTEN __attribute__((__flatten__)) ++#endif ++#ifndef PACKED ++#define PACKED __attribute__((__packed__)) ++#endif ++#ifndef VERSION ++#define VERSION(sym, ver) __asm__(".symver " # sym "," # ver) ++#endif ++#ifndef NORETURN ++#define NORETURN __attribute__((__noreturn__)) ++#endif ++#ifndef ALIGNED ++#define ALIGNED(n) __attribute__((__aligned__(n))) ++#endif ++#ifndef CLEANUP_FUNC ++#define CLEANUP_FUNC(x) __attribute__((__cleanup__(x))) ++#endif ++#ifndef USED ++#define USED __attribute__((__used__)) ++#endif ++#ifndef SECTION ++#define SECTION(x) __attribute__((__section__(x))) ++#endif ++#ifndef OPTIMIZE ++#define OPTIMIZE(x) __attribute__((__optimize__(x))) ++#endif ++ ++#ifndef __CONCAT ++#define __CONCAT3(a, b, c) a ## b ## c ++#endif ++#ifndef CAT ++#define CAT(a, b) __CONCAT(a, b) ++#endif ++#ifndef CAT3 ++#define CAT3(a, b, c) __CONCAT3(a, b, c) ++#endif ++#ifndef STRING ++#define STRING(x) __STRING(x) ++#endif ++ ++#ifndef WRITE_ONCE ++#define WRITE_ONCE(var, val) \ ++ (*((volatile typeof(val) *)(&(var))) = (val)) ++#endif ++ ++#ifndef READ_ONCE ++#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) ++#endif ++ ++#ifndef likely ++#define likely(x) __builtin_expect(!!(x), 1) ++#endif ++ ++#ifndef unlikely ++#define unlikely(x) __builtin_expect(!!(x), 0) ++#endif ++ ++/* Are two types/vars the same type (ignoring qualifiers)? */ ++#ifndef __same_type ++#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) ++#endif ++ ++/* Compile time object size, -1 for unknown */ ++#ifndef __compiletime_object_size ++# define __compiletime_object_size(obj) -1 ++#endif ++#ifndef __compiletime_warning ++# define __compiletime_warning(message) ++#endif ++#ifndef __compiletime_error ++# define __compiletime_error(message) ++#endif ++ ++#ifndef __compiletime_assert ++#define __compiletime_assert(condition, msg, prefix, suffix) \ ++ do { \ ++ extern void prefix ## suffix(void) __compiletime_error(msg); \ ++ if (!(condition)) \ ++ prefix ## suffix(); \ ++ } while (0) ++#endif ++ ++#ifndef _compiletime_assert ++#define _compiletime_assert(condition, msg, prefix, suffix) \ ++ __compiletime_assert(condition, msg, prefix, suffix) ++#endif ++ ++/** ++ * compiletime_assert - break build and emit msg if condition is false ++ * @condition: a compile-time constant condition to check ++ * @msg: a message to emit if condition is false ++ * ++ * In tradition of POSIX assert, this macro will break the build if the ++ * supplied condition is *false*, emitting the supplied error message if the ++ * compiler has support to do so. ++ */ ++#ifndef compiletime_assert ++#define compiletime_assert(condition, msg) \ ++ _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ++#endif ++ ++/** ++ * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied ++ * error message. ++ * @condition: the condition which the compiler should know is false. ++ * ++ * See BUILD_BUG_ON for description. ++ */ ++#ifndef BUILD_BUG_ON_MSG ++#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ++#endif ++ ++#ifndef ALIGN ++#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) ++#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) ++#define ALIGN(x, a) __ALIGN((x), (a)) ++#endif ++#ifndef ALIGN_DOWN ++#define ALIGN_DOWN(x, a) __ALIGN((x) - ((a) - 1), (a)) ++#endif ++ ++#endif /* !COMPILER_H_ */ ++// vim:fenc=utf-8:tw=75:et +diff --git a/shim.h b/shim.h +index e4d40505f09..a0fa5a75e7e 100644 +--- a/shim.h ++++ b/shim.h +@@ -97,6 +97,7 @@ + #define FALLBACK L"\\fb" EFI_ARCH L".efi" + #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" + ++#include "include/asm.h" + #include "include/configtable.h" + #include "include/console.h" + #include "include/crypt_blowfish.h" +-- +2.26.2 + diff --git a/SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch b/SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch new file mode 100644 index 0000000..16f472f --- /dev/null +++ b/SOURCES/0031-Hook-exit-when-shim_lock-protocol-installed.patch @@ -0,0 +1,49 @@ +From b5e10f70c7a495dc1788e3604803ee633f1e5f76 Mon Sep 17 00:00:00 2001 +From: Stuart Hayes +Date: Fri, 8 Feb 2019 15:48:20 -0500 +Subject: [PATCH 31/62] Hook exit when shim_lock protocol installed + +A recent commit moved where the shim_lock protocol is loaded and +unloaded, but did not move where exit was hooked and unhooked. Exit +needs to be hooked when the protocol is installed, so that the protocol +will be uninstalled on exit. Otherwise, the system can crash if, for +example, shim loads grub, the user exits grub, shim is run again, which +installs a second instance of the protocol, and then grub tries to use +the shim_lock protocol that was installed by the first instance of shim. + +Signed-off-by: Stuart Hayes +Upstream-commit-id: 06c92591e94 +--- + shim.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index f69e69487fc..16911a37b17 100644 +--- a/shim.c ++++ b/shim.c +@@ -2474,9 +2474,9 @@ shim_init(void) + loader_is_participating = 0; + } + +- hook_exit(systab); + } + ++ hook_exit(systab); + return install_shim_protocols(); + } + +@@ -2494,9 +2494,10 @@ shim_fini(void) + * Remove our hooks from system services. + */ + unhook_system_services(); +- unhook_exit(); + } + ++ unhook_exit(); ++ + /* + * Free the space allocated for the alternative 2nd stage loader + */ +-- +2.26.2 + diff --git a/SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch b/SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch new file mode 100644 index 0000000..f7696a3 --- /dev/null +++ b/SOURCES/0032-Work-around-stuff-Waddress-of-packed-member-finds.patch @@ -0,0 +1,89 @@ +From 2cbf56b82a5102777b37c4f7f47c8cf058cea027 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 13 May 2019 16:34:35 -0400 +Subject: [PATCH 32/62] Work around stuff -Waddress-of-packed-member finds. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In MokManager we get a lot of these: + +../src/MokManager.c:1063:19: error: taking address of packed member of ‘struct ’ may result in an unaligned pointer value [-Werror=address-of-packed-member] + 1063 | if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) + | ^~~~~~~~~~~~~~~ + +The reason for this is that gnu-efi takes EFI_GUID * as its argument +instead of VOID *, and there's nothing telling the compiler that it +doesn't have alignment constraints on the input, so the compiler wants +it to have 16-byte alignment. + +Just use CompareMem() for these, as that's all CompareGuid is calling +anyway. + +Signed-off-by: Peter Jones +Upstream-commit-id: 08c14376b59 +--- + MokManager.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index df9b6fe6912..a1bd39a68e2 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -22,6 +22,8 @@ + #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" + #define HASH_STRING L"Select a file to trust:\n\n" + ++#define CompareMemberGuid(x, y) CompareMem(x, y, sizeof(EFI_GUID)) ++ + typedef struct { + UINT32 MokSize; + UINT8 *Mok; +@@ -1077,7 +1079,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + continue; + + DataSize += sizeof(EFI_SIGNATURE_LIST); +- if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) ++ if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } +@@ -1099,7 +1101,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + CertList->SignatureType = list[i].Type; + CertList->SignatureHeaderSize = 0; + +- if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) { ++ if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) { + CertList->SignatureListSize = list[i].MokSize + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = +@@ -1140,7 +1142,7 @@ static void delete_cert(void *key, UINT32 key_size, + int i; + + for (i = 0; i < mok_num; i++) { +- if (CompareGuid(&(mok[i].Type), &X509_GUID) != 0) ++ if (CompareMemberGuid(&(mok[i].Type), &X509_GUID) != 0) + continue; + + if (mok[i].MokSize == key_size && +@@ -1191,7 +1193,7 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + sig_size = hash_size + sizeof(EFI_GUID); + + for (i = 0; i < mok_num; i++) { +- if ((CompareGuid(&(mok[i].Type), &Type) != 0) || ++ if ((CompareMemberGuid(&(mok[i].Type), &Type) != 0) || + (mok[i].MokSize < sig_size)) + continue; + +@@ -1355,7 +1357,7 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- if (CompareGuid(&(del_key[i].Type), &X509_GUID) == 0) { ++ if (CompareMemberGuid(&(del_key[i].Type), &X509_GUID) == 0) { + delete_cert(del_key[i].Mok, del_key[i].MokSize, + mok, mok_num); + } else if (is_sha2_hash(del_key[i].Type)) { +-- +2.26.2 + diff --git a/SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch b/SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch new file mode 100644 index 0000000..e79afa1 --- /dev/null +++ b/SOURCES/0033-Fix-a-use-of-strlen-instead-of-Strlen.patch @@ -0,0 +1,27 @@ +From c372ec7a254147f70d62c1f72da5806d42df6994 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 5 Sep 2019 10:36:23 -0400 +Subject: [PATCH 33/62] Fix a use of strlen() instead of Strlen() + +Signed-off-by: Peter Jones +Upstream-commit-id: 1870bae7960 +--- + shim.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/shim.c b/shim.c +index 16911a37b17..a0eb19b91fe 100644 +--- a/shim.c ++++ b/shim.c +@@ -2118,7 +2118,7 @@ static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path) + + dprint(L"dppath: %s\n", dppath); + dprint(L"path: %s\n", path); +- if (StrnCaseCmp(dppath, PathName, strlen(dppath))) ++ if (StrnCaseCmp(dppath, PathName, StrLen(dppath))) + ret = 0; + + done: +-- +2.26.2 + diff --git a/SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch b/SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch new file mode 100644 index 0000000..43a2c6e --- /dev/null +++ b/SOURCES/0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch @@ -0,0 +1,72 @@ +From 5d30a31fef4eb7e773da24c5e6c20576282a9c3a Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Tue, 26 Feb 2019 11:33:53 +0800 +Subject: [PATCH 34/62] MokManager: Use CompareMem on MokListNode.Type instead + of CompareGuid + +Fix the errors from gcc9 '-Werror=address-of-packed-member' + +https://github.com/rhboot/shim/issues/161 + +Signed-off-by: Gary Lin +Upstream-commit-id: aaa09b35e73 +--- + MokManager.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index a1bd39a68e2..30192c16789 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1079,7 +1079,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + continue; + + DataSize += sizeof(EFI_SIGNATURE_LIST); +- if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) ++ if (CompareMem(&(list[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) == 0) + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } +@@ -1101,7 +1102,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + CertList->SignatureType = list[i].Type; + CertList->SignatureHeaderSize = 0; + +- if (CompareMemberGuid(&(list[i].Type), &X509_GUID) == 0) { ++ if (CompareMem(&(list[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) == 0) { + CertList->SignatureListSize = list[i].MokSize + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = +@@ -1142,7 +1144,8 @@ static void delete_cert(void *key, UINT32 key_size, + int i; + + for (i = 0; i < mok_num; i++) { +- if (CompareMemberGuid(&(mok[i].Type), &X509_GUID) != 0) ++ if (CompareMem(&(mok[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) != 0) + continue; + + if (mok[i].MokSize == key_size && +@@ -1193,7 +1196,7 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + sig_size = hash_size + sizeof(EFI_GUID); + + for (i = 0; i < mok_num; i++) { +- if ((CompareMemberGuid(&(mok[i].Type), &Type) != 0) || ++ if ((CompareMem(&(mok[i].Type), &Type, sizeof(EFI_GUID)) != 0) || + (mok[i].MokSize < sig_size)) + continue; + +@@ -1357,7 +1360,8 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- if (CompareMemberGuid(&(del_key[i].Type), &X509_GUID) == 0) { ++ if (CompareMem(&(del_key[i].Type), &X509_GUID, ++ sizeof(EFI_GUID)) == 0) { + delete_cert(del_key[i].Mok, del_key[i].MokSize, + mok, mok_num); + } else if (is_sha2_hash(del_key[i].Type)) { +-- +2.26.2 + diff --git a/SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch b/SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch new file mode 100644 index 0000000..0efaac9 --- /dev/null +++ b/SOURCES/0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch @@ -0,0 +1,32 @@ +From 44b211bcf7ad58ff29e6495e1c3978e4660cb7d1 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 15 Jan 2019 18:04:34 -0500 +Subject: [PATCH 35/62] OpenSSL: always provide OBJ_create() with name strings. + +Some versions of OpenSSL seem to go back and forth as to whether NULL +for these names are okay. Don't risk it. + +Signed-off-by: Peter Jones +Upstream-commit-id: 46b76a01717 +--- + shim.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/shim.c b/shim.c +index a0eb19b91fe..d7ee2b6de6f 100644 +--- a/shim.c ++++ b/shim.c +@@ -388,7 +388,9 @@ static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize) + EXTENDED_KEY_USAGE *eku; + ASN1_OBJECT *module_signing; + +- module_signing = OBJ_nid2obj(OBJ_create(OID_EKU_MODSIGN, NULL, NULL)); ++ module_signing = OBJ_nid2obj(OBJ_create(OID_EKU_MODSIGN, ++ "modsign-eku", ++ "modsign-eku")); + + x509 = d2i_X509 (NULL, &Temp, (long) CertSize); + if (x509 != NULL) { +-- +2.26.2 + diff --git a/SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch b/SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch new file mode 100644 index 0000000..6ba6995 --- /dev/null +++ b/SOURCES/0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch @@ -0,0 +1,42 @@ +From 07de085dabab8daaea589b597e3915893cc98445 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Forsman?= +Date: Fri, 26 Apr 2019 11:41:02 +0200 +Subject: [PATCH 36/62] Use portable shebangs: /bin/bash -> /usr/bin/env bash + +Upstream-commit-id: 6a73ca814af +--- + Cryptlib/update.sh | 2 +- + make-certs | 4 +++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/Cryptlib/update.sh b/Cryptlib/update.sh +index 31a082d4db6..7ea59831a06 100755 +--- a/Cryptlib/update.sh ++++ b/Cryptlib/update.sh +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/usr/bin/env bash + + DIR=$1 + OPENSSL_VERSION="1.0.2k" +diff --git a/make-certs b/make-certs +index 3e9293b2497..6f40b234d6a 100755 +--- a/make-certs ++++ b/make-certs +@@ -1,10 +1,12 @@ +-#!/bin/bash -e ++#!/usr/bin/env bash + # + # Generate a root CA cert for signing, and then a subject cert. + # Usage: make-certs.sh hostname [user[@domain]] [more ...] + # For testing only, probably still has some bugs in it. + # + ++set -e ++ + DOMAIN=xn--u4h.net + DAYS=365 + KEYTYPE=RSA +-- +2.26.2 + diff --git a/SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch b/SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch new file mode 100644 index 0000000..a2619ab --- /dev/null +++ b/SOURCES/0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch @@ -0,0 +1,44 @@ +From 6fd8db6bb3b23b9e41f109135253f77263071f46 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Sat, 22 Jun 2019 15:33:03 +0100 +Subject: [PATCH 37/62] tpm: Fix off-by-one error when calculating event size + +tpm_log_event_raw() allocates a buffer for the EFI_TCG2_EVENT structure +that is one byte larger than necessary, and sets event->Size accordingly. +The result of this is that the event data recorded in the log differs +from the data that is measured to the TPM (it has an extra zero byte +at the end). + +Upstream-commit-id: 8a27a4809a6 +--- + tpm.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tpm.c b/tpm.c +index f07362c70bb..516fb876caa 100644 +--- a/tpm.c ++++ b/tpm.c +@@ -131,8 +131,10 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, + #endif + } else if (tpm2) { + EFI_TCG2_EVENT *event; ++ UINTN event_size = sizeof(*event) - sizeof(event->Event) + ++ logsize; + +- event = AllocatePool(sizeof(*event) + logsize); ++ event = AllocatePool(event_size); + if (!event) { + perror(L"Unable to allocate event structure\n"); + return EFI_OUT_OF_RESOURCES; +@@ -142,7 +144,7 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, + event->Header.HeaderVersion = 1; + event->Header.PCRIndex = pcr; + event->Header.EventType = type; +- event->Size = sizeof(*event) - sizeof(event->Event) + logsize + 1; ++ event->Size = event_size; + CopyMem(event->Event, (VOID *)log, logsize); + if (hash) { + /* TPM 2 systems will generate the appropriate hash +-- +2.26.2 + diff --git a/SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch b/SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch new file mode 100644 index 0000000..71b98a9 --- /dev/null +++ b/SOURCES/0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch @@ -0,0 +1,36 @@ +From 9f80be9f16a854e3946568fa92edebe26eb79e78 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Sat, 22 Jun 2019 15:37:29 +0100 +Subject: [PATCH 38/62] tpm: Define EFI_VARIABLE_DATA_TREE as packed + +tpm_measure_variable() calculates VarLogSize by adding the size of VarName +and VarData to the size of EFI_VARIABLE_DATA_TREE, and then subtracting +the size of the UnicodeName and VariableData members. This results in a +calculation that is 5 bytes larger than necessary because it doesn't take +in to account the padding of these members. The effect of this is that +shim measures an additional 5 zero bytes when measuring UEFI variables +(at least on 64-bit architectures). + +Byte packing EFI_VARIABLE_DATA_TREE fixes this. + +Upstream-commit-id: 7e4d3f1c8c7 +--- + tpm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tpm.c b/tpm.c +index 516fb876caa..c0617bb479e 100644 +--- a/tpm.c ++++ b/tpm.c +@@ -233,7 +233,7 @@ typedef struct { + UINT64 VariableDataLength; + CHAR16 UnicodeName[1]; + INT8 VariableData[1]; +-} EFI_VARIABLE_DATA_TREE; ++} __attribute__ ((packed)) EFI_VARIABLE_DATA_TREE; + + static BOOLEAN tpm_data_measured(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData) + { +-- +2.26.2 + diff --git a/SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch b/SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch new file mode 100644 index 0000000..a71b643 --- /dev/null +++ b/SOURCES/0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch @@ -0,0 +1,223 @@ +From 55163bc82c5179adb109c3d8b982c2689d68b4c9 Mon Sep 17 00:00:00 2001 +From: Ivan Hu +Date: Fri, 10 May 2019 17:50:12 +0800 +Subject: [PATCH 39/62] MokManager: console mode modification for hi-dpi screen + devices + +There are lots of hi-dpi laptops nowadays, as doing mok enrollment, the font +is too small to see. +https://bugs.launchpad.net/ubuntu/+source/shim/+bug/1822043 + +This patch checks if the resolution is larger than Full HD (1920x1080) and +current console output columns and rows is in a good mode. Then swith the +console output to a better mode. + +Signed-off-by: Ivan Hu +Upstream-commit-id: cf05af6d899 +--- + MokManager.c | 2 + + lib/console.c | 161 +++++++++++++++++++++++++++++++++++++++++++++- + include/console.h | 2 + + 3 files changed, 164 insertions(+), 1 deletion(-) + +diff --git a/MokManager.c b/MokManager.c +index 30192c16789..78da9fd95ee 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -2560,6 +2560,8 @@ EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * systab) + + setup_rand(); + ++ console_mode_handle(); ++ + efi_status = check_mok_request(image_handle); + + console_fini(); +diff --git a/lib/console.c b/lib/console.c +index 3aee41cd276..c92d27f3c86 100644 +--- a/lib/console.c ++++ b/lib/console.c +@@ -409,7 +409,166 @@ console_notify(CHAR16 *string) + console_alertbox(str_arr); + } + +-#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) ++void ++console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) ++{ ++ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; ++ ++ if (!SavedMode) { ++ console_print(L"Invalid parameter: SavedMode\n"); ++ return; ++ } ++ ++ CopyMem(SavedMode, co->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); ++ co->EnableCursor(co, FALSE); ++ co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); ++} ++ ++void ++console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) ++{ ++ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; ++ ++ co->EnableCursor(co, SavedMode->CursorVisible); ++ co->SetCursorPosition(co, SavedMode->CursorColumn, ++ SavedMode->CursorRow); ++ co->SetAttribute(co, SavedMode->Attribute); ++} ++ ++int ++console_countdown(CHAR16* title, const CHAR16* message, int timeout) ++{ ++ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; ++ SIMPLE_INPUT_INTERFACE *ci = ST->ConIn; ++ SIMPLE_TEXT_OUTPUT_MODE SavedMode; ++ EFI_INPUT_KEY key; ++ EFI_STATUS efi_status; ++ UINTN cols, rows; ++ CHAR16 *titles[2]; ++ int wait = 10000000; ++ ++ console_save_and_set_mode(&SavedMode); ++ ++ titles[0] = title; ++ titles[1] = NULL; ++ ++ console_print_box_at(titles, -1, 0, 0, -1, -1, 1, 1); ++ ++ co->QueryMode(co, co->Mode->Mode, &cols, &rows); ++ ++ console_print_at((cols - StrLen(message)) / 2, rows / 2, message); ++ while (1) { ++ if (timeout > 1) ++ console_print_at(2, rows - 3, ++ L"Booting in %d seconds ", ++ timeout); ++ else if (timeout) ++ console_print_at(2, rows - 3, ++ L"Booting in %d second ", ++ timeout); ++ ++ efi_status = WaitForSingleEvent(ci->WaitForKey, wait); ++ if (efi_status != EFI_TIMEOUT) { ++ /* Clear the key in the queue */ ++ ci->ReadKeyStroke(ci, &key); ++ break; ++ } ++ ++ timeout--; ++ if (!timeout) ++ break; ++ } ++ ++ console_restore_mode(&SavedMode); ++ ++ return timeout; ++} ++ ++#define HORIZONTAL_MAX_OK 1920 ++#define VERTICAL_MAX_OK 1080 ++#define COLUMNS_MAX_OK 200 ++#define ROWS_MAX_OK 100 ++ ++void ++console_mode_handle(VOID) ++{ ++ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; ++ EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; ++ EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; ++ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; ++ ++ UINTN mode_set; ++ UINTN rows = 0, columns = 0; ++ EFI_STATUS efi_status = EFI_SUCCESS; ++ ++ efi_status = gBS->LocateProtocol(&gop_guid, NULL, (void **)&gop); ++ if (EFI_ERROR(efi_status)) { ++ console_error(L"Locate graphic output protocol fail", efi_status); ++ return; ++ } ++ ++ Info = gop->Mode->Info; ++ ++ /* ++ * Start verifying if we are in a resolution larger than Full HD ++ * (1920x1080). If we're not, assume we're in a good mode and do not ++ * try to change it. ++ */ ++ if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK && ++ Info->VerticalResolution <= VERTICAL_MAX_OK) { ++ /* keep original mode and return */ ++ return; ++ } ++ ++ efi_status = co->QueryMode(co, co->Mode->Mode, &columns, &rows); ++ if (EFI_ERROR(efi_status)) { ++ console_error(L"Console query mode fail", efi_status); ++ return; ++ } ++ ++ /* ++ * Verify current console output to check if the character columns and ++ * rows in a good mode. ++ */ ++ if (columns <= COLUMNS_MAX_OK && rows <= ROWS_MAX_OK) { ++ /* keep original mode and return */ ++ return; ++ } ++ ++ if (!console_text_mode) ++ setup_console(1); ++ ++ co->Reset(co, TRUE); ++ ++ /* ++ * If we reached here, then we have a high resolution screen and the ++ * text too small. Try to switch to a better mode. Mode number 2 is ++ * first non standard mode, which is provided by the device ++ * manufacturer, so it should be a good mode. ++ */ ++ if (co->Mode->MaxMode > 2) ++ mode_set = 2; ++ else ++ mode_set = 0; ++ ++ efi_status = co->SetMode(co, mode_set); ++ if (EFI_ERROR(efi_status) && mode_set != 0) { ++ /* ++ * Set to 0 mode which is required that all output devices ++ * support at least 80x25 text mode. ++ */ ++ mode_set = 0; ++ efi_status = co->SetMode(co, mode_set); ++ } ++ ++ co->ClearScreen(co); ++ ++ if (EFI_ERROR(efi_status)) { ++ console_error(L"Console set mode fail", efi_status); ++ } ++ ++ return; ++} + + /* Copy of gnu-efi-3.0 with the added secure boot strings */ + static struct { +diff --git a/include/console.h b/include/console.h +index deb4fa3db23..9f259c71b72 100644 +--- a/include/console.h ++++ b/include/console.h +@@ -34,6 +34,8 @@ void + console_notify(CHAR16 *string); + void + console_reset(void); ++void ++console_mode_handle(void); + #define NOSEL 0x7fffffff + + typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; +-- +2.26.2 + diff --git a/SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch b/SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch new file mode 100644 index 0000000..ac8814e --- /dev/null +++ b/SOURCES/0040-MokManager-avoid-Werror-address-of-packed-member.patch @@ -0,0 +1,111 @@ +From d57e53f3bddc4bc7299b3d5efd5ba8c547e8dfa5 Mon Sep 17 00:00:00 2001 +From: Jonas Witschel +Date: Thu, 5 Sep 2019 10:39:37 +0200 +Subject: [PATCH 40/62] MokManager: avoid -Werror=address-of-packed-member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When compiling with GCC 9, there are a couple of errors of the form + +MokManager.c: In function ‘write_back_mok_list’: +MokManager.c:1056:19: error: taking address of packed member of ‘struct ’ may result in an unaligned pointer value [-Werror=address-of-packed-member] + 1056 | if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) + | ^~~~~~~~~~~~~~~ + +Copying the member of the packed struct to a temporary variable and +pointing to that variable solves the problem. + +Upstream-commit-id: 58532e12e9a +--- + MokManager.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 78da9fd95ee..fa73e2fd865 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1064,6 +1064,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + EFI_STATUS efi_status; + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *CertData; ++ EFI_GUID type; + void *Data = NULL, *ptr; + INTN DataSize = 0; + int i; +@@ -1079,8 +1080,8 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + continue; + + DataSize += sizeof(EFI_SIGNATURE_LIST); +- if (CompareMem(&(list[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) == 0) ++ type = list[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if (CompareGuid(&type, &X509_GUID) == 0) + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } +@@ -1102,8 +1103,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + CertList->SignatureType = list[i].Type; + CertList->SignatureHeaderSize = 0; + +- if (CompareMem(&(list[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) == 0) { ++ if (CompareGuid(&(CertList->SignatureType), &X509_GUID) == 0) { + CertList->SignatureListSize = list[i].MokSize + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = +@@ -1141,11 +1141,12 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + static void delete_cert(void *key, UINT32 key_size, + MokListNode * mok, INTN mok_num) + { ++ EFI_GUID type; + int i; + + for (i = 0; i < mok_num; i++) { +- if (CompareMem(&(mok[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) != 0) ++ type = mok[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if (CompareGuid(&type, &X509_GUID) != 0) + continue; + + if (mok[i].MokSize == key_size && +@@ -1187,6 +1188,7 @@ static void mem_move(void *dest, void *src, UINTN size) + static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + MokListNode * mok, INTN mok_num) + { ++ EFI_GUID type; + UINT32 sig_size; + UINT32 list_num; + int i, del_ind; +@@ -1196,7 +1198,8 @@ static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + sig_size = hash_size + sizeof(EFI_GUID); + + for (i = 0; i < mok_num; i++) { +- if ((CompareMem(&(mok[i].Type), &Type, sizeof(EFI_GUID)) != 0) || ++ type = mok[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if ((CompareGuid(&type, &Type) != 0) || + (mok[i].MokSize < sig_size)) + continue; + +@@ -1252,6 +1255,7 @@ static void delete_hash_list(EFI_GUID Type, void *hash_list, UINT32 list_size, + static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + { + EFI_STATUS efi_status; ++ EFI_GUID type; + CHAR16 *db_name; + CHAR16 *auth_name; + CHAR16 *err_strs[] = { NULL, NULL, NULL }; +@@ -1360,8 +1364,8 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- if (CompareMem(&(del_key[i].Type), &X509_GUID, +- sizeof(EFI_GUID)) == 0) { ++ type = del_key[i].Type; /* avoid -Werror=address-of-packed-member */ ++ if (CompareGuid(&type, &X509_GUID) == 0) { + delete_cert(del_key[i].Mok, del_key[i].MokSize, + mok, mok_num); + } else if (is_sha2_hash(del_key[i].Type)) { +-- +2.26.2 + diff --git a/SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch b/SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch new file mode 100644 index 0000000..3a282e4 --- /dev/null +++ b/SOURCES/0041-tpm-Don-t-log-duplicate-identical-events.patch @@ -0,0 +1,31 @@ +From 58df8d745c6516818ba6ebfa8fe826702c1621a0 Mon Sep 17 00:00:00 2001 +From: Chris Coulson +Date: Thu, 26 Sep 2019 20:01:01 +0100 +Subject: [PATCH 41/62] tpm: Don't log duplicate identical events + +According to the comment in tpm_measure_variable ("Don't measure something that we've already measured"), shim +shouldn't measure duplicate events if they are identical, which also aligns with section 2.3.4.8 of the TCG PC +Client Platform Firmware Profile Specification ("If it has been measured previously, it MUST NOT be measured +again"). This is currently broken because tpm_data_measured() uses the return value of CompareGuid() incorrectly. + +Upstream-commit-id: 103adc89ce5 +--- + tpm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tpm.c b/tpm.c +index c0617bb479e..196b93c30f6 100644 +--- a/tpm.c ++++ b/tpm.c +@@ -241,7 +241,7 @@ static BOOLEAN tpm_data_measured(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN Var + + for (i=0; i +Date: Mon, 18 Nov 2019 13:59:14 -0500 +Subject: [PATCH 42/62] Slightly better debugging messages + +Signed-off-by: Peter Jones +Upstream-commit-id: 173d35fe8f5 +--- + shim.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/shim.c b/shim.c +index d7ee2b6de6f..2f7aba07421 100644 +--- a/shim.c ++++ b/shim.c +@@ -2459,6 +2459,8 @@ uninstall_shim_protocols(void) + EFI_STATUS + shim_init(void) + { ++ EFI_STATUS efi_status; ++ + setup_verbosity(); + dprint(L"%a", shim_version); + +@@ -2479,7 +2481,12 @@ shim_init(void) + } + + hook_exit(systab); +- return install_shim_protocols(); ++ ++ efi_status = install_shim_protocols(); ++ if (EFI_ERROR(efi_status)) ++ perror(L"install_shim_protocols() failed: %r\n", efi_status); ++ ++ return efi_status; + } + + void +@@ -2575,13 +2582,12 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) + build_cert = shim_cert; + #endif /* defined(ENABLE_SHIM_CERT) */ + CHAR16 *msgs[] = { +- L"import_mok_state() failed\n", +- L"shim_int() failed\n", ++ L"import_mok_state() failed", ++ L"shim_init() failed", + NULL + }; + int msg = 0; + +- + /* + * Set up the shim lock protocol so that grub and MokManager can + * call back in and use shim functions +-- +2.26.2 + diff --git a/SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch b/SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch new file mode 100644 index 0000000..255f47f --- /dev/null +++ b/SOURCES/0043-Actually-check-for-errors-from-set_second_stage.patch @@ -0,0 +1,69 @@ +From 959f5e4e993a82020fef48c7e7c012a44074645c Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 18 Nov 2019 13:58:46 -0500 +Subject: [PATCH 43/62] Actually check for errors from set_second_stage() + +This changes shim_init() to check for errors from set_second_stage(). +In order to make that work, it also does the following: + +- correctly /always/ allocate second_stage, not sometimes allocate and + sometimes point at .data +- test for LoadOptionSize == 0 and return success +- print an error message for the failure so we can see it. + +Signed-off-by: Peter Jones +Upstream-commit-id: 354bd9b1931 +--- + shim.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index 2f7aba07421..5329795c333 100644 +--- a/shim.c ++++ b/shim.c +@@ -2141,8 +2141,15 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + CHAR16 *loader_str = NULL; + UINTN loader_len = 0; + unsigned int i; ++ UINTN second_stage_len; + +- second_stage = DEFAULT_LOADER; ++ second_stage_len = StrLen(DEFAULT_LOADER) + 1; ++ second_stage = AllocatePool(second_stage_len); ++ if (!second_stage) { ++ perror(L"Could not allocate %lu bytes\n", second_stage_len); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ StrCpy(second_stage, DEFAULT_LOADER); + load_options = NULL; + load_options_size = 0; + +@@ -2199,6 +2206,12 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + * BDS will add that, but we ignore that here. + */ + ++ /* ++ * Maybe there just aren't any options... ++ */ ++ if (li->LoadOptionsSize == 0) ++ return EFI_SUCCESS; ++ + /* + * In either case, we've got to have at least a UCS2 NUL... + */ +@@ -2465,7 +2478,11 @@ shim_init(void) + dprint(L"%a", shim_version); + + /* Set the second stage loader */ +- set_second_stage (global_image_handle); ++ efi_status = set_second_stage(global_image_handle); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"set_second_stage() failed: %r\n", efi_status); ++ return efi_status; ++ } + + if (secure_mode()) { + if (vendor_cert_size || vendor_dbx_size) { +-- +2.26.2 + diff --git a/SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch b/SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch new file mode 100644 index 0000000..f69b22e --- /dev/null +++ b/SOURCES/0044-translate_slashes-don-t-write-to-string-literals.patch @@ -0,0 +1,140 @@ +From c6bedd5b83529925c3ec08f96a3bf61c81bff0ae Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 28 Jan 2020 23:33:46 +0100 +Subject: [PATCH 44/62] translate_slashes(): don't write to string literals + +Currently, all three invocations of the translate_slashes() function may +lead to writes to the string literal that is #defined with the +DEFAULT_LOADER_CHAR macro. According to ISO C99 6.4.5p6, this is undefined +behavior ("If the program attempts to modify such an array, the behavior +is undefined"). + +This bug crashes shim on e.g. the 64-bit ArmVirtQemu platform ("Data +abort: Permission fault"), where the platform firmware maps the .text +section (which contains the string literal) read-only. + +Modify translate_slashes() so that it copies and translates characters +from an input array of "char" to an output array of "CHAR8". + +While at it, fix another bug. Before this patch, if translate_slashes() +ever encountered a double backslash (translating it to a single forward +slash), then the output would end up shorter than the input. However, the +output was not NUL-terminated in-place, therefore the original string +length (and according trailing garbage) would be preserved. After this +patch, the NUL-termination on contraction is automatic, as the output +array's contents are indeterminate when entering the function, and so we +must NUL-terminate it anyway. + +Fixes: 8e9124227d18475d3bc634c33518963fc8db7c98 +Fixes: e62b69a5b0b87c6df7a4fc23906134945309e927 +Fixes: 3d79bcb2651b9eae809b975b3e03e2f96c067072 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795654 +Signed-off-by: Laszlo Ersek +Upstream-commit-id: 9813e8bc8b3 +--- + httpboot.c | 4 ++-- + netboot.c | 16 +++++++++++----- + include/str.h | 14 ++++++++------ + 3 files changed, 21 insertions(+), 13 deletions(-) + +diff --git a/httpboot.c b/httpboot.c +index 3622e85867c..2d27e8ed993 100644 +--- a/httpboot.c ++++ b/httpboot.c +@@ -743,14 +743,14 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) + { + EFI_STATUS efi_status; + EFI_HANDLE nic; +- CHAR8 *next_loader = NULL; ++ CHAR8 next_loader[sizeof DEFAULT_LOADER_CHAR]; + CHAR8 *next_uri = NULL; + CHAR8 *hostname = NULL; + + if (!uri) + return EFI_NOT_READY; + +- next_loader = translate_slashes(DEFAULT_LOADER_CHAR); ++ translate_slashes(next_loader, DEFAULT_LOADER_CHAR); + + /* Create the URI for the next loader based on the original URI */ + efi_status = generate_next_uri(uri, next_loader, &next_uri); +diff --git a/netboot.c b/netboot.c +index 58babfb4d2e..4922ef284b1 100644 +--- a/netboot.c ++++ b/netboot.c +@@ -189,7 +189,9 @@ static BOOLEAN extract_tftp_info(CHAR8 *url) + CHAR8 *start, *end; + CHAR8 ip6str[40]; + CHAR8 ip6inv[16]; +- CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); ++ CHAR8 template[sizeof DEFAULT_LOADER_CHAR]; ++ ++ translate_slashes(template, DEFAULT_LOADER_CHAR); + + // to check against str2ip6() errors + memset(ip6inv, 0, sizeof(ip6inv)); +@@ -254,10 +256,14 @@ static EFI_STATUS parseDhcp6() + + static EFI_STATUS parseDhcp4() + { +- CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); +- INTN template_len = strlen(template) + 1; ++ CHAR8 template[sizeof DEFAULT_LOADER_CHAR]; ++ INTN template_len; ++ UINTN template_ofs = 0; + EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4; + ++ translate_slashes(template, DEFAULT_LOADER_CHAR); ++ template_len = strlen(template) + 1; ++ + if(pxe->Mode->ProxyOfferReceived) { + /* + * Proxy should not have precedence. Check if DhcpAck +@@ -288,8 +294,8 @@ static EFI_STATUS parseDhcp4() + full_path[dir_len-1] = '\0'; + } + if (dir_len == 0 && dir[0] != '/' && template[0] == '/') +- template++; +- strcata(full_path, template); ++ template_ofs++; ++ strcata(full_path, template + template_ofs); + memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4); + + return EFI_SUCCESS; +diff --git a/include/str.h b/include/str.h +index 9a748366bd1..f73c6212cd9 100644 +--- a/include/str.h ++++ b/include/str.h +@@ -45,21 +45,23 @@ strcata(CHAR8 *dest, const CHAR8 *src) + static inline + __attribute__((unused)) + CHAR8 * +-translate_slashes(char *str) ++translate_slashes(CHAR8 *out, const char *str) + { + int i; + int j; +- if (str == NULL) +- return (CHAR8 *)str; ++ if (str == NULL || out == NULL) ++ return NULL; + + for (i = 0, j = 0; str[i] != '\0'; i++, j++) { + if (str[i] == '\\') { +- str[j] = '/'; ++ out[j] = '/'; + if (str[i+1] == '\\') + i++; +- } ++ } else ++ out[j] = str[i]; + } +- return (CHAR8 *)str; ++ out[j] = '\0'; ++ return out; + } + + #endif /* SHIM_STR_H */ +-- +2.26.2 + diff --git a/SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch b/SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch new file mode 100644 index 0000000..2203e48 --- /dev/null +++ b/SOURCES/0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch @@ -0,0 +1,93 @@ +From 89d72301aa67c82f00fe7fa4f42d7f6eb6045538 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 18 Feb 2020 12:03:28 +0100 +Subject: [PATCH 45/62] shim: Update EFI_LOADED_IMAGE with the second stage + loader file path + +When shim loads the second stage loader (e.g: GRUB) the FilePath field of +the EFI_LOADED_IMAGE structure isn't updated with the path of the loaded +binary. So it still contains the file path of the shim binary. + +This isn't a problem since the file path is currently not used. But should +be used to set the DevicePath field of the EFI_IMAGE_LOAD_EVENT structure +that is logged when measuring the PE/COFF binaries. In that case the TPM +Event Log will have an incorrect file path for the measured binary, i.e: + +$ hexdump -Cv /sys/kernel/security/tpm0/binary_bios_measurements +... +00000a50 00 00 00 00 00 00 04 04 34 00 5c 00 45 00 46 00 |........4.\.E.F.| +00000a60 49 00 5c 00 72 00 65 00 64 00 68 00 61 00 74 00 |I.\.r.e.d.h.a.t.| +00000a70 5c 00 73 00 68 00 69 00 6d 00 78 00 36 00 34 00 |\.s.h.i.m.x.6.4.| +00000a80 2e 00 65 00 66 00 69 00 00 00 7f ff 04 00 00 00 |..e.f.i.........| +00000a90 00 00 00 00 00 00 af 08 00 00 00 0d 00 00 00 b5 |................| +00000aa0 cd d0 8f bb 16 31 e2 80 8b e8 58 75 c9 89 18 95 |.....1....Xu....| +00000ab0 d2 de 15 15 00 00 00 67 72 75 62 5f 63 6d 64 20 |.......grub_cmd | +00000ac0 73 65 74 20 70 61 67 65 72 3d 31 00 08 00 00 00 |set pager=1.....| +... + +So update the EFI_LOADED_IMAGE structure with the second stage loader file +path to have the correct value in the log, i.e: + +$ hexdump -Cv /sys/kernel/security/tpm0/binary_bios_measurements +... +00000a50 00 00 00 00 00 00 04 04 34 00 5c 00 45 00 46 00 |........4.\.E.F.| +00000a60 49 00 5c 00 72 00 65 00 64 00 68 00 61 00 74 00 |I.\.r.e.d.h.a.t.| +00000a70 5c 00 67 00 72 00 75 00 62 00 78 00 36 00 34 00 |\.g.r.u.b.x.6.4.| +00000a80 2e 00 65 00 66 00 69 00 00 00 7f ff 04 00 00 00 |..e.f.i.........| +00000a90 00 00 00 00 00 00 af 08 00 00 00 0d 00 00 00 b5 |................| +00000aa0 cd d0 8f bb 16 31 e2 80 8b e8 58 75 c9 89 18 95 |.....1....Xu....| +00000ab0 d2 de 15 15 00 00 00 67 72 75 62 5f 63 6d 64 20 |.......grub_cmd | +00000ac0 73 65 74 20 70 61 67 65 72 3d 31 00 08 00 00 00 |set pager=1.....| +... + +Signed-off-by: Javier Martinez Canillas +Upstream-commit-id: cd7d42d493d +--- + shim.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index 5329795c333..a4f7769b38b 100644 +--- a/shim.c ++++ b/shim.c +@@ -1925,6 +1925,16 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + */ + CopyMem(&li_bak, li, sizeof(li_bak)); + ++ /* ++ * Update the loaded image with the second stage loader file path ++ */ ++ li->FilePath = FileDevicePath(NULL, PathName); ++ if (!li->FilePath) { ++ perror(L"Unable to update loaded image file path\n"); ++ efi_status = EFI_OUT_OF_RESOURCES; ++ goto restore; ++ } ++ + /* + * Verify and, if appropriate, relocate and execute the executable + */ +@@ -1934,8 +1944,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + perror(L"Failed to load image: %r\n", efi_status); + PrintErrors(); + ClearErrors(); +- CopyMem(li, &li_bak, sizeof(li_bak)); +- goto done; ++ goto restore; + } + + loader_is_participating = 0; +@@ -1945,6 +1954,10 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + */ + efi_status = entry_point(image_handle, systab); + ++restore: ++ if (li->FilePath) ++ FreePool(li->FilePath); ++ + /* + * Restore our original loaded image values + */ +-- +2.26.2 + diff --git a/SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch b/SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch new file mode 100644 index 0000000..90a6b52 --- /dev/null +++ b/SOURCES/0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch @@ -0,0 +1,124 @@ +From 0a8f7ade76ff3eede486027eaa638181e6bed3b8 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Tue, 18 Feb 2020 12:03:17 +0100 +Subject: [PATCH 46/62] tpm: Include information about PE/COFF images in the + TPM Event Log + +The "TCG PC Client Specific Platform Firmware Profile Specification" says +that when measuring a PE/COFF image, the TCG_PCR_EVENT2 structure Event +field MUST contain a UEFI_IMAGE_LOAD_EVENT structure. + +Currently an empty UEFI_IMAGE_LOAD_EVENT structure is passed so users only +have the hash of the PE/COFF image, but not information such the file path +of the binary. + +Signed-off-by: Javier Martinez Canillas +Upstream-commit-id: c252b9ee94c +--- + shim.c | 7 +++++-- + tpm.c | 46 ++++++++++++++++++++++++++++++++-------------- + include/tpm.h | 5 +++-- + 3 files changed, 40 insertions(+), 18 deletions(-) + +diff --git a/shim.c b/shim.c +index a4f7769b38b..b35b0ad90cc 100644 +--- a/shim.c ++++ b/shim.c +@@ -1274,7 +1274,9 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + #ifdef REQUIRE_TPM + efi_status = + #endif +- tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, sha1hash, 4); ++ tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, ++ (EFI_PHYSICAL_ADDRESS)(UINTN)context.ImageAddress, ++ li->FilePath, sha1hash, 4); + #ifdef REQUIRE_TPM + if (efi_status != EFI_SUCCESS) { + return efi_status; +@@ -1788,7 +1790,8 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) + #ifdef REQUIRE_TPM + efi_status = + #endif +- tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)buffer, size, sha1hash, 4); ++ tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)buffer, size, 0, NULL, ++ sha1hash, 4); + #ifdef REQUIRE_TPM + if (EFI_ERROR(efi_status)) + goto done; +diff --git a/tpm.c b/tpm.c +index 196b93c30f6..22ad148b35a 100644 +--- a/tpm.c ++++ b/tpm.c +@@ -210,21 +210,39 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, + strlen(description) + 1, 0xd, NULL); + } + +-EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash, +- UINT8 pcr) ++EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, ++ EFI_PHYSICAL_ADDRESS addr, EFI_DEVICE_PATH *path, ++ UINT8 *sha1hash, UINT8 pcr) + { +- EFI_IMAGE_LOAD_EVENT ImageLoad; +- +- // All of this is informational and forces us to do more parsing before +- // we can generate it, so let's just leave it out for now +- ImageLoad.ImageLocationInMemory = 0; +- ImageLoad.ImageLengthInMemory = 0; +- ImageLoad.ImageLinkTimeAddress = 0; +- ImageLoad.LengthOfDevicePath = 0; +- +- return tpm_log_event_raw(buf, size, pcr, (CHAR8 *)&ImageLoad, +- sizeof(ImageLoad), +- EV_EFI_BOOT_SERVICES_APPLICATION, sha1hash); ++ EFI_IMAGE_LOAD_EVENT *ImageLoad = NULL; ++ EFI_STATUS efi_status; ++ UINTN path_size = 0; ++ ++ if (path) ++ path_size = DevicePathSize(path); ++ ++ ImageLoad = AllocateZeroPool(sizeof(*ImageLoad) + path_size); ++ if (!ImageLoad) { ++ perror(L"Unable to allocate image load event structure\n"); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ ImageLoad->ImageLocationInMemory = buf; ++ ImageLoad->ImageLengthInMemory = size; ++ ImageLoad->ImageLinkTimeAddress = addr; ++ ++ if (path_size > 0) { ++ CopyMem(ImageLoad->DevicePath, path, path_size); ++ ImageLoad->LengthOfDevicePath = path_size; ++ } ++ ++ efi_status = tpm_log_event_raw(buf, size, pcr, (CHAR8 *)ImageLoad, ++ sizeof(*ImageLoad) + path_size, ++ EV_EFI_BOOT_SERVICES_APPLICATION, ++ sha1hash); ++ FreePool(ImageLoad); ++ ++ return efi_status; + } + + typedef struct { +diff --git a/include/tpm.h b/include/tpm.h +index 746e871ff22..a05c24949e5 100644 +--- a/include/tpm.h ++++ b/include/tpm.h +@@ -10,8 +10,9 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, + const CHAR8 *description); + EFI_STATUS fallback_should_prefer_reset(void); + +-EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash, +- UINT8 pcr); ++EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, ++ EFI_PHYSICAL_ADDRESS addr, EFI_DEVICE_PATH *path, ++ UINT8 *sha1hash, UINT8 pcr); + + EFI_STATUS tpm_measure_variable(CHAR16 *dbname, EFI_GUID guid, UINTN size, void *data); + +-- +2.26.2 + diff --git a/SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch b/SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch new file mode 100644 index 0000000..b62628d --- /dev/null +++ b/SOURCES/0047-Fix-the-license-on-our-buildid-extractor.patch @@ -0,0 +1,27 @@ +From dce3659ac3d14ed338cdb37798a429751898c078 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Apr 2020 18:55:34 -0400 +Subject: [PATCH 47/62] Fix the license on our buildid extractor. + +Signed-off-by: Peter Jones +Upstream-commit-id: 71439f848f6 +--- + buildid.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/buildid.c b/buildid.c +index f213f3bc921..6b414cdcffb 100644 +--- a/buildid.c ++++ b/buildid.c +@@ -1,8 +1,6 @@ + /* + * Walk a list of input files, printing the name and buildid of any file + * that has one. +- * +- * This program is licensed under the GNU Public License version 2. + */ + + #include +-- +2.26.2 + diff --git a/SOURCES/0048-Update-README.tpm.patch b/SOURCES/0048-Update-README.tpm.patch new file mode 100644 index 0000000..b5cd08d --- /dev/null +++ b/SOURCES/0048-Update-README.tpm.patch @@ -0,0 +1,27 @@ +From 633169fe3291c832236ca1074fc679852f9caee1 Mon Sep 17 00:00:00 2001 +From: noahbliss +Date: Wed, 4 Mar 2020 19:46:28 -0500 +Subject: [PATCH 48/62] Update README.tpm + +typo +Upstream-commit-id: bc24c9eb1d4 +--- + README.tpm | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/README.tpm b/README.tpm +index d9c7c53483b..c060dbe22db 100644 +--- a/README.tpm ++++ b/README.tpm +@@ -25,7 +25,7 @@ PCR8: + measured into PCR8. + + PCR9: +-- If you're using the grub2 TPM patchset we cary in Fedora, the kernel, ++- If you're using the grub2 TPM patchset we carry in Fedora, the kernel, + initramfs, and any multiboot modules loaded are measured into PCR9. + + PCR14: +-- +2.26.2 + diff --git a/SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch b/SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch new file mode 100644 index 0000000..dd9eea9 --- /dev/null +++ b/SOURCES/0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch @@ -0,0 +1,61 @@ +From 9a209af5d84f4015ec399e1d1fa9dab31ef4d2b7 Mon Sep 17 00:00:00 2001 +From: Thomas Frauendorfer | Miray Software +Date: Wed, 25 Mar 2020 09:19:19 +0100 +Subject: [PATCH 49/62] Check PxeReplyReceived as fallback in netboot + +Some mainboards do not update the ProxyOffset dhcp information when using +proxy dhcp and boot menus. +This adds a fallback to check the PxeReply field if no boot information is +found in the v4 dhcp or proxy dhcp information + +Upstream-commit-id: cc7ebe0f9f4 +--- + netboot.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + mode change 100644 => 100755 netboot.c + +diff --git a/netboot.c b/netboot.c +old mode 100644 +new mode 100755 +index 4922ef284b1..047dad3a760 +--- a/netboot.c ++++ b/netboot.c +@@ -273,7 +273,16 @@ static EFI_STATUS parseDhcp4() + pkt_v4 = &pxe->Mode->ProxyOffer.Dhcpv4; + } + +- INTN dir_len = strnlena(pkt_v4->BootpBootFile, 127); ++ if(pxe->Mode->PxeReplyReceived) { ++ /* ++ * If we have no bootinfo yet search for it in the PxeReply. ++ * Some mainboards run into this when the server uses boot menus ++ */ ++ if(pkt_v4->BootpBootFile[0] == '\0' && pxe->Mode->PxeReply.Dhcpv4.BootpBootFile[0] != '\0') ++ pkt_v4 = &pxe->Mode->PxeReply.Dhcpv4; ++ } ++ ++ INTN dir_len = strnlena((CHAR8 *)pkt_v4->BootpBootFile, 127); + INTN i; + UINT8 *dir = pkt_v4->BootpBootFile; + +@@ -289,7 +298,7 @@ static EFI_STATUS parseDhcp4() + return EFI_OUT_OF_RESOURCES; + + if (dir_len > 0) { +- strncpya(full_path, dir, dir_len); ++ strncpya(full_path, (CHAR8 *)dir, dir_len); + if (full_path[dir_len-1] == '/' && template[0] == '/') + full_path[dir_len-1] = '\0'; + } +@@ -340,7 +349,7 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *buf + + try_again: + efi_status = pxe->Mtftp(pxe, read, *buffer, overwrite, bufsiz, &blksz, +- &tftp_addr, full_path, NULL, nobuffer); ++ &tftp_addr, (UINT8 *)full_path, NULL, nobuffer); + if (efi_status == EFI_BUFFER_TOO_SMALL) { + /* try again, doubling buf size */ + *bufsiz *= 2; +-- +2.26.2 + diff --git a/SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch b/SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch new file mode 100644 index 0000000..1fda36c --- /dev/null +++ b/SOURCES/0050-Remove-a-couple-of-incorrect-license-claims.patch @@ -0,0 +1,46 @@ +From e8a04c1d84d2ebd0dbdf7bda26d7a22017100586 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 9 Jul 2020 00:24:57 -0400 +Subject: [PATCH 50/62] Remove a couple of incorrect license claims. + +A certain someone's default editor template leaked in to a couple of +source files, and claims they're GPL licensed. They're not. + +Signed-off-by: Peter Jones +Upstream-commit-id: 476cbff1110 +--- + errlog.c | 3 --- + mok.c | 2 -- + 2 files changed, 5 deletions(-) + +diff --git a/errlog.c b/errlog.c +index eebb266d396..6669c800233 100644 +--- a/errlog.c ++++ b/errlog.c +@@ -1,10 +1,7 @@ + /* + * errlog.c + * Copyright 2017 Peter Jones +- * +- * Distributed under terms of the GPLv3 license. + */ +- + #include "shim.h" + + static CHAR16 **errs = NULL; +diff --git a/mok.c b/mok.c +index 59630e74425..089ea6bfc9a 100644 +--- a/mok.c ++++ b/mok.c +@@ -1,8 +1,6 @@ + /* + * mok.c + * Copyright 2017 Peter Jones +- * +- * Distributed under terms of the GPLv3 license. + */ + + #include "shim.h" +-- +2.26.2 + diff --git a/SOURCES/0051-MokManager-fix-uninitialized-value.patch b/SOURCES/0051-MokManager-fix-uninitialized-value.patch new file mode 100644 index 0000000..808d11f --- /dev/null +++ b/SOURCES/0051-MokManager-fix-uninitialized-value.patch @@ -0,0 +1,27 @@ +From 7b77bee7966a1aa5f00a9b34aeb7e550bfa47be1 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 22 Jul 2020 23:53:09 -0400 +Subject: [PATCH 51/62] MokManager: fix uninitialized value + +Signed-off-by: Peter Jones +Upstream: pr#212 +--- + MokManager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/MokManager.c b/MokManager.c +index fa73e2fd865..654a115033c 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1431,7 +1431,7 @@ static CHAR16 get_password_charater(CHAR16 * prompt) + SIMPLE_TEXT_OUTPUT_MODE SavedMode; + EFI_STATUS efi_status; + CHAR16 *message[2]; +- CHAR16 character; ++ CHAR16 character = 0; + UINTN length; + UINT32 pw_length; + +-- +2.26.2 + diff --git a/SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch b/SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch new file mode 100644 index 0000000..4f3d2d6 --- /dev/null +++ b/SOURCES/0052-Fix-some-volatile-usage-gcc-whines-about.patch @@ -0,0 +1,41 @@ +From d3b7dc54cdac474a57b67cf9bcdb15bcb131d06c Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 16:18:52 -0400 +Subject: [PATCH 52/62] Fix some volatile usage gcc whines about. + +Signed-off-by: Peter Jones +Upstream: pr#212 +--- + fallback.c | 2 +- + shim.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fallback.c b/fallback.c +index c3f5583c626..5a4bfff0793 100644 +--- a/fallback.c ++++ b/fallback.c +@@ -983,7 +983,7 @@ debug_hook(void) + UINT8 *data = NULL; + UINTN dataSize = 0; + EFI_STATUS efi_status; +- volatile register int x = 0; ++ register volatile int x = 0; + extern char _etext, _edata; + + efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, +diff --git a/shim.c b/shim.c +index b35b0ad90cc..0e7e784b4c8 100644 +--- a/shim.c ++++ b/shim.c +@@ -2559,7 +2559,7 @@ debug_hook(void) + UINT8 *data = NULL; + UINTN dataSize = 0; + EFI_STATUS efi_status; +- volatile register UINTN x = 0; ++ register volatile UINTN x = 0; + extern char _text, _data; + + if (x) +-- +2.26.2 + diff --git a/SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch b/SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch new file mode 100644 index 0000000..cd20cb4 --- /dev/null +++ b/SOURCES/0053-MokManager-fix-a-wrong-allocation-failure-check.patch @@ -0,0 +1,31 @@ +From 6df96cdb20b84b33027d2e40bc0dbe0676d31282 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 19:01:27 -0400 +Subject: [PATCH 53/62] MokManager: fix a wrong allocation failure check. + +Signed-off-by: Peter Jones +Upstream: pr#212 +--- + MokManager.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/MokManager.c b/MokManager.c +index 654a115033c..c9949e33bcf 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1085,9 +1085,11 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + DataSize += sizeof(EFI_GUID); + DataSize += list[i].MokSize; + } ++ if (DataSize == 0) ++ return EFI_SUCCESS; + + Data = AllocatePool(DataSize); +- if (Data == NULL && DataSize != 0) ++ if (Data == NULL) + return EFI_OUT_OF_RESOURCES; + + ptr = Data; +-- +2.26.2 + diff --git a/SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch b/SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch new file mode 100644 index 0000000..8749432 --- /dev/null +++ b/SOURCES/0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch @@ -0,0 +1,33 @@ +From c186bdddaa7b103aef9d4a164ac0a07499dba112 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 22 Jul 2020 23:55:44 -0400 +Subject: [PATCH 54/62] simple_file: fix uninitialized variable/unchecked + return + +Signed-off-by: Peter Jones +Upstream: pr#212 +--- + lib/simple_file.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/simple_file.c b/lib/simple_file.c +index 3bf92ed8e0f..6ad31b4dc04 100644 +--- a/lib/simple_file.c ++++ b/lib/simple_file.c +@@ -403,10 +403,10 @@ simple_file_selector(EFI_HANDLE * im, CHAR16 ** title, CHAR16 * name, + filter = L""; + if (!*im) { + EFI_HANDLE h; +- CHAR16 *volname; ++ CHAR16 *volname = NULL; + +- simple_volume_selector(title, &volname, &h); +- if (!volname) ++ efi_status = simple_volume_selector(title, &volname, &h); ++ if (EFI_ERROR(efi_status) || !volname) + return; + FreePool(volname); + *im = h; +-- +2.26.2 + diff --git a/SOURCES/0055-Fix-a-broken-tpm-type.patch b/SOURCES/0055-Fix-a-broken-tpm-type.patch new file mode 100644 index 0000000..06b1201 --- /dev/null +++ b/SOURCES/0055-Fix-a-broken-tpm-type.patch @@ -0,0 +1,27 @@ +From a7f9911b776f3cdc12e42bf5990ddef0b08d3701 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 20:35:56 -0400 +Subject: [PATCH 55/62] Fix a broken tpm type + +Signed-off-by: Peter Jones +Upstream: pr#212 +--- + tpm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tpm.c b/tpm.c +index 22ad148b35a..03cf3a1f60e 100644 +--- a/tpm.c ++++ b/tpm.c +@@ -239,7 +239,7 @@ EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, + efi_status = tpm_log_event_raw(buf, size, pcr, (CHAR8 *)ImageLoad, + sizeof(*ImageLoad) + path_size, + EV_EFI_BOOT_SERVICES_APPLICATION, +- sha1hash); ++ (CHAR8 *)sha1hash); + FreePool(ImageLoad); + + return efi_status; +-- +2.26.2 + diff --git a/SOURCES/0056-Make-cert.S-not-impossible-to-read.patch b/SOURCES/0056-Make-cert.S-not-impossible-to-read.patch new file mode 100644 index 0000000..c8068ef --- /dev/null +++ b/SOURCES/0056-Make-cert.S-not-impossible-to-read.patch @@ -0,0 +1,279 @@ +From 7d542805ba5c48185128a2351bb315a5648fe3d7 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 00:08:30 -0400 +Subject: [PATCH 56/62] Make cert.S not impossible to read. + +Signed-off-by: Peter Jones +Upstream: pr#206 +--- + shim.c | 47 +++++++++++++++++-------------- + shim.h | 28 +++++++++++++++--- + cert.S | 89 ++++++++++++++++++++++------------------------------------ + 3 files changed, 84 insertions(+), 80 deletions(-) + +diff --git a/shim.c b/shim.c +index 0e7e784b4c8..888ee6e8d7b 100644 +--- a/shim.c ++++ b/shim.c +@@ -68,16 +68,18 @@ static UINT32 load_options_size; + * The vendor certificate used for validating the second stage loader + */ + extern struct { +- UINT32 vendor_cert_size; +- UINT32 vendor_dbx_size; +- UINT32 vendor_cert_offset; +- UINT32 vendor_dbx_offset; ++ UINT32 vendor_authorized_size; ++ UINT32 vendor_deauthorized_size; ++ UINT32 vendor_authorized_offset; ++ UINT32 vendor_deauthorized_offset; + } cert_table; + +-UINT32 vendor_cert_size; +-UINT32 vendor_dbx_size; +-UINT8 *vendor_cert; +-UINT8 *vendor_dbx; ++UINT32 vendor_authorized_size = 0; ++UINT8 *vendor_authorized = NULL; ++ ++UINT32 vendor_deauthorized_size = 0; ++UINT8 *vendor_deauthorized = NULL; ++ + #if defined(ENABLE_SHIM_CERT) + UINT32 build_cert_size; + UINT8 *build_cert; +@@ -554,22 +556,22 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data, + static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, + UINT8 *sha256hash, UINT8 *sha1hash) + { +- EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx; ++ EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_deauthorized; + +- if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash, ++ if (check_db_hash_in_ram(dbx, vendor_deauthorized_size, sha256hash, + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID, L"dbx", + EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { + LogError(L"binary sha256hash found in vendor dbx\n"); + return EFI_SECURITY_VIOLATION; + } +- if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash, ++ if (check_db_hash_in_ram(dbx, vendor_deauthorized_size, sha1hash, + SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID, L"dbx", + EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { + LogError(L"binary sha1hash found in vendor dbx\n"); + return EFI_SECURITY_VIOLATION; + } + if (cert && +- check_db_cert_in_ram(dbx, vendor_dbx_size, cert, sha256hash, L"dbx", ++ check_db_cert_in_ram(dbx, vendor_deauthorized_size, cert, sha256hash, L"dbx", + EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { + LogError(L"cert sha256hash found in vendor dbx\n"); + return EFI_SECURITY_VIOLATION; +@@ -1077,19 +1079,19 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + /* + * And finally, check against shim's built-in key + */ +- if (vendor_cert_size && ++ if (vendor_authorized_size && + AuthenticodeVerify(cert->CertData, + cert->Hdr.dwLength - sizeof(cert->Hdr), +- vendor_cert, vendor_cert_size, ++ vendor_authorized, vendor_authorized_size, + sha256hash, SHA256_DIGEST_SIZE)) { + update_verification_method(VERIFIED_BY_CERT); + tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, +- vendor_cert_size, vendor_cert); ++ vendor_authorized_size, vendor_authorized); + efi_status = EFI_SUCCESS; + drain_openssl_errors(); + return efi_status; + } else { +- LogError(L"AuthenticodeVerify(vendor_cert) failed\n"); ++ LogError(L"AuthenticodeVerify(vendor_authorized) failed\n"); + } + } + +@@ -2501,7 +2503,7 @@ shim_init(void) + } + + if (secure_mode()) { +- if (vendor_cert_size || vendor_dbx_size) { ++ if (vendor_authorized_size || vendor_deauthorized_size) { + /* + * If shim includes its own certificates then ensure + * that anything it boots has performed some +@@ -2606,14 +2608,17 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) + + verification_method = VERIFIED_BY_NOTHING; + +- vendor_cert_size = cert_table.vendor_cert_size; +- vendor_dbx_size = cert_table.vendor_dbx_size; +- vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset; +- vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset; ++ vendor_authorized_size = cert_table.vendor_authorized_size; ++ vendor_authorized = (UINT8 *)&cert_table + cert_table.vendor_authorized_offset; ++ ++ vendor_deauthorized_size = cert_table.vendor_deauthorized_size; ++ vendor_deauthorized = (UINT8 *)&cert_table + cert_table.vendor_deauthorized_offset; ++ + #if defined(ENABLE_SHIM_CERT) + build_cert_size = sizeof(shim_cert); + build_cert = shim_cert; + #endif /* defined(ENABLE_SHIM_CERT) */ ++ + CHAR16 *msgs[] = { + L"import_mok_state() failed", + L"shim_init() failed", +diff --git a/shim.h b/shim.h +index a0fa5a75e7e..555498c6673 100644 +--- a/shim.h ++++ b/shim.h +@@ -97,6 +97,24 @@ + #define FALLBACK L"\\fb" EFI_ARCH L".efi" + #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" + ++#if defined(VENDOR_CERT_FILE) ++# define vendor_authorized vendor_cert ++# define vendor_authorized_size vendor_cert_size ++# define vendor_authorized_category VENDOR_ADDEND_X509 ++#else ++# define vendor_authorized vendor_null ++# define vendor_authorized_size vendor_null_size ++# define vendor_authorized_category VENDOR_ADDEND_NONE ++#endif ++ ++#if defined(VENDOR_DBX_FILE) ++# define vendor_deauthorized vendor_dbx ++# define vendor_deauthorized_size vendor_dbx_size ++#else ++# define vendor_deauthorized vendor_deauthorized_null ++# define vendor_deauthorized_size vendor_deauthorized_null_size ++#endif ++ + #include "include/asm.h" + #include "include/configtable.h" + #include "include/console.h" +@@ -166,10 +184,12 @@ extern VOID ClearErrors(VOID); + extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath); + extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle); + +-extern UINT32 vendor_cert_size; +-extern UINT32 vendor_dbx_size; +-extern UINT8 *vendor_cert; +-extern UINT8 *vendor_dbx; ++extern UINT32 vendor_authorized_size; ++extern UINT8 *vendor_authorized; ++ ++extern UINT32 vendor_deauthorized_size; ++extern UINT8 *vendor_deauthorized; ++ + #if defined(ENABLE_SHIM_CERT) + extern UINT32 build_cert_size; + extern UINT8 *build_cert; +diff --git a/cert.S b/cert.S +index cfc4525b44c..520caaef3af 100644 +--- a/cert.S ++++ b/cert.S +@@ -1,65 +1,44 @@ ++ ++#if defined(VENDOR_CERT_FILE) ++# define vendor_authorized vendor_cert ++# define vendor_authorized_end vendor_cert_end ++# define vendor_authorized_size vendor_cert_size ++# define vendor_authorized_size_end vendor_cert_size_end ++#endif ++ ++#if defined(VENDOR_DBX_FILE) ++# define vendor_deauthorized vendor_dbx ++# define vendor_deauthorized_end vendor_dbx_end ++# define vendor_deauthorized_size vendor_dbx_size ++# define vendor_deauthorized_size_end vendor_dbx_size_end ++#endif ++ + .globl cert_table + .type cert_table, %object +- .size cert_table, 4 ++ .size cert_table, .Lcert_table_end - cert_table + .section .vendor_cert, "a", %progbits ++ .balignl 4, 0 + cert_table: +-#if defined(VENDOR_CERT_FILE) +- .long vendor_cert_priv_end - vendor_cert_priv +-#else +- .long 0 +-#endif +-#if defined(VENDOR_DBX_FILE) +- .long vendor_dbx_priv_end - vendor_dbx_priv +-#else +- .long 0 +-#endif +- .long vendor_cert_priv - cert_table +- .long vendor_dbx_priv - cert_table +-#if defined(VENDOR_CERT_FILE) +- .data +- .align 1 +- .type vendor_cert_priv, %object +- .size vendor_cert_priv, vendor_cert_priv_end-vendor_cert_priv ++ .4byte .Lvendor_authorized_end - vendor_authorized ++ .4byte .Lvendor_deauthorized_end - vendor_deauthorized ++ .4byte vendor_authorized - cert_table ++ .4byte vendor_deauthorized - cert_table ++ .balign 1, 0 ++ .type vendor_authorized, %object ++ .size vendor_authorized, .Lvendor_authorized_end - vendor_authorized + .section .vendor_cert, "a", %progbits +-vendor_cert_priv: ++vendor_authorized: ++#if defined(VENDOR_CERT_FILE) + .incbin VENDOR_CERT_FILE +-vendor_cert_priv_end: +-#else +- .bss +- .type vendor_cert_priv, %object +- .size vendor_cert_priv, 1 +- .section .vendor_cert, "a", %progbits +-vendor_cert_priv: +- .zero 1 +- +- .data +- .align 4 +- .type vendor_cert_size_priv, %object +- .size vendor_cert_size_priv, 4 +- .section .vendor_cert, "a", %progbits +-vendor_cert_priv_end: + #endif ++.Lvendor_authorized_end: ++ .balign 1, 0 ++ .type vendor_deauthorized, %object ++ .size vendor_deauthorized, .Lvendor_deauthorized_end - vendor_deauthorized ++ .section .vendor_cert, "a", %progbits ++vendor_deauthorized: + #if defined(VENDOR_DBX_FILE) +- .data +- .align 1 +- .type vendor_dbx_priv, %object +- .size vendor_dbx_priv, vendor_dbx_priv_end-vendor_dbx_priv +- .section .vendor_cert, "a", %progbits +-vendor_dbx_priv: + .incbin VENDOR_DBX_FILE +-vendor_dbx_priv_end: +-#else +- .bss +- .type vendor_dbx_priv, %object +- .size vendor_dbx_priv, 1 +- .section .vendor_cert, "a", %progbits +-vendor_dbx_priv: +- .zero 1 +- +- .data +- .align 4 +- .type vendor_dbx_size_priv, %object +- .size vendor_dbx_size_priv, 4 +- .section .vendor_cert, "a", %progbits +-vendor_dbx_priv_end: + #endif ++.Lvendor_deauthorized_end: ++.Lcert_table_end: +-- +2.26.2 + diff --git a/SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch b/SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch new file mode 100644 index 0000000..13a25e8 --- /dev/null +++ b/SOURCES/0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch @@ -0,0 +1,943 @@ +From dd3a5d71252a1f94e37f1a4c8841d253630b305a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 12:36:56 -0400 +Subject: [PATCH 57/62] Add support for vendor_db built-in shim authorized + list. + +Potential new signing strategies ( for example signing grub, fwupdate +and vmlinuz with separate certificates ) require shim to support a +vendor provided bundle of trusted certificates and hashes, which allows +shim to trust EFI binaries matching either certificate by signature or +hash in the vendor_db. Functionality is similar to vendor_dbx. + +This also improves the mirroring quite a bit. +Upstream: pr#206 +--- + lib/variables.c | 55 +++-- + mok.c | 502 ++++++++++++++++++++++++++++++-------------- + shim.c | 27 +++ + include/console.h | 3 +- + include/variables.h | 9 +- + shim.h | 7 +- + cert.S | 13 +- + Make.defaults | 3 + + README.tpm | 1 + + 9 files changed, 437 insertions(+), 183 deletions(-) + +diff --git a/lib/variables.c b/lib/variables.c +index 9c2e7d0ac2d..8123ae60fc9 100644 +--- a/lib/variables.c ++++ b/lib/variables.c +@@ -25,32 +25,59 @@ + #include "shim.h" + + EFI_STATUS +-variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, +- void **out, int *outlen) ++fill_esl(const uint8_t *data, const size_t data_len, ++ const EFI_GUID *type, const EFI_GUID *owner, ++ uint8_t *out, size_t *outlen) + { +- *outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); ++ EFI_SIGNATURE_LIST *sl; ++ EFI_SIGNATURE_DATA *sd; ++ size_t needed = 0; + +- *out = AllocateZeroPool(*outlen); +- if (!*out) +- return EFI_OUT_OF_RESOURCES; ++ if (!data || !data_len || !type || !outlen) ++ return EFI_INVALID_PARAMETER; + +- EFI_SIGNATURE_LIST *sl = *out; ++ needed = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) + data_len; ++ if (!out || *outlen < needed) { ++ *outlen = needed; ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ *outlen = needed; ++ sl = (EFI_SIGNATURE_LIST *)out; + + sl->SignatureHeaderSize = 0; + sl->SignatureType = *type; +- sl->SignatureSize = cert_len + sizeof(EFI_GUID); +- sl->SignatureListSize = *outlen; +- +- EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST); ++ sl->SignatureSize = sizeof(EFI_GUID) + data_len; ++ sl->SignatureListSize = needed; + ++ sd = (EFI_SIGNATURE_DATA *)(out + sizeof(EFI_SIGNATURE_LIST)); + if (owner) + sd->SignatureOwner = *owner; + +- CopyMem(sd->SignatureData, cert, cert_len); ++ CopyMem(sd->SignatureData, data, data_len); + + return EFI_SUCCESS; + } + ++EFI_STATUS ++variable_create_esl(const uint8_t *data, const size_t data_len, ++ const EFI_GUID *type, const EFI_GUID *owner, ++ uint8_t **out, size_t *outlen) ++{ ++ EFI_STATUS efi_status; ++ ++ *outlen = 0; ++ efi_status = fill_esl(data, data_len, type, owner, NULL, outlen); ++ if (efi_status != EFI_BUFFER_TOO_SMALL) ++ return efi_status; ++ ++ *out = AllocateZeroPool(*outlen); ++ if (!*out) ++ return EFI_OUT_OF_RESOURCES; ++ ++ return fill_esl(data, data_len, type, owner, *out, outlen); ++} ++ + EFI_STATUS + CreateTimeBasedPayload(IN OUT UINTN * DataSize, IN OUT UINT8 ** Data) + { +@@ -137,9 +164,9 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, + return EFI_SECURITY_VIOLATION; + + if (createtimebased) { +- int ds; ++ size_t ds; + efi_status = variable_create_esl(Data, len, &X509_GUID, NULL, +- (void **)&Cert, &ds); ++ (uint8_t **)&Cert, &ds); + if (EFI_ERROR(efi_status)) { + console_print(L"Failed to create %s certificate %d\n", + var, efi_status); +diff --git a/mok.c b/mok.c +index 089ea6bfc9a..e69857f3c37 100644 +--- a/mok.c ++++ b/mok.c +@@ -5,6 +5,8 @@ + + #include "shim.h" + ++#include ++ + /* + * Check if a variable exists + */ +@@ -47,6 +49,15 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) + return EFI_SUCCESS; + } + ++typedef enum { ++ VENDOR_ADDEND_DB, ++ VENDOR_ADDEND_X509, ++ VENDOR_ADDEND_NONE, ++} vendor_addend_category_t; ++ ++struct mok_state_variable; ++typedef vendor_addend_category_t (vendor_addend_categorizer_t)(struct mok_state_variable *); ++ + /* + * MoK variables that need to have their storage validated. + * +@@ -58,18 +69,20 @@ struct mok_state_variable { + char *name8; + CHAR16 *rtname; + EFI_GUID *guid; ++ + UINT8 *data; + UINTN data_size; ++ + /* +- * These two are indirect pointers just to make initialization +- * saner... ++ * These are indirect pointers just to make initialization saner... + */ +- UINT8 **addend_source; ++ vendor_addend_categorizer_t *categorize_addend; ++ UINT8 **addend; + UINT32 *addend_size; +-#if defined(ENABLE_SHIM_CERT) ++ + UINT8 **build_cert; + UINT32 *build_cert_size; +-#endif /* defined(ENABLE_SHIM_CERT) */ ++ + UINT32 yes_attr; + UINT32 no_attr; + UINT32 flags; +@@ -77,6 +90,28 @@ struct mok_state_variable { + UINT8 *state; + }; + ++static vendor_addend_category_t ++categorize_authorized(struct mok_state_variable *v) ++{ ++ if (!(v->addend && v->addend_size && ++ *v->addend && *v->addend_size)) { ++ return VENDOR_ADDEND_NONE; ++ } ++ ++ return vendor_authorized_category; ++} ++ ++static vendor_addend_category_t ++categorize_deauthorized(struct mok_state_variable *v) ++{ ++ if (!(v->addend && v->addend_size && ++ *v->addend && *v->addend_size)) { ++ return VENDOR_ADDEND_NONE; ++ } ++ ++ return VENDOR_ADDEND_DB; ++} ++ + #define MOK_MIRROR_KEYDB 0x01 + #define MOK_MIRROR_DELETE_FIRST 0x02 + #define MOK_VARIABLE_MEASURE 0x04 +@@ -90,8 +125,9 @@ struct mok_state_variable mok_state_variables[] = { + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, +- .addend_source = &vendor_cert, +- .addend_size = &vendor_cert_size, ++ .categorize_addend = categorize_authorized, ++ .addend = &vendor_authorized, ++ .addend_size = &vendor_authorized_size, + #if defined(ENABLE_SHIM_CERT) + .build_cert = &build_cert, + .build_cert_size = &build_cert_size, +@@ -107,6 +143,9 @@ struct mok_state_variable mok_state_variables[] = { + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, ++ .categorize_addend = categorize_deauthorized, ++ .addend = &vendor_deauthorized, ++ .addend_size = &vendor_deauthorized_size, + .flags = MOK_MIRROR_KEYDB | + MOK_VARIABLE_LOG, + .pcr = 14, +@@ -136,123 +175,253 @@ struct mok_state_variable mok_state_variables[] = { + { NULL, } + }; + +-static inline BOOLEAN nonnull(1) +-check_vendor_cert(struct mok_state_variable *v) +-{ +- return (v->addend_source && v->addend_size && +- *v->addend_source && *v->addend_size) ? TRUE : FALSE; +-} ++#define should_mirror_addend(v) (((v)->categorize_addend) && ((v)->categorize_addend(v) != VENDOR_ADDEND_NONE)) + +-#if defined(ENABLE_SHIM_CERT) + static inline BOOLEAN nonnull(1) +-check_build_cert(struct mok_state_variable *v) ++should_mirror_build_cert(struct mok_state_variable *v) + { + return (v->build_cert && v->build_cert_size && + *v->build_cert && *v->build_cert_size) ? TRUE : FALSE; + } +-#define check_addend(v) (check_vendor_cert(v) || check_build_cert(v)) +-#else +-#define check_addend(v) check_vendor_cert(v) +-#endif /* defined(ENABLE_SHIM_CERT) */ ++ ++static const uint8_t null_sha256[32] = { 0, }; + + static EFI_STATUS nonnull(1) + mirror_one_mok_variable(struct mok_state_variable *v) + { + EFI_STATUS efi_status = EFI_SUCCESS; +- void *FullData = NULL; +- UINTN FullDataSize = 0; ++ uint8_t *FullData = NULL; ++ size_t FullDataSize = 0; ++ vendor_addend_category_t addend_category = VENDOR_ADDEND_NONE; + uint8_t *p = NULL; + +- if ((v->flags & MOK_MIRROR_KEYDB) && check_addend(v)) { +- EFI_SIGNATURE_LIST *CertList = NULL; +- EFI_SIGNATURE_DATA *CertData = NULL; +-#if defined(ENABLE_SHIM_CERT) +- FullDataSize = v->data_size; +- if (check_build_cert(v)) { +- FullDataSize += sizeof (*CertList) +- + sizeof (EFI_GUID) +- + *v->build_cert_size; +- } +- if (check_vendor_cert(v)) { +- FullDataSize += sizeof (*CertList) +- + sizeof (EFI_GUID) +- + *v->addend_size; +- } +-#else +- FullDataSize = v->data_size +- + sizeof (*CertList) +- + sizeof (EFI_GUID) +- + *v->addend_size; +-#endif /* defined(ENABLE_SHIM_CERT) */ +- FullData = AllocatePool(FullDataSize); +- if (!FullData) { +- perror(L"Failed to allocate space for MokListRT\n"); +- return EFI_OUT_OF_RESOURCES; +- } +- p = FullData; ++ size_t build_cert_esl_sz = 0, addend_esl_sz = 0; + +- if (!EFI_ERROR(efi_status) && v->data_size > 0) { +- CopyMem(p, v->data, v->data_size); +- p += v->data_size; +- } ++ if (v->categorize_addend) ++ addend_category = v->categorize_addend(v); + +-#if defined(ENABLE_SHIM_CERT) +- if (check_build_cert(v) == FALSE) +- goto skip_build_cert; ++ /* ++ * we're always mirroring the original data, whether this is an efi ++ * security database or not ++ */ ++ dprint(L"v->data_size:%lu v->data:0x%08llx\n", v->data_size, v->data); ++ dprint(L"FullDataSize:%lu FullData:0x%08llx\n", FullDataSize, FullData); ++ if (v->data_size) { ++ FullDataSize = v->data_size; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ FullDataSize, FullData); ++ } + +- CertList = (EFI_SIGNATURE_LIST *)p; +- p += sizeof (*CertList); +- CertData = (EFI_SIGNATURE_DATA *)p; +- p += sizeof (EFI_GUID); ++ /* ++ * if it is, there's more data ++ */ ++ if (v->flags & MOK_MIRROR_KEYDB) { + +- CertList->SignatureType = EFI_CERT_TYPE_X509_GUID; +- CertList->SignatureListSize = *v->build_cert_size +- + sizeof (*CertList) +- + sizeof (*CertData) +- -1; +- CertList->SignatureHeaderSize = 0; +- CertList->SignatureSize = *v->build_cert_size + +- sizeof (EFI_GUID); ++ /* ++ * We're mirroring (into) an efi security database, aka an ++ * array of efi_signature_list_t. Its layout goes like: ++ * ++ * existing_variable_data ++ * existing_variable_data_size ++ * if flags & MOK_MIRROR_KEYDB ++ * if build_cert ++ * build_cert_esl ++ * build_cert_header (always sz=0) ++ * build_cert_esd[0] { owner, data } ++ * if addend==vendor_db ++ * for n=[1..N] ++ * vendor_db_esl_n ++ * vendor_db_header_n (always sz=0) ++ * vendor_db_esd_n[m] {{ owner, data }, ... } ++ * elif addend==vendor_cert ++ * vendor_cert_esl ++ * vendor_cert_header (always sz=0) ++ * vendor_cert_esd[1] { owner, data } ++ * ++ * first we determine the size of the variable, then alloc ++ * and add the data. ++ */ + +- CertData->SignatureOwner = SHIM_LOCK_GUID; +- CopyMem(p, *v->build_cert, *v->build_cert_size); ++ /* ++ * first bit is existing data, but we added that above ++ */ + +- p += *v->build_cert_size; ++ /* ++ * then the build cert if it's there ++ */ ++ if (should_mirror_build_cert(v)) { ++ efi_status = fill_esl(*v->build_cert, ++ *v->build_cert_size, ++ &EFI_CERT_TYPE_X509_GUID, ++ &SHIM_LOCK_GUID, ++ NULL, &build_cert_esl_sz); ++ if (efi_status != EFI_BUFFER_TOO_SMALL) { ++ perror(L"Could not add built-in cert to %s: %r\n", ++ v->name, efi_status); ++ return efi_status; ++ } ++ FullDataSize += build_cert_esl_sz; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ FullDataSize, FullData); ++ } + +- if (check_vendor_cert(v) == FALSE) +- goto skip_vendor_cert; +-skip_build_cert: +-#endif /* defined(ENABLE_SHIM_CERT) */ ++ /* ++ * then the addend data ++ */ ++ switch (addend_category) { ++ case VENDOR_ADDEND_DB: ++ /* ++ * if it's an ESL already, we use it wholesale ++ */ ++ FullDataSize += *v->addend_size; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ FullDataSize, FullData); ++ break; ++ case VENDOR_ADDEND_X509: ++ efi_status = fill_esl(*v->addend, *v->addend_size, ++ &EFI_CERT_TYPE_X509_GUID, ++ &SHIM_LOCK_GUID, ++ NULL, &addend_esl_sz); ++ if (efi_status != EFI_BUFFER_TOO_SMALL) { ++ perror(L"Could not add built-in cert to %s: %r\n", ++ v->name, efi_status); ++ return efi_status; ++ } ++ FullDataSize += addend_esl_sz; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ FullDataSize, FullData); ++ break; ++ default: ++ case VENDOR_ADDEND_NONE: ++ dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ FullDataSize, FullData); ++ break; ++ } ++ } + +- CertList = (EFI_SIGNATURE_LIST *)p; +- p += sizeof (*CertList); +- CertData = (EFI_SIGNATURE_DATA *)p; +- p += sizeof (EFI_GUID); ++ /* ++ * Now we have the full size ++ */ ++ if (FullDataSize) { ++ /* ++ * allocate the buffer, or use the old one if it's just the ++ * existing data. ++ */ ++ if (FullDataSize != v->data_size) { ++ dprint(L"FullDataSize:%lu FullData:0x%08llx allocating FullData\n", ++ FullDataSize, FullData); ++ FullData = AllocatePool(FullDataSize); ++ if (!FullData) { ++ FreePool(v->data); ++ v->data = NULL; ++ v->data_size = 0; ++ perror(L"Failed to allocate %lu bytes for %s\n", ++ FullDataSize, v->name); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ p = FullData; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ if (v->data && v->data_size) { ++ CopyMem(p, v->data, v->data_size); ++ p += v->data_size; ++ } ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ } else { ++ FullData = v->data; ++ FullDataSize = v->data_size; ++ p = FullData + FullDataSize; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ v->data = NULL; ++ v->data_size = 0; ++ } ++ } ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); + +- CertList->SignatureType = EFI_CERT_TYPE_X509_GUID; +- CertList->SignatureListSize = *v->addend_size +- + sizeof (*CertList) +- + sizeof (*CertData) +- -1; +- CertList->SignatureHeaderSize = 0; +- CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID); ++ /* ++ * Now fill it. ++ */ ++ if (v->flags & MOK_MIRROR_KEYDB) { ++ /* ++ * first bit is existing data, but again, we added that above ++ */ + +- CertData->SignatureOwner = SHIM_LOCK_GUID; +- CopyMem(p, *v->addend_source, *v->addend_size); ++ /* ++ * second is the build cert ++ */ ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ if (should_mirror_build_cert(v)) { ++ efi_status = fill_esl(*v->build_cert, ++ *v->build_cert_size, ++ &EFI_CERT_TYPE_X509_GUID, ++ &SHIM_LOCK_GUID, ++ p, &build_cert_esl_sz); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Could not add built-in cert to %s: %r\n", ++ v->name, efi_status); ++ return efi_status; ++ } ++ p += build_cert_esl_sz; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ } + +-#if defined(ENABLE_SHIM_CERT) +-skip_vendor_cert: +-#endif /* defined(ENABLE_SHIM_CERT) */ +- if (v->data && v->data_size) +- FreePool(v->data); +- v->data = FullData; +- v->data_size = FullDataSize; +- } else { +- FullDataSize = v->data_size; +- FullData = v->data; ++ switch (addend_category) { ++ case VENDOR_ADDEND_DB: ++ CopyMem(p, *v->addend, *v->addend_size); ++ p += *v->addend_size; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ break; ++ case VENDOR_ADDEND_X509: ++ efi_status = fill_esl(*v->addend, *v->addend_size, ++ &EFI_CERT_TYPE_X509_GUID, ++ &SHIM_LOCK_GUID, ++ p, &addend_esl_sz); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Could not add built-in cert to %s: %r\n", ++ v->name, efi_status); ++ return efi_status; ++ } ++ p += addend_esl_sz; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ break; ++ default: ++ case VENDOR_ADDEND_NONE: ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ break; ++ } ++ } ++ /* ++ * We always want to create our key databases, so in this case we ++ * need a dummy entry ++ */ ++ if ((v->flags & MOK_MIRROR_KEYDB) && FullDataSize == 0) { ++ efi_status = variable_create_esl( ++ null_sha256, sizeof(null_sha256), ++ &EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID, ++ &FullData, &FullDataSize); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to allocate %lu bytes for %s\n", ++ FullDataSize, v->name); ++ return efi_status; ++ } ++ p = FullData + FullDataSize; ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); + } + ++ dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); + if (FullDataSize) { ++ dprint(L"Setting %s with %lu bytes of data\n", ++ v->rtname, FullDataSize); + efi_status = gRT->SetVariable(v->rtname, v->guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, +@@ -262,7 +431,15 @@ skip_vendor_cert: + v->rtname, efi_status); + } + } +- ++ if (v->data && v->data_size) { ++ FreePool(v->data); ++ v->data = NULL; ++ v->data_size = 0; ++ } ++ if (FullData && FullDataSize) { ++ FreePool(FullData); ++ } ++ dprint(L"returning %r\n", efi_status); + return efi_status; + } + +@@ -274,6 +451,8 @@ static EFI_STATUS nonnull(1) + maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret) + { + EFI_STATUS efi_status; ++ BOOLEAN present = FALSE; ++ + if (v->rtname) { + if (v->flags & MOK_MIRROR_DELETE_FIRST) + LibDeleteVariable(v->rtname, v->guid); +@@ -286,6 +465,43 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret) + efi_status); + } + } ++ ++ present = (v->data && v->data_size) ? TRUE : FALSE; ++ if (!present) ++ return ret; ++ ++ if (v->data_size == sizeof(UINT8) && v->state) { ++ *v->state = v->data[0]; ++ } ++ ++ if (v->flags & MOK_VARIABLE_MEASURE) { ++ /* ++ * Measure this into PCR 7 in the Microsoft format ++ */ ++ efi_status = tpm_measure_variable(v->name, *v->guid, ++ v->data_size, ++ v->data); ++ if (EFI_ERROR(efi_status)) { ++ if (ret != EFI_SECURITY_VIOLATION) ++ ret = efi_status; ++ } ++ } ++ ++ if (v->flags & MOK_VARIABLE_LOG) { ++ /* ++ * Log this variable into whichever PCR the table ++ * says. ++ */ ++ EFI_PHYSICAL_ADDRESS datap = ++ (EFI_PHYSICAL_ADDRESS)(UINTN)v->data, ++ efi_status = tpm_log_event(datap, v->data_size, ++ v->pcr, (CHAR8 *)v->name8); ++ if (EFI_ERROR(efi_status)) { ++ if (ret != EFI_SECURITY_VIOLATION) ++ ret = efi_status; ++ } ++ } ++ + return ret; + } + +@@ -311,26 +527,20 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + user_insecure_mode = 0; + ignore_db = 0; + ++ dprint(L"importing mok state\n"); + for (i = 0; mok_state_variables[i].name != NULL; i++) { + struct mok_state_variable *v = &mok_state_variables[i]; + UINT32 attrs = 0; +- BOOLEAN delete = FALSE, present, addend; +- +- addend = check_addend(v); ++ BOOLEAN delete = FALSE; + + efi_status = get_variable_attr(v->name, + &v->data, &v->data_size, + *v->guid, &attrs); ++ dprint(L"maybe mirroring %s\n", v->name); + if (efi_status == EFI_NOT_FOUND) { +- if (addend) +- ret = maybe_mirror_one_mok_variable(v, ret); +- /* +- * after possibly adding, we can continue, no +- * further checks to be done. +- */ +- continue; +- } +- if (EFI_ERROR(efi_status)) { ++ v->data = NULL; ++ v->data_size = 0; ++ } else if (EFI_ERROR(efi_status)) { + perror(L"Could not verify %s: %r\n", v->name, + efi_status); + /* +@@ -339,22 +549,22 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + */ + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; +- continue; +- } +- +- if (!(attrs & v->yes_attr)) { +- perror(L"Variable %s is missing attributes:\n", +- v->name); +- perror(L" 0x%08x should have 0x%08x set.\n", +- attrs, v->yes_attr); +- delete = TRUE; +- } +- if (attrs & v->no_attr) { +- perror(L"Variable %s has incorrect attribute:\n", +- v->name); +- perror(L" 0x%08x should not have 0x%08x set.\n", +- attrs, v->no_attr); + delete = TRUE; ++ } else { ++ if (!(attrs & v->yes_attr)) { ++ perror(L"Variable %s is missing attributes:\n", ++ v->name); ++ perror(L" 0x%08x should have 0x%08x set.\n", ++ attrs, v->yes_attr); ++ delete = TRUE; ++ } ++ if (attrs & v->no_attr) { ++ perror(L"Variable %s has incorrect attribute:\n", ++ v->name); ++ perror(L" 0x%08x should not have 0x%08x set.\n", ++ attrs, v->no_attr); ++ delete = TRUE; ++ } + } + if (delete == TRUE) { + perror(L"Deleting bad variable %s\n", v->name); +@@ -366,45 +576,9 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + FreePool(v->data); + v->data = NULL; + v->data_size = 0; +- continue; + } + +- if (v->data && v->data_size == sizeof(UINT8) && v->state) { +- *v->state = v->data[0]; +- } +- +- present = (v->data && v->data_size) ? TRUE : FALSE; +- +- if (v->flags & MOK_VARIABLE_MEASURE && present) { +- /* +- * Measure this into PCR 7 in the Microsoft format +- */ +- efi_status = tpm_measure_variable(v->name, *v->guid, +- v->data_size, +- v->data); +- if (EFI_ERROR(efi_status)) { +- if (ret != EFI_SECURITY_VIOLATION) +- ret = efi_status; +- } +- } +- +- if (v->flags & MOK_VARIABLE_LOG && present) { +- /* +- * Log this variable into whichever PCR the table +- * says. +- */ +- EFI_PHYSICAL_ADDRESS datap = +- (EFI_PHYSICAL_ADDRESS)(UINTN)v->data, +- efi_status = tpm_log_event(datap, v->data_size, +- v->pcr, (CHAR8 *)v->name8); +- if (EFI_ERROR(efi_status)) { +- if (ret != EFI_SECURITY_VIOLATION) +- ret = efi_status; +- } +- } +- +- if (present) +- ret = maybe_mirror_one_mok_variable(v, ret); ++ ret = maybe_mirror_one_mok_variable(v, ret); + } + + /* +@@ -412,14 +586,16 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + * cause MokManager to demand a machine reboot, so this is safe to + * have after the entire loop. + */ ++ dprint(L"checking mok request\n"); + efi_status = check_mok_request(image_handle); ++ dprint(L"mok returned %r\n", efi_status); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + return ret; + } + +- ++ dprint(L"returning %r\n", ret); + return ret; + } + +diff --git a/shim.c b/shim.c +index 888ee6e8d7b..ee62248ca4e 100644 +--- a/shim.c ++++ b/shim.c +@@ -646,6 +646,31 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, + } + } + ++#if defined(VENDOR_DB_FILE) ++ EFI_SIGNATURE_LIST *db = (EFI_SIGNATURE_LIST *)vendor_db; ++ ++ if (check_db_hash_in_ram(db, vendor_db_size, ++ sha256hash, SHA256_DIGEST_SIZE, ++ EFI_CERT_SHA256_GUID, L"vendor_db", ++ EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { ++ verification_method = VERIFIED_BY_HASH; ++ update_verification_method(VERIFIED_BY_HASH); ++ return EFI_SUCCESS; ++ } else { ++ LogError(L"check_db_hash(vendor_db, sha256hash) != DATA_FOUND\n"); ++ } ++ if (cert && ++ check_db_cert_in_ram(db, vendor_db_size, ++ cert, sha256hash, L"vendor_db", ++ EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { ++ verification_method = VERIFIED_BY_CERT; ++ update_verification_method(VERIFIED_BY_CERT); ++ return EFI_SUCCESS; ++ } else { ++ LogError(L"check_db_cert(vendor_db, sha256hash) != DATA_FOUND\n"); ++ } ++#endif ++ + if (check_db_hash(L"MokList", SHIM_LOCK_GUID, sha256hash, + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) + == DATA_FOUND) { +@@ -1076,6 +1101,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + } + #endif /* defined(ENABLE_SHIM_CERT) */ + ++#if defined(VENDOR_CERT_FILE) + /* + * And finally, check against shim's built-in key + */ +@@ -1093,6 +1119,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + } else { + LogError(L"AuthenticodeVerify(vendor_authorized) failed\n"); + } ++#endif /* defined(VENDOR_CERT_FILE) */ + } + + LogError(L"Binary is not whitelisted\n"); +diff --git a/include/console.h b/include/console.h +index 9f259c71b72..810bf13a1f1 100644 +--- a/include/console.h ++++ b/include/console.h +@@ -78,12 +78,13 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL { + extern VOID console_fini(VOID); + extern VOID setup_verbosity(VOID); + extern UINT32 verbose; +-#define dprint(fmt, ...) ({ \ ++#define dprint_(fmt, ...) ({ \ + UINTN __dprint_ret = 0; \ + if (verbose) \ + __dprint_ret = console_print((fmt), ##__VA_ARGS__); \ + __dprint_ret; \ + }) ++#define dprint(fmt, ...) dprint_(L"%a:%d:%a() " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__) + + extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line); + #define crypterr(rc) print_crypto_errors((rc), __FILE__, __func__, __LINE__) +diff --git a/include/variables.h b/include/variables.h +index 8566a1a4746..436adb46e16 100644 +--- a/include/variables.h ++++ b/include/variables.h +@@ -57,7 +57,12 @@ EFI_STATUS + variable_enroll_hash(CHAR16 *var, EFI_GUID owner, + UINT8 hash[SHA256_DIGEST_SIZE]); + EFI_STATUS +-variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, +- void **out, int *outlen); ++variable_create_esl(const uint8_t *cert, const size_t cert_len, ++ const EFI_GUID *type, const EFI_GUID *owner, ++ uint8_t **out, size_t *outlen); ++EFI_STATUS ++fill_esl(const uint8_t *data, const size_t data_len, ++ const EFI_GUID *type, const EFI_GUID *owner, ++ uint8_t *out, size_t *outlen); + + #endif /* SHIM_VARIABLES_H */ +diff --git a/shim.h b/shim.h +index 555498c6673..c1d7e7c7197 100644 +--- a/shim.h ++++ b/shim.h +@@ -97,7 +97,11 @@ + #define FALLBACK L"\\fb" EFI_ARCH L".efi" + #define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" + +-#if defined(VENDOR_CERT_FILE) ++#if defined(VENDOR_DB_FILE) ++# define vendor_authorized vendor_db ++# define vendor_authorized_size vendor_db_size ++# define vendor_authorized_category VENDOR_ADDEND_DB ++#elif defined(VENDOR_CERT_FILE) + # define vendor_authorized vendor_cert + # define vendor_authorized_size vendor_cert_size + # define vendor_authorized_category VENDOR_ADDEND_X509 +@@ -116,6 +120,7 @@ + #endif + + #include "include/asm.h" ++#include "include/compiler.h" + #include "include/configtable.h" + #include "include/console.h" + #include "include/crypt_blowfish.h" +diff --git a/cert.S b/cert.S +index 520caaef3af..e636fcbbf2d 100644 +--- a/cert.S ++++ b/cert.S +@@ -1,5 +1,12 @@ + +-#if defined(VENDOR_CERT_FILE) ++#if defined(VENDOR_DB_FILE) && defined(VENDOR_CERT_FILE) ++# error both VENDOR_DB_FILE and VENDOR_CERT_FILE have been configured ++#elif defined(VENDOR_DB_FILE) ++# define vendor_authorized vendor_db ++# define vendor_authorized_end vendor_db_end ++# define vendor_authorized_size vendor_db_size ++# define vendor_authorized_size_end vendor_db_size_end ++#elif defined(VENDOR_CERT_FILE) + # define vendor_authorized vendor_cert + # define vendor_authorized_end vendor_cert_end + # define vendor_authorized_size vendor_cert_size +@@ -28,7 +35,9 @@ cert_table: + .size vendor_authorized, .Lvendor_authorized_end - vendor_authorized + .section .vendor_cert, "a", %progbits + vendor_authorized: +-#if defined(VENDOR_CERT_FILE) ++#if defined(VENDOR_DB_FILE) ++.incbin VENDOR_DB_FILE ++#elif defined(VENDOR_CERT_FILE) + .incbin VENDOR_CERT_FILE + #endif + .Lvendor_authorized_end: +diff --git a/Make.defaults b/Make.defaults +index f0bfa9fd573..2e01646a35d 100644 +--- a/Make.defaults ++++ b/Make.defaults +@@ -125,6 +125,9 @@ BOOTCSVNAME ?= BOOT$(ARCH_SUFFIX_UPPER).CSV + + CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/share/shim/$(ARCH_SUFFIX)-$(VERSION)$(DASHRELEASE)/\"" + ++ifneq ($(origin VENDOR_DB_FILE), undefined) ++ CFLAGS += -DVENDOR_DB_FILE=\"$(VENDOR_DB_FILE)\" ++endif + ifneq ($(origin VENDOR_CERT_FILE), undefined) + CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\" + endif +diff --git a/README.tpm b/README.tpm +index c060dbe22db..62308d5c71a 100644 +--- a/README.tpm ++++ b/README.tpm +@@ -13,6 +13,7 @@ PCR7: + - MokListX - the Mok blacklist, logged as "MokListX" + - vendor_dbx - shim's built-in vendor blacklist, logged as "dbx" + - DB - the system whitelist, logged as "db" ++ - vendor_db - shim's built-in vendor whitelist, logged as "db" + - MokList the Mok whitelist, logged as "MokList" + - vendor_cert - shim's built-in vendor whitelist, logged as "Shim" + - shim_cert - shim's build-time generated whitelist, logged as "Shim" +-- +2.26.2 + diff --git a/SOURCES/0058-Handle-binaries-with-multiple-signatures.patch b/SOURCES/0058-Handle-binaries-with-multiple-signatures.patch new file mode 100644 index 0000000..84482de --- /dev/null +++ b/SOURCES/0058-Handle-binaries-with-multiple-signatures.patch @@ -0,0 +1,366 @@ +From 76c0447e204c7e4ce918c4887ce8aae0e0816271 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 16:32:05 -0400 +Subject: [PATCH 58/62] Handle binaries with multiple signatures. + +This adds support for multiple signatures. It first tries validating +the binary by hash, first against our dbx lists, then against our db +lists. If it isn't allowed or rejected at that step, it continues to +the normal routine of checking all the signatures. + +At this point it does *not* reject a binary just because a signature is +by a cert on a dbx list, though that will override any db list that +certificate is listed on. If at any point any assertion about the +binary or signature list being well-formed fails, the binary is +immediately rejected, though we do allow skipping over signatures +which have an unsupported sig->Hdr.wCertificateType. + +Signed-off-by: Peter Jones +Upstream: pr#210 +--- + shim.c | 287 +++++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 198 insertions(+), 89 deletions(-) + +diff --git a/shim.c b/shim.c +index ee62248ca4e..d10a1ba1cac 100644 +--- a/shim.c ++++ b/shim.c +@@ -690,7 +690,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, + } + + update_verification_method(VERIFIED_BY_NOTHING); +- return EFI_SECURITY_VIOLATION; ++ return EFI_NOT_FOUND; + } + + /* +@@ -1004,6 +1004,103 @@ done: + return efi_status; + } + ++static EFI_STATUS ++verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig, ++ UINT8 *sha256hash, UINT8 *sha1hash) ++{ ++ EFI_STATUS efi_status; ++ ++ /* ++ * Ensure that the binary isn't blacklisted ++ */ ++ drain_openssl_errors(); ++ efi_status = check_blacklist(sig, sha256hash, sha1hash); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Binary is blacklisted: %r\n", efi_status); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(efi_status); ++ return efi_status; ++ } ++ ++ /* ++ * Check whether the binary is whitelisted in any of the firmware ++ * databases ++ */ ++ drain_openssl_errors(); ++ efi_status = check_whitelist(sig, sha256hash, sha1hash); ++ if (EFI_ERROR(efi_status)) { ++ if (efi_status != EFI_NOT_FOUND) { ++ dprint(L"check_whitelist(): %r\n", efi_status); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(efi_status); ++ } ++ } else { ++ drain_openssl_errors(); ++ return efi_status; ++ } ++ ++ efi_status = EFI_NOT_FOUND; ++#if defined(ENABLE_SHIM_CERT) ++ /* ++ * Check against the shim build key ++ */ ++ drain_openssl_errors(); ++ if (build_cert && build_cert_size) { ++ dprint("verifying against shim cert\n"); ++ } ++ if (build_cert && build_cert_size && ++ AuthenticodeVerify(sig->CertData, ++ sig->Hdr.dwLength - sizeof(sig->Hdr), ++ build_cert, build_cert_size, sha256hash, ++ SHA256_DIGEST_SIZE)) { ++ dprint(L"AuthenticodeVerify(shim_cert) succeeded\n"); ++ update_verification_method(VERIFIED_BY_CERT); ++ tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, ++ build_cert_size, build_cert); ++ efi_status = EFI_SUCCESS; ++ drain_openssl_errors(); ++ return efi_status; ++ } else { ++ dprint(L"AuthenticodeVerify(shim_cert) failed\n"); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(EFI_NOT_FOUND); ++ } ++#endif /* defined(ENABLE_SHIM_CERT) */ ++ ++#if defined(VENDOR_CERT_FILE) ++ /* ++ * And finally, check against shim's built-in key ++ */ ++ drain_openssl_errors(); ++ if (vendor_cert_size) { ++ dprint("verifying against vendor_cert\n"); ++ } ++ if (vendor_cert_size && ++ AuthenticodeVerify(sig->CertData, ++ sig->Hdr.dwLength - sizeof(sig->Hdr), ++ vendor_cert, vendor_cert_size, ++ sha256hash, SHA256_DIGEST_SIZE)) { ++ dprint(L"AuthenticodeVerify(vendor_cert) succeeded\n"); ++ update_verification_method(VERIFIED_BY_CERT); ++ tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, ++ vendor_cert_size, vendor_cert); ++ efi_status = EFI_SUCCESS; ++ drain_openssl_errors(); ++ return efi_status; ++ } else { ++ dprint(L"AuthenticodeVerify(vendor_cert) failed\n"); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(EFI_NOT_FOUND); ++ } ++#endif /* defined(VENDOR_CERT_FILE) */ ++ ++ return efi_status; ++} ++ + /* + * Check that the signature is valid and matches the binary + */ +@@ -1011,40 +1108,14 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash) + { +- EFI_STATUS efi_status = EFI_SECURITY_VIOLATION; +- WIN_CERTIFICATE_EFI_PKCS *cert = NULL; +- unsigned int size = datasize; ++ EFI_STATUS ret_efi_status; ++ size_t size = datasize; ++ size_t offset = 0; ++ unsigned int i = 0; + + if (datasize < 0) + return EFI_INVALID_PARAMETER; + +- if (context->SecDir->Size != 0) { +- if (context->SecDir->Size >= size) { +- perror(L"Certificate Database size is too large\n"); +- return EFI_INVALID_PARAMETER; +- } +- +- cert = ImageAddress (data, size, +- context->SecDir->VirtualAddress); +- +- if (!cert) { +- perror(L"Certificate located outside the image\n"); +- return EFI_INVALID_PARAMETER; +- } +- +- if (cert->Hdr.dwLength > context->SecDir->Size) { +- perror(L"Certificate list size is inconsistent with PE headers"); +- return EFI_INVALID_PARAMETER; +- } +- +- if (cert->Hdr.wCertificateType != +- WIN_CERT_TYPE_PKCS_SIGNED_DATA) { +- perror(L"Unsupported certificate type %x\n", +- cert->Hdr.wCertificateType); +- return EFI_UNSUPPORTED; +- } +- } +- + /* + * Clear OpenSSL's error log, because we get some DSO unimplemented + * errors during its intialization, and we don't want those to look +@@ -1052,81 +1123,119 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + */ + drain_openssl_errors(); + +- efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash); +- if (EFI_ERROR(efi_status)) { +- LogError(L"generate_hash: %r\n", efi_status); +- return efi_status; ++ ret_efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash); ++ if (EFI_ERROR(ret_efi_status)) { ++ dprint(L"generate_hash: %r\n", ret_efi_status); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(ret_efi_status); ++ return ret_efi_status; + } + + /* +- * Ensure that the binary isn't blacklisted ++ * Ensure that the binary isn't blacklisted by hash + */ +- efi_status = check_blacklist(cert, sha256hash, sha1hash); +- if (EFI_ERROR(efi_status)) { ++ drain_openssl_errors(); ++ ret_efi_status = check_blacklist(NULL, sha256hash, sha1hash); ++ if (EFI_ERROR(ret_efi_status)) { + perror(L"Binary is blacklisted\n"); +- LogError(L"Binary is blacklisted: %r\n", efi_status); +- return efi_status; ++ dprint(L"Binary is blacklisted: %r\n", ret_efi_status); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(ret_efi_status); ++ return ret_efi_status; + } + + /* +- * Check whether the binary is whitelisted in any of the firmware +- * databases ++ * Check whether the binary is whitelisted by hash in any of the ++ * firmware databases + */ +- efi_status = check_whitelist(cert, sha256hash, sha1hash); +- if (EFI_ERROR(efi_status)) { +- LogError(L"check_whitelist(): %r\n", efi_status); ++ drain_openssl_errors(); ++ ret_efi_status = check_whitelist(NULL, sha256hash, sha1hash); ++ if (EFI_ERROR(ret_efi_status)) { ++ dprint(L"check_whitelist: %r\n", ret_efi_status); ++ if (ret_efi_status != EFI_NOT_FOUND) { ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(ret_efi_status); ++ return ret_efi_status; ++ } + } else { + drain_openssl_errors(); +- return efi_status; ++ return ret_efi_status; + } + +- if (cert) { +-#if defined(ENABLE_SHIM_CERT) +- /* +- * Check against the shim build key +- */ +- if (sizeof(shim_cert) && +- AuthenticodeVerify(cert->CertData, +- cert->Hdr.dwLength - sizeof(cert->Hdr), +- shim_cert, sizeof(shim_cert), sha256hash, +- SHA256_DIGEST_SIZE)) { +- update_verification_method(VERIFIED_BY_CERT); +- tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, +- sizeof(shim_cert), shim_cert); +- efi_status = EFI_SUCCESS; +- drain_openssl_errors(); +- return efi_status; +- } else { +- LogError(L"AuthenticodeVerify(shim_cert) failed\n"); ++ if (context->SecDir->Size == 0) { ++ dprint(L"No signatures found\n"); ++ return EFI_SECURITY_VIOLATION; ++ } ++ ++ if (context->SecDir->Size >= size) { ++ perror(L"Certificate Database size is too large\n"); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ ret_efi_status = EFI_NOT_FOUND; ++ do { ++ WIN_CERTIFICATE_EFI_PKCS *sig = NULL; ++ size_t sz; ++ ++ sig = ImageAddress(data, size, ++ context->SecDir->VirtualAddress + offset); ++ if (!sig) ++ break; ++ ++ sz = offset + offsetof(WIN_CERTIFICATE_EFI_PKCS, Hdr.dwLength) ++ + sizeof(sig->Hdr.dwLength); ++ if (sz > context->SecDir->Size) { ++ perror(L"Certificate size is too large for secruity database"); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ sz = sig->Hdr.dwLength; ++ if (sz > context->SecDir->Size - offset) { ++ perror(L"Certificate size is too large for secruity database"); ++ return EFI_INVALID_PARAMETER; + } +-#endif /* defined(ENABLE_SHIM_CERT) */ +- +-#if defined(VENDOR_CERT_FILE) +- /* +- * And finally, check against shim's built-in key +- */ +- if (vendor_authorized_size && +- AuthenticodeVerify(cert->CertData, +- cert->Hdr.dwLength - sizeof(cert->Hdr), +- vendor_authorized, vendor_authorized_size, +- sha256hash, SHA256_DIGEST_SIZE)) { +- update_verification_method(VERIFIED_BY_CERT); +- tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, +- vendor_authorized_size, vendor_authorized); +- efi_status = EFI_SUCCESS; +- drain_openssl_errors(); +- return efi_status; ++ ++ if (sz < sizeof(sig->Hdr)) { ++ perror(L"Certificate size is too small for certificate data"); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (sig->Hdr.wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { ++ EFI_STATUS efi_status; ++ ++ dprint(L"Attempting to verify signature %d:\n", i++); ++ ++ efi_status = verify_one_signature(sig, sha256hash, sha1hash); ++ ++ /* ++ * If we didn't get EFI_SECURITY_VIOLATION from ++ * checking the hashes above, then any dbx entries are ++ * for a certificate, not this individual binary. ++ * ++ * So don't clobber successes with security violation ++ * here; that just means it isn't a success. ++ */ ++ if (ret_efi_status != EFI_SUCCESS) ++ ret_efi_status = efi_status; + } else { +- LogError(L"AuthenticodeVerify(vendor_authorized) failed\n"); ++ perror(L"Unsupported certificate type %x\n", ++ sig->Hdr.wCertificateType); + } +-#endif /* defined(VENDOR_CERT_FILE) */ +- } ++ offset = ALIGN_VALUE(offset + sz, 8); ++ } while (offset < context->SecDir->Size); + +- LogError(L"Binary is not whitelisted\n"); +- crypterr(EFI_SECURITY_VIOLATION); +- PrintErrors(); +- efi_status = EFI_SECURITY_VIOLATION; +- return efi_status; ++ if (ret_efi_status != EFI_SUCCESS) { ++ dprint(L"Binary is not whitelisted\n"); ++ PrintErrors(); ++ ClearErrors(); ++ crypterr(EFI_SECURITY_VIOLATION); ++ ret_efi_status = EFI_SECURITY_VIOLATION; ++ } ++ drain_openssl_errors(); ++ return ret_efi_status; + } + + /* +-- +2.26.2 + diff --git a/SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch b/SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch new file mode 100644 index 0000000..87d6f0c --- /dev/null +++ b/SOURCES/0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch @@ -0,0 +1,119 @@ +From 705d47ac2c90b8de07a4ef3e1930de6c4b8fece0 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 22 Jul 2020 19:54:58 -0400 +Subject: [PATCH 59/62] Make openssl accept the right set of KU/EKUs + +Signed-off-by: Peter Jones +Upstream: pr#211 +--- + Cryptlib/Pk/CryptPkcs7Verify.c | 87 ++++++++++++++++++++++++++++++++++ + 1 file changed, 87 insertions(+) + +diff --git a/Cryptlib/Pk/CryptPkcs7Verify.c b/Cryptlib/Pk/CryptPkcs7Verify.c +index dcaba436797..09895d8c66a 100644 +--- a/Cryptlib/Pk/CryptPkcs7Verify.c ++++ b/Cryptlib/Pk/CryptPkcs7Verify.c +@@ -30,6 +30,91 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 }; + ++#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#define X509_OBJECT_get0_X509(obj) ((obj)->data.x509) ++#define X509_OBJECT_get_type(obj) ((obj)->type) ++#define X509_STORE_CTX_get0_cert(ctx) ((ctx)->cert) ++#define X509_STORE_get0_objects(certs) ((certs)->objs) ++#define X509_get_extended_key_usage(cert) ((cert)->ex_xkusage) ++#if OPENSSL_VERSION_NUMBER < 0x10020000L ++#define X509_STORE_CTX_get0_store(ctx) ((ctx)->ctx) ++#endif ++#endif ++ ++static int cert_in_store(X509 *cert, X509_STORE_CTX *ctx) ++{ ++ X509_OBJECT obj; ++ obj.type = X509_LU_X509; ++ obj.data.x509 = cert; ++ return X509_OBJECT_retrieve_match(ctx->ctx->objs, &obj) != NULL; ++} ++#else ++/* ++ * Later versions of openssl will need this instead. ++ */ ++static int cert_in_store(X509 *cert, X509_STORE_CTX *ctx) ++{ ++ STACK_OF(X509_OBJECT) *objs; ++ X509_OBJECT *obj; ++ int i; ++ ++ objs = X509_STORE_get0_objects(X509_STORE_CTX_get0_store(ctx)); ++ ++ for (i = 0; i < sk_X509_OBJECT_num(objs); i++) { ++ obj = sk_X509_OBJECT_value(objs, i); ++ ++ if (X509_OBJECT_get_type(obj) == X509_LU_X509 && ++ !X509_cmp(X509_OBJECT_get0_X509(obj), cert)) ++ return 1; ++ } ++ ++ return 0; ++} ++#endif ++ ++int ++X509VerifyCb ( ++ IN int Status, ++ IN X509_STORE_CTX *Context ++ ) ++{ ++ INTN Error; ++ ++ Error = (INTN) X509_STORE_CTX_get_error (Context); ++ ++ /* Accept code-signing keys */ ++ if (Error == X509_V_ERR_INVALID_PURPOSE && ++ X509_get_extended_key_usage(X509_STORE_CTX_get0_cert(Context)) == XKU_CODE_SIGN) { ++ Status = 1; ++ } else if (Error == X509_V_ERR_CERT_UNTRUSTED || ++ Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT || ++ Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY || ++ Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) { ++ /* all certs in our cert database are explicitly trusted */ ++ ++ if (cert_in_store(X509_STORE_CTX_get_current_cert(Context), Context)) ++ Status = 1; ++ } else if (Error == X509_V_ERR_CERT_HAS_EXPIRED || ++ Error == X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD || ++ Error == X509_V_ERR_CERT_NOT_YET_VALID || ++ Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY || ++ Error == X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD) { ++ /* UEFI explicitly allows expired certificates */ ++ Status = 1; ++#if 0 ++ } else if (Error == X509_V_ERR_INVALID_CA) { ++ /* Due to the historical reason, we have to relax the the x509 v3 extension ++ * check to allow the CA certificates without the CA flag in the basic ++ * constraints or KeyCertSign in the key usage to be loaded. In the future, ++ * this callback should be removed to enforce the proper check. */ ++ Status = 1; ++#endif ++ } ++ ++ return Status; ++} ++ + /** + Check input P7Data is a wrapped ContentInfo structure or not. If not construct + a new structure to wrap P7Data. +@@ -844,6 +929,8 @@ Pkcs7Verify ( + goto _Exit; + } + ++ X509_STORE_set_verify_cb (CertStore, X509VerifyCb); ++ + // + // For generic PKCS#7 handling, InData may be NULL if the content is present + // in PKCS#7 structure. So ignore NULL checking here. +-- +2.26.2 + diff --git a/SOURCES/0060-Improve-debug-output-some.patch b/SOURCES/0060-Improve-debug-output-some.patch new file mode 100644 index 0000000..b48e54b --- /dev/null +++ b/SOURCES/0060-Improve-debug-output-some.patch @@ -0,0 +1,451 @@ +From fc4368fed53837e00d303600d8b628cb0392b629 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 20:29:52 -0400 +Subject: [PATCH 60/62] Improve debug output some + +Signed-off-by: Peter Jones +Upstream: pr#213 +--- + errlog.c | 26 ++++++- + shim.c | 36 ++++++++-- + include/console.h | 3 + + include/hexdump.h | 172 ++++++++++++++++++++++++++++------------------ + shim.h | 5 +- + 5 files changed, 164 insertions(+), 78 deletions(-) + +diff --git a/errlog.c b/errlog.c +index 6669c800233..08f7a82a6b2 100644 +--- a/errlog.c ++++ b/errlog.c +@@ -3,12 +3,28 @@ + * Copyright 2017 Peter Jones + */ + #include "shim.h" ++#include "hexdump.h" + + static CHAR16 **errs = NULL; + static UINTN nerrs = 0; + + EFI_STATUS +-VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args) ++vdprint_(const CHAR16 *fmt, const char *file, int line, const char *func, va_list args) ++{ ++ va_list args2; ++ EFI_STATUS efi_status = EFI_SUCCESS; ++ ++ if (verbose) { ++ va_copy(args2, args); ++ console_print(L"%a:%d:%a() ", file, line, func); ++ efi_status = VPrint(fmt, args2); ++ va_end(args2); ++ } ++ return efi_status; ++} ++ ++EFI_STATUS ++VLogError(const char *file, int line, const char *func, const CHAR16 *fmt, va_list args) + { + va_list args2; + CHAR16 **newerrs; +@@ -35,7 +51,7 @@ VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list arg + } + + EFI_STATUS +-LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...) ++LogError_(const char *file, int line, const char *func, const CHAR16 *fmt, ...) + { + va_list args; + EFI_STATUS efi_status; +@@ -47,6 +63,12 @@ LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...) + return efi_status; + } + ++VOID ++LogHexdump_(const char *file, int line, const char *func, const void *data, size_t sz) ++{ ++ hexdumpat(file, line, func, data, sz, 0); ++} ++ + VOID + PrintErrors(VOID) + { +diff --git a/shim.c b/shim.c +index d10a1ba1cac..9248642bd57 100644 +--- a/shim.c ++++ b/shim.c +@@ -34,6 +34,7 @@ + */ + + #include "shim.h" ++#include "hexdump.h" + #if defined(ENABLE_SHIM_CERT) + #include "shim_cert.h" + #endif /* defined(ENABLE_SHIM_CERT) */ +@@ -373,12 +374,18 @@ static BOOLEAN verify_x509(UINT8 *Cert, UINTN CertSize) + * and 64KB. For convenience, assume the number of value bytes + * is 2, i.e. the second byte is 0x82. + */ +- if (Cert[0] != 0x30 || Cert[1] != 0x82) ++ if (Cert[0] != 0x30 || Cert[1] != 0x82) { ++ dprint(L"cert[0:1] is [%02x%02x], should be [%02x%02x]\n", ++ Cert[0], Cert[1], 0x30, 0x82); + return FALSE; ++ } + + length = Cert[2]<<8 | Cert[3]; +- if (length != (CertSize - 4)) ++ if (length != (CertSize - 4)) { ++ dprint(L"Cert length is %ld, expecting %ld\n", ++ length, CertSize); + return FALSE; ++ } + + return TRUE; + } +@@ -426,19 +433,23 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, + EFI_SIGNATURE_DATA *Cert; + UINTN CertSize; + BOOLEAN IsFound = FALSE; ++ int i = 0; + + while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { + if (CompareGuid (&CertList->SignatureType, &EFI_CERT_TYPE_X509_GUID) == 0) { + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + CertSize = CertList->SignatureSize - sizeof(EFI_GUID); ++ dprint(L"trying to verify cert %d (%s)\n", i++, dbname); + if (verify_x509(Cert->SignatureData, CertSize)) { + if (verify_eku(Cert->SignatureData, CertSize)) { ++ drain_openssl_errors(); + IsFound = AuthenticodeVerify (data->CertData, + data->Hdr.dwLength - sizeof(data->Hdr), + Cert->SignatureData, + CertSize, + hash, SHA256_DIGEST_SIZE); + if (IsFound) { ++ dprint(L"AuthenticodeVerify() succeeded: %d\n", IsFound); + tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData); + drain_openssl_errors(); + return DATA_FOUND; +@@ -447,7 +458,9 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, + } + } + } else if (verbose) { +- console_notify(L"Not a DER encoding x.509 Certificate"); ++ console_print(L"Not a DER encoded x.509 Certificate"); ++ dprint(L"cert:\n"); ++ dhexdumpat(Cert->SignatureData, CertSize, 0); + } + } + +@@ -641,7 +654,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, + verification_method = VERIFIED_BY_CERT; + update_verification_method(VERIFIED_BY_CERT); + return EFI_SUCCESS; +- } else { ++ } else if (cert) { + LogError(L"check_db_cert(db, sha256hash) != DATA_FOUND\n"); + } + } +@@ -666,7 +679,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, + verification_method = VERIFIED_BY_CERT; + update_verification_method(VERIFIED_BY_CERT); + return EFI_SUCCESS; +- } else { ++ } else if (cert) { + LogError(L"check_db_cert(vendor_db, sha256hash) != DATA_FOUND\n"); + } + #endif +@@ -685,7 +698,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, + verification_method = VERIFIED_BY_CERT; + update_verification_method(VERIFIED_BY_CERT); + return EFI_SUCCESS; +- } else { ++ } else if (cert) { + LogError(L"check_db_cert(MokList, sha256hash) != DATA_FOUND\n"); + } + +@@ -993,6 +1006,11 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, + goto done; + } + ++ dprint(L"sha1 authenticode hash:\n"); ++ dhexdumpat(sha1hash, SHA1_DIGEST_SIZE, 0); ++ dprint(L"sha256 authenticode hash:\n"); ++ dhexdumpat(sha256hash, SHA256_DIGEST_SIZE, 0); ++ + done: + if (SectionHeader) + FreePool(SectionHeader); +@@ -1155,6 +1173,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + if (EFI_ERROR(ret_efi_status)) { + dprint(L"check_whitelist: %r\n", ret_efi_status); + if (ret_efi_status != EFI_NOT_FOUND) { ++ dprint(L"check_whitelist(): %r\n", ret_efi_status); + PrintErrors(); + ClearErrors(); + crypterr(ret_efi_status); +@@ -1803,6 +1822,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + + device = li->DeviceHandle; + ++ dprint(L"attempting to load %s\n", PathName); + /* + * Open the device + */ +@@ -2778,6 +2798,10 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) + */ + InitializeLib(image_handle, systab); + ++ dprint(L"vendor_authorized:0x%08lx vendor_authorized_size:%lu\n", ++ __FILE__, __LINE__, __func__, vendor_authorized, vendor_authorized_size); ++ dprint(L"vendor_deauthorized:0x%08lx vendor_deauthorized_size:%lu\n", ++ __FILE__, __LINE__, __func__, vendor_deauthorized, vendor_deauthorized_size); + init_openssl(); + + /* +diff --git a/include/console.h b/include/console.h +index 810bf13a1f1..ac6fdf61d18 100644 +--- a/include/console.h ++++ b/include/console.h +@@ -85,6 +85,9 @@ extern UINT32 verbose; + __dprint_ret; \ + }) + #define dprint(fmt, ...) dprint_(L"%a:%d:%a() " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__) ++extern EFI_STATUS ++vdprint_(const CHAR16 *fmt, const char *file, int line, const char *func, va_list args); ++#define vdprint(fmt, ...) vdprint_(fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__) + + extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line); + #define crypterr(rc) print_crypto_errors((rc), __FILE__, __func__, __LINE__) +diff --git a/include/hexdump.h b/include/hexdump.h +index d337b571d8d..f3f3ac284a3 100644 +--- a/include/hexdump.h ++++ b/include/hexdump.h +@@ -1,104 +1,140 @@ + #ifndef STATIC_HEXDUMP_H + #define STATIC_HEXDUMP_H + +-static int +-__attribute__((__unused__)) +-isprint(char c) +-{ +- if (c < 0x20) +- return 0; +- if (c > 0x7e) +- return 0; +- return 1; +-} ++#include + +-static UINTN +-__attribute__((__unused__)) +-format_hex(UINT8 *data, UINTN size, CHAR16 *buf) ++static inline unsigned long UNUSED ++prepare_hex(const void *data, size_t size, char *buf, int position) + { +- UINTN sz = (UINTN)data % 16; +- CHAR16 hexchars[] = L"0123456789abcdef"; ++ char hexchars[] = "0123456789abcdef"; + int offset = 0; +- UINTN i; +- UINTN j; ++ unsigned long i; ++ unsigned long j; ++ unsigned long ret; + +- for (i = 0; i < sz; i++) { +- buf[offset++] = L' '; +- buf[offset++] = L' '; +- buf[offset++] = L' '; ++ unsigned long before = (position % 16); ++ unsigned long after = (before+size >= 16) ? 0 : 16 - (before+size); ++ ++ for (i = 0; i < before; i++) { ++ buf[offset++] = 'X'; ++ buf[offset++] = 'X'; ++ buf[offset++] = ' '; + if (i == 7) +- buf[offset++] = L' '; ++ buf[offset++] = ' '; + } +- for (j = sz; j < 16 && j < size; j++) { +- UINT8 d = data[j-sz]; ++ for (j = 0; j < 16 - after - before; j++) { ++ uint8_t d = ((uint8_t *)data)[j]; + buf[offset++] = hexchars[(d & 0xf0) >> 4]; + buf[offset++] = hexchars[(d & 0x0f)]; +- if (j != 15) +- buf[offset++] = L' '; +- if (j == 7) +- buf[offset++] = L' '; ++ if (i+j != 15) ++ buf[offset++] = ' '; ++ if (i+j == 7) ++ buf[offset++] = ' '; + } +- for (i = j; i < 16; i++) { +- buf[offset++] = L' '; +- buf[offset++] = L' '; +- if (i != 15) +- buf[offset++] = L' '; +- if (i == 7) +- buf[offset++] = L' '; ++ ret = 16 - after - before; ++ j += i; ++ for (i = 0; i < after; i++) { ++ buf[offset++] = 'X'; ++ buf[offset++] = 'X'; ++ if (i+j != 15) ++ buf[offset++] = ' '; ++ if (i+j == 7) ++ buf[offset++] = ' '; + } +- buf[offset] = L'\0'; +- return j - sz; ++ buf[offset] = '\0'; ++ return ret; + } + +-static void +-__attribute__((__unused__)) +-format_text(UINT8 *data, UINTN size, CHAR16 *buf) ++#define isprint(c) ((c) >= 0x20 && (c) <= 0x7e) ++ ++static inline void UNUSED ++prepare_text(const void *data, size_t size, char *buf, int position) + { +- UINTN sz = (UINTN)data % 16; + int offset = 0; +- UINTN i; +- UINTN j; ++ unsigned long i; ++ unsigned long j; + +- for (i = 0; i < sz; i++) +- buf[offset++] = L' '; +- buf[offset++] = L'|'; +- for (j = sz; j < 16 && j < size; j++) { +- if (isprint(data[j-sz])) +- buf[offset++] = data[j-sz]; ++ unsigned long before = position % 16; ++ unsigned long after = (before+size > 16) ? 0 : 16 - (before+size); ++ ++ if (size == 0) { ++ buf[0] = '\0'; ++ return; ++ } ++ for (i = 0; i < before; i++) ++ buf[offset++] = 'X'; ++ buf[offset++] = '|'; ++ for (j = 0; j < 16 - after - before; j++) { ++ if (isprint(((uint8_t *)data)[j])) ++ buf[offset++] = ((uint8_t *)data)[j]; + else +- buf[offset++] = L'.'; ++ buf[offset++] = '.'; + } +- buf[offset++] = L'|'; +- for (i = j; i < 16; i++) +- buf[offset++] = L' '; +- buf[offset] = L'\0'; ++ buf[offset++] = size > 0 ? '|' : 'X'; ++ buf[offset] = '\0'; + } + +-static void +-__attribute__((__unused__)) +-hexdump(UINT8 *data, UINTN size) ++/* ++ * variadic hexdump formatted ++ * think of it as: printf("%s%s\n", vformat(fmt, ap), hexdump(data,size)); ++ */ ++static inline void UNUSED ++vhexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt, const void *data, unsigned long size, size_t at, va_list ap) + { +- UINTN display_offset = (UINTN)data & 0xffffffff; +- UINTN offset = 0; +- //console_print(L"hexdump: data=0x%016x size=0x%x\n", data, size); ++ unsigned long display_offset = at; ++ unsigned long offset = 0; + + while (offset < size) { +- CHAR16 hexbuf[49]; +- CHAR16 txtbuf[19]; +- UINTN sz; ++ char hexbuf[49]; ++ char txtbuf[19]; ++ unsigned long sz; + +- sz = format_hex(data+offset, size-offset, hexbuf); ++ sz = prepare_hex(data+offset, size-offset, hexbuf, ++ (unsigned long)data+offset); + if (sz == 0) + return; +- msleep(200000); + +- format_text(data+offset, size-offset, txtbuf); +- console_print(L"%08x %s %s\n", display_offset, hexbuf, txtbuf); +- msleep(200000); ++ prepare_text(data+offset, size-offset, txtbuf, ++ (unsigned long)data+offset); ++ if (fmt && fmt[0] != 0) ++ vdprint_(fmt, file, line, func, ap); ++ dprint_(L"%a:%d:%a() %08lx %a %a\n", file, line, func, display_offset, hexbuf, txtbuf); + + display_offset += sz; + offset += sz; + } + } + ++/* ++ * hexdump formatted ++ * think of it as: printf("%s%s", format(fmt, ...), hexdump(data,size)[lineN]); ++ */ ++static inline void UNUSED ++hexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt, const void *data, unsigned long size, size_t at, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, at); ++ vhexdumpf(file, line, func, fmt, data, size, at, ap); ++ va_end(ap); ++} ++ ++static inline void UNUSED ++hexdump(const char *file, int line, const char *func, const void *data, unsigned long size) ++{ ++ hexdumpf(file, line, func, L"", data, size, (intptr_t)data); ++} ++ ++static inline void UNUSED ++hexdumpat(const char *file, int line, const char *func, const void *data, unsigned long size, size_t at) ++{ ++ hexdumpf(file, line, func, L"", data, size, at); ++} ++ ++#define LogHexdump(data, sz) LogHexdump_(__FILE__, __LINE__, __func__, data, sz) ++#define dhexdump(data, sz) hexdump(__FILE__, __LINE__, __func__, data, sz) ++#define dhexdumpat(data, sz, at) hexdumpat(__FILE__, __LINE__, __func__, data, sz, at) ++#define dhexdumpf(fmt, data, sz, at, ...) hexdumpf(__FILE__, __LINE__, __func__, fmt, data, sz, at, ##__VA_ARGS__) ++ + #endif /* STATIC_HEXDUMP_H */ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/shim.h b/shim.h +index c1d7e7c7197..0b3ad4f2d20 100644 +--- a/shim.h ++++ b/shim.h +@@ -182,8 +182,9 @@ typedef struct _SHIM_LOCK { + + extern EFI_STATUS shim_init(void); + extern void shim_fini(void); +-extern EFI_STATUS LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...); +-extern EFI_STATUS VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args); ++extern EFI_STATUS LogError_(const char *file, int line, const char *func, const CHAR16 *fmt, ...); ++extern EFI_STATUS VLogError(const char *file, int line, const char *func, const CHAR16 *fmt, va_list args); ++extern VOID LogHexdump_(const char *file, int line, const char *func, const void *data, size_t sz); + extern VOID PrintErrors(VOID); + extern VOID ClearErrors(VOID); + extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath); +-- +2.26.2 + diff --git a/SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch b/SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch new file mode 100644 index 0000000..a2095b1 --- /dev/null +++ b/SOURCES/0061-Also-use-a-config-table-to-mirror-mok-variables.patch @@ -0,0 +1,352 @@ +From fecc2dfb8e408526221091923d9345796b8e294e Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 23 Jul 2020 22:09:03 -0400 +Subject: [PATCH 61/62] Also use a config table to mirror mok variables. + +Everything was going just fine until I made a vendor_db with 17kB of +sha256 sums in it. And then the same source tree that had worked fine +without that threw errors and failed all over the place. I wrote some +code to diagnose the problem, and of course it was a failure in +mirroring MokList to MokListRT. + +As Patrick noted in 741c61abba7, some systems have obnoxiously low +amounts of variable storage available: + +mok.c:550:import_mok_state() BS+RT variable info: + MaximumVariableStorageSize:0x000000000000DFE4 + RemainingVariableStorageSize:0x000000000000D21C + MaximumVariableSize:0x0000000000001FC4 + +The most annoying part is that on at least this edk2 build, +SetVariable() /does actually appear to set the variable/, but it returns +EFI_INVALID_PARAMETER. I'm not planning on relying on that behavior. + +So... yeah, the largest *volatile* (i.e. RAM only) variable this edk2 +build will let you create is less than two pages. It's only got 7.9G +free, so I guess it's feeling like space is a little tight. + +We're also not quite preserving that return code well enough for his +workaround to work. + +New plan. We try to create variables the normal way, but we don't +consider not having enough space to be fatal. In that case, we create +an EFI_SECURITY_LIST with one sha256sum in it, with a value of all 0, +and try to add that so we're sure there's /something/ there that's +innocuous. On systems where the first SetVariable() / +QueryVariableInfo() lied to us, the correct variable should be there, +otherwise the one with the zero-hash will be. + +We then also build a config table to hold this info and install that. + +The config table is a packed array of this struct: + +struct mok_variable_config_entry { + CHAR8 name[256]; + UINT64 data_size; + UINT8 data[]; +}; + +There will be N+1 entries, and the last entry is all 0 for name and +data_size. The total allocation size will always be a multiple of 4096. +In the typical RHEL 7.9 case that means it'll be around 5 pages. + +It's installed with this guid: + +c451ed2b-9694-45d3-baba-ed9f8988a389 + +Anything that can go wrong will. + +Signed-off-by: Peter Jones +Upstream: not yet, I don't want people to read this before Wednesday. +Signed-off-by: Peter Jones +--- + lib/guid.c | 2 + + mok.c | 150 ++++++++++++++++++++++++++++++++++++++++++++----- + include/guid.h | 2 + + 3 files changed, 140 insertions(+), 14 deletions(-) + +diff --git a/lib/guid.c b/lib/guid.c +index 57c02fbeecd..99ff400a0ab 100644 +--- a/lib/guid.c ++++ b/lib/guid.c +@@ -36,4 +36,6 @@ EFI_GUID EFI_SECURE_BOOT_DB_GUID = { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, + EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID = SIMPLE_FILE_SYSTEM_PROTOCOL; + EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } }; + EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; ++ + EFI_GUID SHIM_LOCK_GUID = {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }; ++EFI_GUID MOK_VARIABLE_STORE = {0xc451ed2b, 0x9694, 0x45d3, {0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89} }; +diff --git a/mok.c b/mok.c +index e69857f3c37..4e141fb21fc 100644 +--- a/mok.c ++++ b/mok.c +@@ -68,6 +68,7 @@ struct mok_state_variable { + CHAR16 *name; + char *name8; + CHAR16 *rtname; ++ char *rtname8; + EFI_GUID *guid; + + UINT8 *data; +@@ -121,6 +122,7 @@ struct mok_state_variable mok_state_variables[] = { + {.name = L"MokList", + .name8 = "MokList", + .rtname = L"MokListRT", ++ .rtname8 = "MokListRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, +@@ -133,12 +135,14 @@ struct mok_state_variable mok_state_variables[] = { + .build_cert_size = &build_cert_size, + #endif /* defined(ENABLE_SHIM_CERT) */ + .flags = MOK_MIRROR_KEYDB | ++ MOK_MIRROR_DELETE_FIRST | + MOK_VARIABLE_LOG, + .pcr = 14, + }, + {.name = L"MokListX", + .name8 = "MokListX", + .rtname = L"MokListXRT", ++ .rtname8 = "MokListXRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, +@@ -147,12 +151,14 @@ struct mok_state_variable mok_state_variables[] = { + .addend = &vendor_deauthorized, + .addend_size = &vendor_deauthorized_size, + .flags = MOK_MIRROR_KEYDB | ++ MOK_MIRROR_DELETE_FIRST | + MOK_VARIABLE_LOG, + .pcr = 14, + }, + {.name = L"MokSBState", + .name8 = "MokSBState", + .rtname = L"MokSBStateRT", ++ .rtname8 = "MokSBStateRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, +@@ -166,6 +172,7 @@ struct mok_state_variable mok_state_variables[] = { + {.name = L"MokDBState", + .name8 = "MokDBState", + .rtname = L"MokIgnoreDB", ++ .rtname8 = "MokIgnoreDB", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, +@@ -204,6 +211,7 @@ mirror_one_mok_variable(struct mok_state_variable *v) + * we're always mirroring the original data, whether this is an efi + * security database or not + */ ++ dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname); + dprint(L"v->data_size:%lu v->data:0x%08llx\n", v->data_size, v->data); + dprint(L"FullDataSize:%lu FullData:0x%08llx\n", FullDataSize, FullData); + if (v->data_size) { +@@ -299,6 +307,7 @@ mirror_one_mok_variable(struct mok_state_variable *v) + } + } + ++ + /* + * Now we have the full size + */ +@@ -417,28 +426,72 @@ mirror_one_mok_variable(struct mok_state_variable *v) + FullDataSize, FullData, p, p-(uintptr_t)FullData); + } + +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%016llx p:0x%016llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); + if (FullDataSize) { +- dprint(L"Setting %s with %lu bytes of data\n", +- v->rtname, FullDataSize); ++ uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ EFI_VARIABLE_RUNTIME_ACCESS; ++ uint64_t max_storage_sz = 0; ++ uint64_t remaining_sz = 0; ++ uint64_t max_var_sz = 0; ++ UINT8 *tmp = NULL; ++ UINTN tmpsz = 0; ++ ++ efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz, ++ &remaining_sz, &max_var_sz); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Could not get variable storage info: %r\n", efi_status); ++ return efi_status; ++ } ++ dprint(L"calling SetVariable(\"%s\", 0x%016llx, 0x%08lx, %lu, 0x%016llx)\n", ++ v->rtname, v->guid, ++ EFI_VARIABLE_BOOTSERVICE_ACCESS ++ | EFI_VARIABLE_RUNTIME_ACCESS, ++ FullDataSize, FullData); + efi_status = gRT->SetVariable(v->rtname, v->guid, +- EFI_VARIABLE_BOOTSERVICE_ACCESS | +- EFI_VARIABLE_RUNTIME_ACCESS, ++ EFI_VARIABLE_BOOTSERVICE_ACCESS ++ | EFI_VARIABLE_RUNTIME_ACCESS, + FullDataSize, FullData); +- if (EFI_ERROR(efi_status)) { +- perror(L"Failed to set %s: %r\n", +- v->rtname, efi_status); ++ if (efi_status == EFI_INVALID_PARAMETER && max_var_sz < FullDataSize) { ++ /* ++ * In this case we're going to try to create a ++ * dummy variable so that there's one there. It ++ * may or may not work, because on some firmware ++ * builds when the SetVariable call above fails it ++ * does actually set the variable(!), so aside from ++ * not using the allocation if it doesn't work, we ++ * don't care about failures here. ++ */ ++ console_print(L"WARNING: Maximum volatile variable size is %lu.\n", max_var_sz); ++ console_print(L"WARNING: Cannot set %s (%lu bytes)\n", v->rtname, FullDataSize); ++ perror(L"Failed to set %s: %r\n", v->rtname, efi_status); ++ efi_status = variable_create_esl( ++ null_sha256, sizeof(null_sha256), ++ &EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID, ++ &tmp, &tmpsz); ++ /* ++ * from here we don't really care if it works or ++ * doens't. ++ */ ++ if (!EFI_ERROR(efi_status) && tmp && tmpsz) { ++ gRT->SetVariable(v->rtname, v->guid, ++ EFI_VARIABLE_BOOTSERVICE_ACCESS ++ | EFI_VARIABLE_RUNTIME_ACCESS, ++ tmpsz, tmp); ++ FreePool(tmp); ++ } ++ efi_status = EFI_INVALID_PARAMETER; ++ } else if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to set %s: %r\n", v->rtname, efi_status); + } + } +- if (v->data && v->data_size) { ++ if (v->data && v->data_size && v->data != FullData) { + FreePool(v->data); + v->data = NULL; + v->data_size = 0; + } +- if (FullData && FullDataSize) { +- FreePool(FullData); +- } ++ v->data = FullData; ++ v->data_size = FullDataSize; + dprint(L"returning %r\n", efi_status); + return efi_status; + } +@@ -454,8 +507,11 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret) + BOOLEAN present = FALSE; + + if (v->rtname) { +- if (v->flags & MOK_MIRROR_DELETE_FIRST) +- LibDeleteVariable(v->rtname, v->guid); ++ if (v->flags & MOK_MIRROR_DELETE_FIRST) { ++ dprint(L"deleting \"%s\"\n", v->rtname); ++ efi_status = LibDeleteVariable(v->rtname, v->guid); ++ dprint(L"LibDeleteVariable(\"%s\",...) => %r\n", v->rtname, efi_status); ++ } + + efi_status = mirror_one_mok_variable(v); + if (EFI_ERROR(efi_status)) { +@@ -505,6 +561,12 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret) + return ret; + } + ++struct mok_variable_config_entry { ++ CHAR8 name[256]; ++ UINT64 data_size; ++ UINT8 data[]; ++}; ++ + /* + * Verify our non-volatile MoK state. This checks the variables above + * accessable and have valid attributes. If they don't, it removes +@@ -527,6 +589,11 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + user_insecure_mode = 0; + ignore_db = 0; + ++ UINT64 config_sz = 0; ++ UINT8 *config_table = NULL; ++ size_t npages = 0; ++ struct mok_variable_config_entry config_template; ++ + dprint(L"importing mok state\n"); + for (i = 0; mok_state_variables[i].name != NULL; i++) { + struct mok_state_variable *v = &mok_state_variables[i]; +@@ -579,6 +646,61 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + } + + ret = maybe_mirror_one_mok_variable(v, ret); ++ if (v->data && v->data_size) { ++ config_sz += v->data_size; ++ config_sz += sizeof(config_template); ++ } ++ } ++ ++ /* ++ * Alright, so we're going to copy these to a config table. The ++ * table is a packed array of N+1 struct mok_variable_config_entry ++ * items, with the last item having all zero's in name and ++ * data_size. ++ */ ++ if (config_sz) { ++ config_sz += sizeof(config_template); ++ npages = ALIGN_VALUE(config_sz, PAGE_SIZE) >> EFI_PAGE_SHIFT; ++ config_table = NULL; ++ efi_status = gBS->AllocatePages(AllocateAnyPages, ++ EfiRuntimeServicesData, ++ npages, ++ (EFI_PHYSICAL_ADDRESS *)&config_table); ++ if (EFI_ERROR(efi_status) || !config_table) { ++ console_print(L"Allocating %lu pages for mok config table failed: %r\n", ++ npages, efi_status); ++ if (ret != EFI_SECURITY_VIOLATION) ++ ret = efi_status; ++ config_table = NULL; ++ } else { ++ ZeroMem(config_table, npages << EFI_PAGE_SHIFT); ++ } ++ } ++ ++ UINT8 *p = (UINT8 *)config_table; ++ for (i = 0; p && mok_state_variables[i].name != NULL; i++) { ++ struct mok_state_variable *v = &mok_state_variables[i]; ++ ++ ZeroMem(&config_template, sizeof(config_template)); ++ strncpya(config_template.name, (CHAR8 *)v->rtname8, 255); ++ config_template.name[255] = '\0'; ++ ++ config_template.data_size = v->data_size; ++ ++ CopyMem(p, &config_template, sizeof(config_template)); ++ p += sizeof(config_template); ++ CopyMem(p, v->data, v->data_size); ++ p += v->data_size; ++ } ++ if (p) { ++ ZeroMem(&config_template, sizeof(config_template)); ++ CopyMem(p, &config_template, sizeof(config_template)); ++ ++ efi_status = gBS->InstallConfigurationTable(&MOK_VARIABLE_STORE, ++ config_table); ++ if (EFI_ERROR(efi_status)) { ++ console_print(L"Couldn't install MoK configuration table\n"); ++ } + } + + /* +diff --git a/include/guid.h b/include/guid.h +index 81689d6cc1a..91b14d96146 100644 +--- a/include/guid.h ++++ b/include/guid.h +@@ -35,4 +35,6 @@ extern EFI_GUID SECURITY_PROTOCOL_GUID; + extern EFI_GUID SECURITY2_PROTOCOL_GUID; + extern EFI_GUID SHIM_LOCK_GUID; + ++extern EFI_GUID MOK_VARIABLE_STORE; ++ + #endif /* SHIM_GUID_H */ +-- +2.26.2 + diff --git a/SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch b/SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch new file mode 100644 index 0000000..86467e3 --- /dev/null +++ b/SOURCES/0062-Implement-lennysz-s-suggestions-for-MokListRT.patch @@ -0,0 +1,991 @@ +From 65be350308783a8ef537246c8ad0545b4e6ad069 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sat, 25 Jul 2020 22:13:57 -0400 +Subject: [PATCH 62/62] Implement lennysz's suggestions for MokListRT + +Signed-off-by: Peter Jones +--- + mok.c | 726 ++++++++++++++++++++++++++++++++-------------- + shim.c | 7 +- + include/PeImage.h | 3 +- + 3 files changed, 515 insertions(+), 221 deletions(-) + +diff --git a/mok.c b/mok.c +index 4e141fb21fc..3e6c7e43025 100644 +--- a/mok.c ++++ b/mok.c +@@ -7,6 +7,8 @@ + + #include + ++#include "hexdump.h" ++ + /* + * Check if a variable exists + */ +@@ -25,6 +27,15 @@ static BOOLEAN check_var(CHAR16 *varname) + return FALSE; + } + ++#define SetVariable(name, guid, attrs, varsz, var) ({ \ ++ EFI_STATUS efi_status_; \ ++ efi_status_ = gRT->SetVariable(name, guid, attrs, varsz, var); \ ++ dprint_(L"%a:%d:%a() SetVariable(\"%s\", ... varsz=0x%llx) = %r\n",\ ++ __FILE__, __LINE__, __func__, \ ++ name, varsz, efi_status_); \ ++ efi_status_; \ ++}) ++ + /* + * If the OS has set any of these variables we need to drop into MOK and + * handle them appropriately +@@ -193,33 +204,296 @@ should_mirror_build_cert(struct mok_state_variable *v) + + static const uint8_t null_sha256[32] = { 0, }; + ++typedef UINTN SIZE_T; ++ ++static EFI_STATUS ++get_max_var_sz(UINT32 attrs, SIZE_T *max_var_szp) ++{ ++ EFI_STATUS efi_status; ++ uint64_t max_storage_sz = 0; ++ uint64_t remaining_sz = 0; ++ uint64_t max_var_sz = 0; ++ ++ *max_var_szp = 0; ++ efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz, ++ &remaining_sz, &max_var_sz); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Could not get variable storage info: %r\n", efi_status); ++ return efi_status; ++ } ++ ++ /* ++ * I just don't trust implementations to not be showing static data ++ * for max_var_sz ++ */ ++ *max_var_szp = (max_var_sz < remaining_sz) ? max_var_sz : remaining_sz; ++ dprint("max_var_sz:%lx remaining_sz:%lx max_storage_sz:%lx\n", ++ max_var_sz, remaining_sz, max_storage_sz); ++ return efi_status; ++} ++ ++/* ++ * If any entries fit in < maxsz, and nothing goes wrong, create a variable ++ * of the given name and guid with as many esd entries as possible in it, ++ * and updates *esdp with what would be the next entry (even if makes *esdp ++ * > esl+esl->SignatureListSize), and returns whatever SetVariable() ++ * returns ++ * ++ * If no entries fit (i.e. sizeof(esl) + esl->SignatureSize > maxsz), ++ * returns EFI_BUFFER_TOO_SMALL; ++ */ ++static EFI_STATUS ++mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs, ++ EFI_SIGNATURE_LIST *esl, EFI_SIGNATURE_DATA *esd, ++ UINTN *newsz, SIZE_T maxsz) ++{ ++ EFI_STATUS efi_status; ++ SIZE_T howmany, varsz = 0, esdsz; ++ UINT8 *var, *data; ++ ++ howmany = min((maxsz - sizeof(*esl)) / esl->SignatureSize, ++ (esl->SignatureListSize - sizeof(*esl)) / esl->SignatureSize); ++ if (howmany < 1) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ /* ++ * We always assume esl->SignatureHeaderSize is 0 (and so far, ++ * that's true as per UEFI 2.8) ++ */ ++ esdsz = howmany * esl->SignatureSize; ++ data = (UINT8 *)esd; ++ dprint(L"Trying to add %lx signatures to \"%s\" of size %lx\n", ++ howmany, name, esl->SignatureSize); ++ ++ /* ++ * Because of the semantics of variable_create_esl(), the first ++ * owner guid from the data is not part of esdsz, or the data. ++ * ++ * Compensate here. ++ */ ++ efi_status = variable_create_esl(data + sizeof(EFI_GUID), ++ esdsz - sizeof(EFI_GUID), ++ &esl->SignatureType, ++ &esd->SignatureOwner, ++ &var, &varsz); ++ if (EFI_ERROR(efi_status) || !var || !varsz) { ++ LogError(L"Couldn't allocate %lu bytes for mok variable \"%s\": %r\n", ++ varsz, var, efi_status); ++ return efi_status; ++ } ++ ++ dprint(L"new esl:\n"); ++ dhexdumpat(var, varsz, 0); ++ ++ efi_status = SetVariable(name, guid, attrs, varsz, var); ++ FreePool(var); ++ if (EFI_ERROR(efi_status)) { ++ LogError(L"Couldn't create mok variable \"%s\": %r\n", ++ varsz, var, efi_status); ++ return efi_status; ++ } ++ ++ *newsz = esdsz; ++ ++ return efi_status; ++} ++ ++static EFI_STATUS ++mirror_mok_db(CHAR16 *name, CHAR8 *name8, EFI_GUID *guid, UINT32 attrs, ++ UINT8 *FullData, SIZE_T FullDataSize, BOOLEAN only_first) ++{ ++ EFI_STATUS efi_status = EFI_SUCCESS; ++ SIZE_T max_var_sz; ++ ++ if (only_first) { ++ efi_status = get_max_var_sz(attrs, &max_var_sz); ++ if (EFI_ERROR(efi_status)) { ++ LogError(L"Could not get maximum variable size: %r", ++ efi_status); ++ return efi_status; ++ } ++ ++ if (FullDataSize <= max_var_sz) { ++ efi_status = SetVariable(name, guid, attrs, ++ FullDataSize, FullData); ++ return efi_status; ++ } ++ } ++ ++ CHAR16 *namen; ++ CHAR8 *namen8; ++ UINTN namelen, namesz; ++ ++ namelen = StrLen(name); ++ namesz = namelen * 2; ++ if (only_first) { ++ namen = name; ++ namen8 = name8; ++ } else { ++ namelen += 18; ++ namesz += 34; ++ namen = AllocateZeroPool(namesz); ++ if (!namen) { ++ LogError(L"Could not allocate %lu bytes", namesz); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ namen8 = AllocateZeroPool(namelen); ++ if (!namen8) { ++ FreePool(namen); ++ LogError(L"Could not allocate %lu bytes", namelen); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ } ++ ++ UINTN pos, i; ++ const SIZE_T minsz = sizeof(EFI_SIGNATURE_LIST) ++ + sizeof(EFI_SIGNATURE_DATA) ++ + SHA1_DIGEST_SIZE; ++ BOOLEAN did_one = FALSE; ++ ++ /* ++ * Create any entries that can fit. ++ */ ++ if (!only_first) { ++ dprint(L"full data for \"%s\":\n", name); ++ dhexdumpat(FullData, FullDataSize, 0); ++ } ++ EFI_SIGNATURE_LIST *esl = NULL; ++ UINTN esl_end_pos = 0; ++ for (i = 0, pos = 0; FullDataSize - pos >= minsz && FullData; ) { ++ EFI_SIGNATURE_DATA *esd = NULL; ++ ++ dprint(L"pos:0x%llx FullDataSize:0x%llx\n", pos, FullDataSize); ++ if (esl == NULL || pos >= esl_end_pos) { ++ UINT8 *nesl = FullData + pos; ++ dprint(L"esl:0x%llx->0x%llx\n", esl, nesl); ++ esl = (EFI_SIGNATURE_LIST *)nesl; ++ esl_end_pos = pos + esl->SignatureListSize; ++ dprint(L"pos:0x%llx->0x%llx\n", pos, pos + sizeof(*esl)); ++ pos += sizeof(*esl); ++ } ++ esd = (EFI_SIGNATURE_DATA *)(FullData + pos); ++ if (pos >= FullDataSize) ++ break; ++ if (esl->SignatureListSize == 0 || esl->SignatureSize == 0) ++ break; ++ ++ dprint(L"esl[%lu] 0x%llx = {sls=0x%lx, ss=0x%lx} esd:0x%llx\n", ++ i, esl, esl->SignatureListSize, esl->SignatureSize, esd); ++ ++ if (!only_first) { ++ SPrint(namen, namelen, L"%s%lu", name, i); ++ namen[namelen-1] = 0; ++ /* uggggh */ ++ UINTN j; ++ for (j = 0; j < namelen; j++) ++ namen8[j] = (CHAR8)(namen[j] & 0xff); ++ namen8[namelen - 1] = 0; ++ } ++ ++ /* ++ * In case max_var_sz is computed dynamically, refresh the ++ * value here. ++ */ ++ efi_status = get_max_var_sz(attrs, &max_var_sz); ++ if (EFI_ERROR(efi_status)) { ++ LogError(L"Could not get maximum variable size: %r", ++ efi_status); ++ if (!only_first) { ++ FreePool(namen); ++ FreePool(namen8); ++ } ++ return efi_status; ++ } ++ ++ SIZE_T howmany; ++ UINTN adj = 0; ++ howmany = min((max_var_sz - sizeof(*esl)) / esl->SignatureSize, ++ (esl->SignatureListSize - sizeof(*esl)) / esl->SignatureSize); ++ if (!only_first && i == 0 && howmany >= 1) { ++ adj = howmany * esl->SignatureSize; ++ dprint(L"pos:0x%llx->0x%llx\n", pos, pos + adj); ++ pos += adj; ++ i++; ++ continue; ++ ++ } ++ ++ efi_status = mirror_one_esl(namen, guid, attrs, ++ esl, esd, &adj, max_var_sz); ++ dprint(L"esd:0x%llx adj:0x%llx\n", esd, adj); ++ if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) { ++ LogError(L"Could not mirror mok variable \"%s\": %r\n", ++ namen, efi_status); ++ break; ++ } ++ ++ if (!EFI_ERROR(efi_status)) { ++ did_one = TRUE; ++ if (only_first) ++ break; ++ dprint(L"pos:0x%llx->0x%llx\n", pos, pos + adj); ++ pos += adj; ++ i++; ++ } ++ } ++ ++ if (only_first && !did_one) { ++ /* ++ * In this case we're going to try to create a ++ * dummy variable so that there's one there. It ++ * may or may not work, because on some firmware ++ * builds when the SetVariable call above fails it ++ * does actually set the variable(!), so aside from ++ * not using the allocation if it doesn't work, we ++ * don't care about failures here. ++ */ ++ UINT8 *var; ++ UINTN varsz; ++ ++ efi_status = variable_create_esl( ++ null_sha256, sizeof(null_sha256), ++ &EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID, ++ &var, &varsz); ++ /* ++ * from here we don't really care if it works or ++ * doesn't. ++ */ ++ if (!EFI_ERROR(efi_status) && var && varsz) { ++ SetVariable(name, guid, ++ EFI_VARIABLE_BOOTSERVICE_ACCESS ++ | EFI_VARIABLE_RUNTIME_ACCESS, ++ varsz, var); ++ FreePool(var); ++ } ++ efi_status = EFI_INVALID_PARAMETER; ++ } else if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to set %s: %r\n", name, efi_status); ++ } ++ return efi_status; ++} ++ ++ + static EFI_STATUS nonnull(1) +-mirror_one_mok_variable(struct mok_state_variable *v) ++mirror_one_mok_variable(struct mok_state_variable *v, ++ BOOLEAN only_first) + { + EFI_STATUS efi_status = EFI_SUCCESS; + uint8_t *FullData = NULL; + size_t FullDataSize = 0; + vendor_addend_category_t addend_category = VENDOR_ADDEND_NONE; + uint8_t *p = NULL; +- ++ uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ EFI_VARIABLE_RUNTIME_ACCESS; ++ BOOLEAN measure = v->flags & MOK_VARIABLE_MEASURE; ++ BOOLEAN log = v->flags & MOK_VARIABLE_LOG; + size_t build_cert_esl_sz = 0, addend_esl_sz = 0; ++ bool reuse = FALSE; + + if (v->categorize_addend) + addend_category = v->categorize_addend(v); + +- /* +- * we're always mirroring the original data, whether this is an efi +- * security database or not +- */ +- dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname); +- dprint(L"v->data_size:%lu v->data:0x%08llx\n", v->data_size, v->data); +- dprint(L"FullDataSize:%lu FullData:0x%08llx\n", FullDataSize, FullData); +- if (v->data_size) { +- FullDataSize = v->data_size; +- dprint(L"FullDataSize:%lu FullData:0x%08llx\n", +- FullDataSize, FullData); +- } +- + /* + * if it is, there's more data + */ +@@ -227,7 +501,7 @@ mirror_one_mok_variable(struct mok_state_variable *v) + + /* + * We're mirroring (into) an efi security database, aka an +- * array of efi_signature_list_t. Its layout goes like: ++ * array of EFI_SIGNATURE_LIST. Its layout goes like: + * + * existing_variable_data + * existing_variable_data_size +@@ -251,30 +525,7 @@ mirror_one_mok_variable(struct mok_state_variable *v) + */ + + /* +- * first bit is existing data, but we added that above +- */ +- +- /* +- * then the build cert if it's there +- */ +- if (should_mirror_build_cert(v)) { +- efi_status = fill_esl(*v->build_cert, +- *v->build_cert_size, +- &EFI_CERT_TYPE_X509_GUID, +- &SHIM_LOCK_GUID, +- NULL, &build_cert_esl_sz); +- if (efi_status != EFI_BUFFER_TOO_SMALL) { +- perror(L"Could not add built-in cert to %s: %r\n", +- v->name, efi_status); +- return efi_status; +- } +- FullDataSize += build_cert_esl_sz; +- dprint(L"FullDataSize:%lu FullData:0x%08llx\n", +- FullDataSize, FullData); +- } +- +- /* +- * then the addend data ++ * *first* vendor_db or vendor_cert + */ + switch (addend_category) { + case VENDOR_ADDEND_DB: +@@ -282,7 +533,7 @@ mirror_one_mok_variable(struct mok_state_variable *v) + * if it's an ESL already, we use it wholesale + */ + FullDataSize += *v->addend_size; +- dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx\n", + FullDataSize, FullData); + break; + case VENDOR_ADDEND_X509: +@@ -296,17 +547,51 @@ mirror_one_mok_variable(struct mok_state_variable *v) + return efi_status; + } + FullDataSize += addend_esl_sz; +- dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx\n", + FullDataSize, FullData); + break; + default: + case VENDOR_ADDEND_NONE: +- dprint(L"FullDataSize:%lu FullData:0x%08llx\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx\n", + FullDataSize, FullData); + break; + } ++ ++ /* ++ * then the build cert if it's there ++ */ ++ if (should_mirror_build_cert(v)) { ++ efi_status = fill_esl(*v->build_cert, ++ *v->build_cert_size, ++ &EFI_CERT_TYPE_X509_GUID, ++ &SHIM_LOCK_GUID, ++ NULL, &build_cert_esl_sz); ++ if (efi_status != EFI_BUFFER_TOO_SMALL) { ++ perror(L"Could not add built-in cert to %s: %r\n", ++ v->name, efi_status); ++ return efi_status; ++ } ++ FullDataSize += build_cert_esl_sz; ++ dprint(L"FullDataSize:0x%lx FullData:0x%llx\n", ++ FullDataSize, FullData); ++ } ++ + } + ++ /* ++ * we're always mirroring the original data, whether this is an efi ++ * security database or not ++ */ ++ dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname); ++ dprint(L"v->data_size:%lu v->data:0x%llx\n", v->data_size, v->data); ++ dprint(L"FullDataSize:%lu FullData:0x%llx\n", FullDataSize, FullData); ++ if (v->data_size) { ++ FullDataSize += v->data_size; ++ dprint(L"FullDataSize:%lu FullData:0x%llx\n", ++ FullDataSize, FullData); ++ } ++ if (v->data_size == FullDataSize) ++ reuse = TRUE; + + /* + * Now we have the full size +@@ -316,38 +601,33 @@ mirror_one_mok_variable(struct mok_state_variable *v) + * allocate the buffer, or use the old one if it's just the + * existing data. + */ +- if (FullDataSize != v->data_size) { +- dprint(L"FullDataSize:%lu FullData:0x%08llx allocating FullData\n", ++ if (FullDataSize == v->data_size) { ++ FullData = v->data; ++ FullDataSize = v->data_size; ++ p = FullData + FullDataSize; ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ v->data = NULL; ++ v->data_size = 0; ++ } else { ++ dprint(L"FullDataSize:%lu FullData:0x%llx allocating FullData\n", + FullDataSize, FullData); +- FullData = AllocatePool(FullDataSize); ++ /* ++ * make sure we've got some zeroes at the end, just ++ * in case. ++ */ ++ UINTN allocsz = FullDataSize + sizeof(EFI_SIGNATURE_LIST); ++ allocsz = ALIGN_VALUE(allocsz, 4096); ++ FullData = AllocateZeroPool(FullDataSize); + if (!FullData) { +- FreePool(v->data); +- v->data = NULL; +- v->data_size = 0; + perror(L"Failed to allocate %lu bytes for %s\n", + FullDataSize, v->name); + return EFI_OUT_OF_RESOURCES; + } + p = FullData; +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", +- FullDataSize, FullData, p, p-(uintptr_t)FullData); +- if (v->data && v->data_size) { +- CopyMem(p, v->data, v->data_size); +- p += v->data_size; +- } +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", +- FullDataSize, FullData, p, p-(uintptr_t)FullData); +- } else { +- FullData = v->data; +- FullDataSize = v->data_size; +- p = FullData + FullDataSize; +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", +- FullDataSize, FullData, p, p-(uintptr_t)FullData); +- v->data = NULL; +- v->data_size = 0; + } + } +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); + + /* +@@ -355,35 +635,13 @@ mirror_one_mok_variable(struct mok_state_variable *v) + */ + if (v->flags & MOK_MIRROR_KEYDB) { + /* +- * first bit is existing data, but again, we added that above ++ * first vendor_cert or vendor_db + */ +- +- /* +- * second is the build cert +- */ +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", +- FullDataSize, FullData, p, p-(uintptr_t)FullData); +- if (should_mirror_build_cert(v)) { +- efi_status = fill_esl(*v->build_cert, +- *v->build_cert_size, +- &EFI_CERT_TYPE_X509_GUID, +- &SHIM_LOCK_GUID, +- p, &build_cert_esl_sz); +- if (EFI_ERROR(efi_status)) { +- perror(L"Could not add built-in cert to %s: %r\n", +- v->name, efi_status); +- return efi_status; +- } +- p += build_cert_esl_sz; +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", +- FullDataSize, FullData, p, p-(uintptr_t)FullData); +- } +- + switch (addend_category) { + case VENDOR_ADDEND_DB: + CopyMem(p, *v->addend, *v->addend_size); + p += *v->addend_size; +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); + break; + case VENDOR_ADDEND_X509: +@@ -397,16 +655,53 @@ mirror_one_mok_variable(struct mok_state_variable *v) + return efi_status; + } + p += addend_esl_sz; +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); + break; + default: + case VENDOR_ADDEND_NONE: +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); + break; + } ++ ++ /* ++ * then is the build cert ++ */ ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ if (should_mirror_build_cert(v)) { ++ efi_status = fill_esl(*v->build_cert, ++ *v->build_cert_size, ++ &EFI_CERT_TYPE_X509_GUID, ++ &SHIM_LOCK_GUID, ++ p, &build_cert_esl_sz); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Could not add built-in cert to %s: %r\n", ++ v->name, efi_status); ++ return efi_status; ++ } ++ p += build_cert_esl_sz; ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ } + } ++ ++ /* ++ * last bit is existing data, unless it's the only thing, ++ * in which case it's already there. ++ */ ++ if (!reuse) { ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ if (v->data && v->data_size) { ++ CopyMem(p, v->data, v->data_size); ++ p += v->data_size; ++ } ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", ++ FullDataSize, FullData, p, p-(uintptr_t)FullData); ++ } ++ + /* + * We always want to create our key databases, so in this case we + * need a dummy entry +@@ -422,68 +717,55 @@ mirror_one_mok_variable(struct mok_state_variable *v) + return efi_status; + } + p = FullData + FullDataSize; +- dprint(L"FullDataSize:%lu FullData:0x%08llx p:0x%08llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); + } + +- dprint(L"FullDataSize:%lu FullData:0x%016llx p:0x%016llx pos:%lld\n", ++ dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n", + FullDataSize, FullData, p, p-(uintptr_t)FullData); +- if (FullDataSize) { +- uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS | +- EFI_VARIABLE_RUNTIME_ACCESS; +- uint64_t max_storage_sz = 0; +- uint64_t remaining_sz = 0; +- uint64_t max_var_sz = 0; +- UINT8 *tmp = NULL; +- UINTN tmpsz = 0; +- +- efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz, +- &remaining_sz, &max_var_sz); +- if (EFI_ERROR(efi_status)) { +- perror(L"Could not get variable storage info: %r\n", efi_status); +- return efi_status; +- } +- dprint(L"calling SetVariable(\"%s\", 0x%016llx, 0x%08lx, %lu, 0x%016llx)\n", +- v->rtname, v->guid, +- EFI_VARIABLE_BOOTSERVICE_ACCESS +- | EFI_VARIABLE_RUNTIME_ACCESS, +- FullDataSize, FullData); +- efi_status = gRT->SetVariable(v->rtname, v->guid, +- EFI_VARIABLE_BOOTSERVICE_ACCESS +- | EFI_VARIABLE_RUNTIME_ACCESS, +- FullDataSize, FullData); +- if (efi_status == EFI_INVALID_PARAMETER && max_var_sz < FullDataSize) { ++ if (FullDataSize && v->flags & MOK_MIRROR_KEYDB) { ++ dprint(L"calling mirror_mok_db(\"%s\", datasz=%lu)\n", ++ v->rtname, FullDataSize); ++ efi_status = mirror_mok_db(v->rtname, (CHAR8 *)v->rtname8, v->guid, ++ attrs, FullData, FullDataSize, ++ only_first); ++ dprint(L"mirror_mok_db(\"%s\", datasz=%lu) returned %r\n", ++ v->rtname, FullDataSize, efi_status); ++ } else if (FullDataSize && only_first) { ++ efi_status = SetVariable(v->rtname, v->guid, attrs, ++ FullDataSize, FullData); ++ } ++ if (FullDataSize && only_first) { ++ if (measure) { + /* +- * In this case we're going to try to create a +- * dummy variable so that there's one there. It +- * may or may not work, because on some firmware +- * builds when the SetVariable call above fails it +- * does actually set the variable(!), so aside from +- * not using the allocation if it doesn't work, we +- * don't care about failures here. ++ * Measure this into PCR 7 in the Microsoft format + */ +- console_print(L"WARNING: Maximum volatile variable size is %lu.\n", max_var_sz); +- console_print(L"WARNING: Cannot set %s (%lu bytes)\n", v->rtname, FullDataSize); +- perror(L"Failed to set %s: %r\n", v->rtname, efi_status); +- efi_status = variable_create_esl( +- null_sha256, sizeof(null_sha256), +- &EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID, +- &tmp, &tmpsz); ++ efi_status = tpm_measure_variable(v->name, *v->guid, ++ FullDataSize, FullData); ++ if (EFI_ERROR(efi_status)) { ++ dprint(L"tpm_measure_variable(\"%s\",%lu,0x%llx)->%r\n", ++ v->name, FullDataSize, FullData, efi_status); ++ return efi_status; ++ } ++ } ++ ++ if (log) { + /* +- * from here we don't really care if it works or +- * doens't. ++ * Log this variable into whichever PCR the table ++ * says. + */ +- if (!EFI_ERROR(efi_status) && tmp && tmpsz) { +- gRT->SetVariable(v->rtname, v->guid, +- EFI_VARIABLE_BOOTSERVICE_ACCESS +- | EFI_VARIABLE_RUNTIME_ACCESS, +- tmpsz, tmp); +- FreePool(tmp); ++ EFI_PHYSICAL_ADDRESS datap = ++ (EFI_PHYSICAL_ADDRESS)(UINTN)FullData, ++ efi_status = tpm_log_event(datap, FullDataSize, ++ v->pcr, (CHAR8 *)v->name8); ++ if (EFI_ERROR(efi_status)) { ++ dprint(L"tpm_log_event(0x%llx, %lu, %lu, \"%s\")->%r\n", ++ FullData, FullDataSize, v->pcr, v->name, ++ efi_status); ++ return efi_status; + } +- efi_status = EFI_INVALID_PARAMETER; +- } else if (EFI_ERROR(efi_status)) { +- perror(L"Failed to set %s: %r\n", v->rtname, efi_status); + } ++ + } + if (v->data && v->data_size && v->data != FullData) { + FreePool(v->data); +@@ -501,19 +783,20 @@ mirror_one_mok_variable(struct mok_state_variable *v) + * EFI_SECURITY_VIOLATION status at the same time. + */ + static EFI_STATUS nonnull(1) +-maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret) ++maybe_mirror_one_mok_variable(struct mok_state_variable *v, ++ EFI_STATUS ret, BOOLEAN only_first) + { + EFI_STATUS efi_status; + BOOLEAN present = FALSE; + + if (v->rtname) { +- if (v->flags & MOK_MIRROR_DELETE_FIRST) { ++ if (!only_first && (v->flags & MOK_MIRROR_DELETE_FIRST)) { + dprint(L"deleting \"%s\"\n", v->rtname); + efi_status = LibDeleteVariable(v->rtname, v->guid); + dprint(L"LibDeleteVariable(\"%s\",...) => %r\n", v->rtname, efi_status); + } + +- efi_status = mirror_one_mok_variable(v); ++ efi_status = mirror_one_mok_variable(v, only_first); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; +@@ -530,34 +813,6 @@ maybe_mirror_one_mok_variable(struct mok_state_variable *v, EFI_STATUS ret) + *v->state = v->data[0]; + } + +- if (v->flags & MOK_VARIABLE_MEASURE) { +- /* +- * Measure this into PCR 7 in the Microsoft format +- */ +- efi_status = tpm_measure_variable(v->name, *v->guid, +- v->data_size, +- v->data); +- if (EFI_ERROR(efi_status)) { +- if (ret != EFI_SECURITY_VIOLATION) +- ret = efi_status; +- } +- } +- +- if (v->flags & MOK_VARIABLE_LOG) { +- /* +- * Log this variable into whichever PCR the table +- * says. +- */ +- EFI_PHYSICAL_ADDRESS datap = +- (EFI_PHYSICAL_ADDRESS)(UINTN)v->data, +- efi_status = tpm_log_event(datap, v->data_size, +- v->pcr, (CHAR8 *)v->name8); +- if (EFI_ERROR(efi_status)) { +- if (ret != EFI_SECURITY_VIOLATION) +- ret = efi_status; +- } +- } +- + return ret; + } + +@@ -567,6 +822,66 @@ struct mok_variable_config_entry { + UINT8 data[]; + }; + ++EFI_STATUS import_one_mok_state(struct mok_state_variable *v, ++ BOOLEAN only_first) ++{ ++ EFI_STATUS ret = EFI_SUCCESS; ++ EFI_STATUS efi_status; ++ ++ user_insecure_mode = 0; ++ ignore_db = 0; ++ ++ UINT32 attrs = 0; ++ BOOLEAN delete = FALSE; ++ ++ dprint(L"importing mok state for \"%s\"\n", v->name); ++ ++ efi_status = get_variable_attr(v->name, ++ &v->data, &v->data_size, ++ *v->guid, &attrs); ++ if (efi_status == EFI_NOT_FOUND) { ++ v->data = NULL; ++ v->data_size = 0; ++ } else if (EFI_ERROR(efi_status)) { ++ perror(L"Could not verify %s: %r\n", v->name, ++ efi_status); ++ delete = TRUE; ++ } else { ++ if (!(attrs & v->yes_attr)) { ++ perror(L"Variable %s is missing attributes:\n", ++ v->name); ++ perror(L" 0x%08x should have 0x%08x set.\n", ++ attrs, v->yes_attr); ++ delete = TRUE; ++ } ++ if (attrs & v->no_attr) { ++ perror(L"Variable %s has incorrect attribute:\n", ++ v->name); ++ perror(L" 0x%08x should not have 0x%08x set.\n", ++ attrs, v->no_attr); ++ delete = TRUE; ++ } ++ } ++ if (delete == TRUE) { ++ perror(L"Deleting bad variable %s\n", v->name); ++ efi_status = LibDeleteVariable(v->name, v->guid); ++ if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to erase %s\n", v->name); ++ ret = EFI_SECURITY_VIOLATION; ++ } ++ FreePool(v->data); ++ v->data = NULL; ++ v->data_size = 0; ++ } ++ ++ dprint(L"maybe mirroring \"%s\". original data:\n", v->name); ++ dhexdumpat(v->data, v->data_size, 0); ++ ++ ret = maybe_mirror_one_mok_variable(v, ret, only_first); ++ dprint(L"returning %r\n", ret); ++ return ret; ++} ++ + /* + * Verify our non-volatile MoK state. This checks the variables above + * accessable and have valid attributes. If they don't, it removes +@@ -594,58 +909,22 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + size_t npages = 0; + struct mok_variable_config_entry config_template; + +- dprint(L"importing mok state\n"); ++ dprint(L"importing minimal mok state variables\n"); + for (i = 0; mok_state_variables[i].name != NULL; i++) { + struct mok_state_variable *v = &mok_state_variables[i]; +- UINT32 attrs = 0; +- BOOLEAN delete = FALSE; + +- efi_status = get_variable_attr(v->name, +- &v->data, &v->data_size, +- *v->guid, &attrs); +- dprint(L"maybe mirroring %s\n", v->name); +- if (efi_status == EFI_NOT_FOUND) { +- v->data = NULL; +- v->data_size = 0; +- } else if (EFI_ERROR(efi_status)) { +- perror(L"Could not verify %s: %r\n", v->name, +- efi_status); ++ efi_status = import_one_mok_state(v, TRUE); ++ if (EFI_ERROR(efi_status)) { ++ dprint(L"import_one_mok_state(ih, \"%s\", TRUE): %r\n", ++ v->rtname); + /* + * don't clobber EFI_SECURITY_VIOLATION from some + * other variable in the list. + */ + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; +- delete = TRUE; +- } else { +- if (!(attrs & v->yes_attr)) { +- perror(L"Variable %s is missing attributes:\n", +- v->name); +- perror(L" 0x%08x should have 0x%08x set.\n", +- attrs, v->yes_attr); +- delete = TRUE; +- } +- if (attrs & v->no_attr) { +- perror(L"Variable %s has incorrect attribute:\n", +- v->name); +- perror(L" 0x%08x should not have 0x%08x set.\n", +- attrs, v->no_attr); +- delete = TRUE; +- } +- } +- if (delete == TRUE) { +- perror(L"Deleting bad variable %s\n", v->name); +- efi_status = LibDeleteVariable(v->name, v->guid); +- if (EFI_ERROR(efi_status)) { +- perror(L"Failed to erase %s\n", v->name); +- ret = EFI_SECURITY_VIOLATION; +- } +- FreePool(v->data); +- v->data = NULL; +- v->data_size = 0; + } + +- ret = maybe_mirror_one_mok_variable(v, ret); + if (v->data && v->data_size) { + config_sz += v->data_size; + config_sz += sizeof(config_template); +@@ -669,8 +948,6 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + if (EFI_ERROR(efi_status) || !config_table) { + console_print(L"Allocating %lu pages for mok config table failed: %r\n", + npages, efi_status); +- if (ret != EFI_SECURITY_VIOLATION) +- ret = efi_status; + config_table = NULL; + } else { + ZeroMem(config_table, npages << EFI_PAGE_SHIFT); +@@ -703,6 +980,16 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + } + } + ++ /* ++ * This is really just to make it easy for userland. ++ */ ++ dprint(L"importing full mok state variables\n"); ++ for (i = 0; mok_state_variables[i].name != NULL; i++) { ++ struct mok_state_variable *v = &mok_state_variables[i]; ++ ++ import_one_mok_state(v, FALSE); ++ } ++ + /* + * Enter MokManager if necessary. Any actual *changes* here will + * cause MokManager to demand a machine reboot, so this is safe to +@@ -712,6 +999,9 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) + efi_status = check_mok_request(image_handle); + dprint(L"mok returned %r\n", efi_status); + if (EFI_ERROR(efi_status)) { ++ /* ++ * don't clobber EFI_SECURITY_VIOLATION ++ */ + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + return ret; +diff --git a/shim.c b/shim.c +index 9248642bd57..1a4d7bb9ded 100644 +--- a/shim.c ++++ b/shim.c +@@ -1445,7 +1445,10 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + sha256hash, sha1hash); + + if (EFI_ERROR(efi_status)) { +- console_error(L"Verification failed", efi_status); ++ if (verbose) ++ console_print(L"Verification failed: %r\n", efi_status); ++ else ++ console_error(L"Verification failed", efi_status); + return efi_status; + } else { + if (verbose) +@@ -2648,7 +2651,6 @@ shim_init(void) + { + EFI_STATUS efi_status; + +- setup_verbosity(); + dprint(L"%a", shim_version); + + /* Set the second stage loader */ +@@ -2797,6 +2799,7 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) + * Ensure that gnu-efi functions are available + */ + InitializeLib(image_handle, systab); ++ setup_verbosity(); + + dprint(L"vendor_authorized:0x%08lx vendor_authorized_size:%lu\n", + __FILE__, __LINE__, __func__, vendor_authorized, vendor_authorized_size); +diff --git a/include/PeImage.h b/include/PeImage.h +index a606e8b2a9f..209b96fb8ff 100644 +--- a/include/PeImage.h ++++ b/include/PeImage.h +@@ -768,7 +768,8 @@ typedef struct { + UINT8 CertData[1]; + } WIN_CERTIFICATE_EFI_PKCS; + +-#define SHA256_DIGEST_SIZE 32 ++#define SHA1_DIGEST_SIZE 20 ++#define SHA256_DIGEST_SIZE 32 + #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 + + typedef struct { +-- +2.26.2 + diff --git a/SOURCES/redhatsecurebootca5.cer b/SOURCES/redhatsecurebootca5.cer new file mode 100644 index 0000000000000000000000000000000000000000..dfb0284954861282d1a0ce16c8c5cdc71c27659f GIT binary patch literal 920 zcmXqLVxD5q#8k6@nTe5!iIbtZm{+@~;bN2lFB_*;n@8JsUPeZ4RtAH3LoovpHs(+k zE*{>X)D#7e#1b6^&%9(kLq!95kT^4s1XNrhI5oMnC{@8JKfgr5*-^pNP{}|6ZW6NxP$#b?ru1p1aqn$3D)YB{Qqo zjCvjz?|=HkE#3AN-xTZpws*U~)f@DZ{t~uwMZy8<;F%jD%$u6!n#qYzp^Sryh{C;x9qf@!N=T4ui@b#({ zSD&^p3kNZ=9lAQ9%xdfP9doNToV+k2^LHOFD{5oE&78StJa^8n7$i2k94PWc<&xr*# z`sciS&XK#@>h!OC8{=mczNLHbADCJ+pE=-CsaDOF#s}?5Q)1qq&%R~#cz>QmiAiVx zk5XXYstAL9d+iK-w@u$FESybMIPOFY~9lmn~9nUf%vMc88@((p0B(#qL+!COmt7`j5IhPVzo{cRPw} Pd!}BnFF!b8N6JS4>O*3Z literal 0 HcmV?d00001 diff --git a/SOURCES/securebootca.cer b/SOURCES/securebootca.cer deleted file mode 100644 index b2354007b9668258683b99a68fa5bdd3067c31b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 977 zcmXqLVm@oo#I$t*GZP~d6DPykKFO2}lmD>>ylk9WZ60mkc^MhGSs4s`4b=@)*_cCF zn1$tnQd1N>5=#_OQj1C) zic(WD5=-=w^K%X4#CZ)(42%qc(8R>VG)kP;*xbO#zzoWzwslR6O2{5!WMyD(V&rEq zXkz4IYGPz$nC+~vi6EDouC4!V-;tv&JA zN}nf->iaHo2tM8rAb&8=Njdj{a^${=Z?aE)&k<1VH{Q3Wx7jKD-_5CYum4K4d~JV` z`ccOE*<7!m22LI4&u3g0F3h!NN?ysm?c*7~^lIfF3D-Xhnr_&uU!bJ$?ZS8WW+A0- zr9raw{Iep~On)hDAUrqc*pZy>@YoE^;z#ABPp))utMY{K9XOZuN+87Vv97^}gccFK z6&c%&T=rzVyKuJ1S>c?Rq?77kYS zv==`X%}MC|0a-81!fL?G$oL;QPJxLO7^jR3 zp{b9(0{X(lQ;+K%h_CKtxc%nd+9kH!CBia&JkgcqO9LvF9(I1~^2+p(_fBqs&+@+g zjZG)^b(y8?lr#NV`RkoR|I-BpaSiJiPBV7drX0Bbe!0fPB95K&)ygj1YM5%bK;(6L z=7Y@r2hM%A`uyr;o|A^(c{icYtu_B=WuE^MZ_<i|1QMhsQHT z4}wg*#%C!d<*ePQAKPyWoS|9R;jPUx*P-5Ksuo_~6c3tyKHzf+y+r*{_;vOAw> zmv4Wk&h*1hGe;ze)#t#BH;PsH)$e|FOmna8+@9jW!^ymRMf{q+C84h)mppfN*sxn6 NnfI|Q%N6m!6aeL$dME$@ diff --git a/SPECS/shim-unsigned-x64.spec b/SPECS/shim-unsigned-x64.spec index a5e0483..8af6f10 100644 --- a/SPECS/shim-unsigned-x64.spec +++ b/SPECS/shim-unsigned-x64.spec @@ -18,23 +18,81 @@ Name: shim-unsigned-%{efiarch} Version: 15 -Release: 2%{?dist} +Release: 7%{?dist} Summary: First-stage UEFI bootloader ExclusiveArch: x86_64 License: BSD URL: https://github.com/rhboot/shim Source0: https://github.com/rhboot/shim/releases/download/%{version}/shim-%{version}.tar.bz2 -Source1: securebootca.cer +Source1: redhatsecurebootca5.cer # currently here's what's in our dbx: # nothing. Source2: dbx.esl Source100: shim-find-debuginfo.sh -Patch0001: 0001-Make-sure-that-MOK-variables-always-get-mirrored.patch -Patch0002: 0002-mok-fix-the-mirroring-of-RT-variables.patch -Patch0003: 0003-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch -Patch0004: 0004-Make-VLogError-behave-as-expected.patch +Patch0001: 0001-Make-some-things-dprint-instead-of-console_print.patch +Patch0002: 0002-Makefiles-ensure-m32-gets-propogated-to-our-gcc-para.patch +Patch0003: 0003-Let-MokManager-follow-a-MokTimeout-var-for-timeout-l.patch +Patch0004: 0004-httpboot-return-EFI_NOT_FOUND-when-it-fails-to-find-.patch +Patch0005: 0005-httpboot-print-more-messages-when-it-fails-to-set-IP.patch +Patch0006: 0006-httpboot-allow-the-IPv4-gateway-to-be-empty.patch +Patch0007: 0007-httpboot-show-the-error-message-for-the-ChildHandle.patch +Patch0008: 0008-Fix-typo-in-debug-path-in-shim.h.patch +Patch0009: 0009-MokManager-Stop-using-EFI_VARIABLE_APPEND_WRITE.patch +Patch0010: 0010-shim-Extend-invalid-reloc-size-warning-message.patch +Patch0011: 0011-Add-GRUB-s-PCR-Usage-to-README.tpm.patch +Patch0012: 0012-Fix-the-compile-error-of-mkdir-wrong-directory.patch +Patch0013: 0013-shim-Properly-generate-absolute-paths-from-relative-.patch +Patch0014: 0014-shim-Prevent-shim-to-set-itself-as-a-second-stage-lo.patch +Patch0015: 0015-Fix-for-Section-0-has-negative-size-error-when-loadi.patch +Patch0016: 0016-Fix-apparent-typo-in-ARM-32-on-64-code.patch +Patch0017: 0017-Makefile-do-not-run-git-on-clean-if-there-s-no-.git-.patch +Patch0018: 0018-Make.default-use-correct-flags-to-disable-unaligned-.patch +Patch0019: 0019-Cryptlib-fix-build-on-32bit-ARM.patch +Patch0020: 0020-Make-sure-that-MOK-variables-always-get-mirrored.patch +Patch0021: 0021-mok-fix-the-mirroring-of-RT-variables.patch +Patch0022: 0022-mok-consolidate-mirroring-code-in-a-helper-instead-o.patch +Patch0023: 0023-shim-only-include-shim_cert.h-in-shim.c.patch +Patch0024: 0024-mok-also-mirror-the-build-cert-to-MokListRT.patch +Patch0025: 0025-mok-minor-cleanups.patch +Patch0026: 0026-Remove-call-to-TPM2-get_event_log.patch +Patch0027: 0027-Make-EFI-variable-copying-fatal-only-on-secureboot-e.patch +Patch0028: 0028-VLogError-Avoid-NULL-pointer-dereferences-in-V-Sprin.patch +Patch0029: 0029-Once-again-try-even-harder-to-get-binaries-without-t.patch +Patch0030: 0030-shim-Rework-pause-functions-and-add-read_counter.patch +Patch0031: 0031-Hook-exit-when-shim_lock-protocol-installed.patch +Patch0032: 0032-Work-around-stuff-Waddress-of-packed-member-finds.patch +Patch0033: 0033-Fix-a-use-of-strlen-instead-of-Strlen.patch +Patch0034: 0034-MokManager-Use-CompareMem-on-MokListNode.Type-instea.patch +Patch0035: 0035-OpenSSL-always-provide-OBJ_create-with-name-strings.patch +Patch0036: 0036-Use-portable-shebangs-bin-bash-usr-bin-env-bash.patch +Patch0037: 0037-tpm-Fix-off-by-one-error-when-calculating-event-size.patch +Patch0038: 0038-tpm-Define-EFI_VARIABLE_DATA_TREE-as-packed.patch +Patch0039: 0039-MokManager-console-mode-modification-for-hi-dpi-scre.patch +Patch0040: 0040-MokManager-avoid-Werror-address-of-packed-member.patch +Patch0041: 0041-tpm-Don-t-log-duplicate-identical-events.patch +Patch0042: 0042-Slightly-better-debugging-messages.patch +Patch0043: 0043-Actually-check-for-errors-from-set_second_stage.patch +Patch0044: 0044-translate_slashes-don-t-write-to-string-literals.patch +Patch0045: 0045-shim-Update-EFI_LOADED_IMAGE-with-the-second-stage-l.patch +Patch0046: 0046-tpm-Include-information-about-PE-COFF-images-in-the-.patch +Patch0047: 0047-Fix-the-license-on-our-buildid-extractor.patch +Patch0048: 0048-Update-README.tpm.patch +Patch0049: 0049-Check-PxeReplyReceived-as-fallback-in-netboot.patch +Patch0050: 0050-Remove-a-couple-of-incorrect-license-claims.patch +Patch0051: 0051-MokManager-fix-uninitialized-value.patch +Patch0052: 0052-Fix-some-volatile-usage-gcc-whines-about.patch +Patch0053: 0053-MokManager-fix-a-wrong-allocation-failure-check.patch +Patch0054: 0054-simple_file-fix-uninitialized-variable-unchecked-ret.patch +Patch0055: 0055-Fix-a-broken-tpm-type.patch +Patch0056: 0056-Make-cert.S-not-impossible-to-read.patch +Patch0057: 0057-Add-support-for-vendor_db-built-in-shim-authorized-l.patch +Patch0058: 0058-Handle-binaries-with-multiple-signatures.patch +Patch0059: 0059-Make-openssl-accept-the-right-set-of-KU-EKUs.patch +Patch0060: 0060-Improve-debug-output-some.patch +Patch0061: 0061-Also-use-a-config-table-to-mirror-mok-variables.patch +Patch0062: 0062-Implement-lennysz-s-suggestions-for-MokListRT.patch BuildRequires: elfutils-libelf-devel BuildRequires: git openssl-devel openssl @@ -108,10 +166,10 @@ MAKEFLAGS="TOPDIR=.. -f ../Makefile COMMITID=${COMMITID} " MAKEFLAGS+="EFIDIR=%{efidir} PKGNAME=shim RELEASE=%{release} " MAKEFLAGS+="ENABLE_HTTPBOOT=true ENABLE_SHIM_HASH=true " MAKEFLAGS+="%{_smp_mflags}" -if [ -f "%{SOURCE1}" ]; then +if [ -s "%{SOURCE1}" ]; then MAKEFLAGS="$MAKEFLAGS VENDOR_CERT_FILE=%{SOURCE1}" fi -if [ -f "%{SOURCE2}" ]; then +if [ -s "%{SOURCE2}" ]; then MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE2}" fi @@ -128,10 +186,10 @@ COMMITID=$(cat commit) MAKEFLAGS="TOPDIR=.. -f ../Makefile COMMITID=${COMMITID} " MAKEFLAGS+="EFIDIR=%{efidir} PKGNAME=shim RELEASE=%{release} " MAKEFLAGS+="ENABLE_HTTPBOOT=true ENABLE_SHIM_HASH=true " -if [ -f "%{SOURCE1}" ]; then +if [ -s "%{SOURCE1}" ]; then MAKEFLAGS="$MAKEFLAGS VENDOR_CERT_FILE=%{SOURCE1}" fi -if [ -f "%{SOURCE2}" ]; then +if [ -s "%{SOURCE2}" ]; then MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE2}" fi @@ -172,6 +230,36 @@ cd .. %files debugsource -f build-%{efiarch}/debugsource.list %changelog +* Sat Jul 25 2020 Peter Jones - 15-7 +- Implement Lenny's workaround + Related: CVE-2020-10713 + Related: CVE-2020-14308 + Related: CVE-2020-14309 + Related: CVE-2020-14310 + Related: CVE-2020-14311 + +* Fri Jul 24 2020 Peter Jones - 15-5 +- Once more with the MokListRT config table patch added. + Related: CVE-2020-10713 + Related: CVE-2020-14308 + Related: CVE-2020-14309 + Related: CVE-2020-14310 + Related: CVE-2020-14311 + +* Thu Jul 23 2020 Peter Jones - 15-4 +- Rebuild for bug fixes and new signing keys + Related: CVE-2020-10713 + Related: CVE-2020-14308 + Related: CVE-2020-14309 + Related: CVE-2020-14310 + Related: CVE-2020-14311 + +* Wed Jun 05 2019 Javier Martinez Canillas - 15-3 +- Make EFI variable copying fatal only on secureboot enabled systems + Resolves: rhbz#1715878 +- Fix booting shim from an EFI shell using a relative path + Resolves: rhbz#1717064 + * Tue Feb 12 2019 Peter Jones - 15-2 - Fix MoK mirroring issue which breaks kdump without intervention Related: rhbz#1668966