- Use AlmaLinux cert

This commit is contained in:
eabdullin 2023-03-29 13:52:05 +03:00
parent a06095b4df
commit 57ac541491
72 changed files with 30 additions and 7501 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/shim-15.tar.bz2
SOURCES/shim-15.6.tar.bz2

View File

@ -1 +1 @@
2dc6308584187bf3ee88bf9b119938c72c5a5088 SOURCES/shim-15.tar.bz2
3df0ab5cefc74fdf865cb36aea0e923cb4b6b3ed SOURCES/shim-15.6.tar.bz2

View File

@ -1,29 +0,0 @@
From 1d50318f448b73b072724eb6664d311e6084a446 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,131 +0,0 @@
From 32f71225382ddb7dd1ad51f584bc3d42a7ee39d1 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,61 +0,0 @@
From 74718677945b1ab825130b317c63f5002876e772 Mon Sep 17 00:00:00 2001
From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
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 <mathieu.trudel-lapierre@canonical.com>
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

View File

@ -1,30 +0,0 @@
From 8a66f5571bb059d2692e804f4ba9817e978dd103 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,107 +0,0 @@
From 0ba6c87bdf55f749a0ec1c3b0fd24ebb8200d537 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,68 +0,0 @@
From 80e52895f206fcb40a60f031e7b721627bb193ca Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,30 +0,0 @@
From c2f645c7cd9872585e7b4522b01c368bb545258b Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,54 +0,0 @@
From 409b59af29b8749207a527c91dccba7eee98232b Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,43 +0,0 @@
From 85c837d67fef9cd831a3126398ed8da1421f61c5 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,40 +0,0 @@
From 956717e2b375d7c7f0faafec8f12a7692708eb9a Mon Sep 17 00:00:00 2001
From: Paul Menzel <pmenzel@molgen.mpg.de>
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 <pmenzel@molgen.mpg.de>
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

View File

@ -1,34 +0,0 @@
From bd97e72f0490b2be766949f448bf6ea3ec2bba1a Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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

View File

@ -1,36 +0,0 @@
From c4e3516e303daa42b3381ddd889a90641717f720 Mon Sep 17 00:00:00 2001
From: TanMing <tanminger@TanMing-WorkPC.sh.intel.com>
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 <ming.tan@intel.com>
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

View File

@ -1,52 +0,0 @@
From 79be2af5260b1f2e2a4680e74e14da0fdb42b570 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
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 <javierm@redhat.com>
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

View File

@ -1,77 +0,0 @@
From 818a0dbd247f7c83d844febfa0a037b396d22701 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
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 <javierm@redhat.com>
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

View File

@ -1,121 +0,0 @@
From 3d04aef8d80293d701f7efee6b5300f9f528ddfc Mon Sep 17 00:00:00 2001
From: Maran Wilson <maran.wilson@oracle.com>
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 <maran.wilson@oracle.com>
Reviewed-by: Aaron Young <aaron.young@oracle.com>
Reviewed-by: Jack Schwartz <jack.schwartz@oracle.com>
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

View File

@ -1,30 +0,0 @@
From d5b72b322d5b7c6c115833c518e1aa5798076309 Mon Sep 17 00:00:00 2001
From: dann frazier <dann.frazier@canonical.com>
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 <dann.frazier@canonical.com>
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

View File

@ -1,32 +0,0 @@
From 8544018093b8aa4311b1e970f8396140c22ede0b Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
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 <bluca@debian.org>
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

View File

@ -1,40 +0,0 @@
From 7f080b30f3c3718d6b2533f62a50f373fd2cda21 Mon Sep 17 00:00:00 2001
From: Peter Korsgaard <peter@korsgaard.com>
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 <peter@korsgaard.com>
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

View File

@ -1,34 +0,0 @@
From ee832f21c6706d6b3890d82f9d8bcb2bd249ee04 Mon Sep 17 00:00:00 2001
From: Peter Korsgaard <peter@korsgaard.com>
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 <peter@korsgaard.com>
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

View File

@ -1,61 +0,0 @@
From ac0400b20264ef67b67891d2216edd3fe20e5571 Mon Sep 17 00:00:00 2001
From: Patrick Uiterwijk <patrick@puiterwijk.org>
Date: Mon, 5 Nov 2018 14:51:16 +0100
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).
This patch makes sure that if we have extra data to append, we still mirror
the variable.
Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
Upstream-commit-id: 9ab0d796bdc
---
mok.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/mok.c b/mok.c
index 38675211e0e..00dd1ad3034 100644
--- a/mok.c
+++ b/mok.c
@@ -223,11 +223,26 @@ 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;
+
efi_status = get_variable_attr(v->name,
&v->data, &v->data_size,
*v->guid, &attrs);
- if (efi_status == EFI_NOT_FOUND)
+ if (efi_status == EFI_NOT_FOUND) {
+ if (v->rtname && addend) {
+ efi_status = mirror_one_mok_variable(v);
+ if (EFI_ERROR(efi_status) &&
+ ret != EFI_SECURITY_VIOLATION)
+ ret = efi_status;
+ }
+ /*
+ * after possibly adding, we can continue, no
+ * further checks to be done.
+ */
continue;
+ }
if (EFI_ERROR(efi_status)) {
perror(L"Could not verify %s: %r\n", v->name,
efi_status);
@@ -272,9 +287,6 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
}
present = (v->data && v->data_size) ? TRUE : FALSE;
- addend = (v->addend_source && v->addend_size &&
- *v->addend_source && *v->addend_size)
- ? TRUE : FALSE;
if (v->flags & MOK_VARIABLE_MEASURE && present) {
/*
--
2.26.2

View File

@ -1,50 +0,0 @@
From f748139695384fb4e09833898f0b8cb3ab85d810 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Wed, 21 Nov 2018 12:47:43 +0800
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
check of 'present' and 'addend' invalidates the mirroring of MokListXRT,
MokSBStateRT, and MokIgnoreDB.
https://github.com/rhboot/shim/issues/154
Signed-off-by: Gary Lin <glin@suse.com>
Upstream-commit-id: 4b27ae034ba
---
mok.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/mok.c b/mok.c
index 00dd1ad3034..41925abbb49 100644
--- a/mok.c
+++ b/mok.c
@@ -231,12 +231,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
&v->data, &v->data_size,
*v->guid, &attrs);
if (efi_status == EFI_NOT_FOUND) {
- if (v->rtname && addend) {
- efi_status = mirror_one_mok_variable(v);
- if (EFI_ERROR(efi_status) &&
- ret != EFI_SECURITY_VIOLATION)
- ret = efi_status;
- }
+ if (addend)
+ goto mirror_addend;
/*
* after possibly adding, we can continue, no
* further checks to be done.
@@ -316,7 +312,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
}
}
- if (v->rtname && present && addend) {
+mirror_addend:
+ if (v->rtname && (present || addend)) {
if (v->flags & MOK_MIRROR_DELETE_FIRST)
LibDeleteVariable(v->rtname, v->guid);
--
2.26.2

View File

@ -1,110 +0,0 @@
From ff6e5cda136c8fd637d3d6b8334f4f221ba2b1ee Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 31 Jan 2019 13:45:30 -0500
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 <pjones@redhat.com>
Upstream-commit-id: 29c11483101
---
mok.c | 42 +++++++++++++++++++++++++++++-------------
shim.h | 2 ++
2 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/mok.c b/mok.c
index 41925abbb49..2b9d796a0e8 100644
--- a/mok.c
+++ b/mok.c
@@ -130,7 +130,8 @@ struct mok_state_variable mok_state_variables[] = {
{ NULL, }
};
-static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
+static EFI_STATUS nonnull(1)
+mirror_one_mok_variable(struct mok_state_variable *v)
{
EFI_STATUS efi_status = EFI_SUCCESS;
void *FullData = NULL;
@@ -196,6 +197,29 @@ static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
return efi_status;
}
+/*
+ * Mirror a variable if it has an rtname, and preserve any
+ * 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)
+{
+ EFI_STATUS efi_status;
+ if (v->rtname) {
+ if (v->flags & MOK_MIRROR_DELETE_FIRST)
+ LibDeleteVariable(v->rtname, v->guid);
+
+ efi_status = mirror_one_mok_variable(v);
+ if (EFI_ERROR(efi_status)) {
+ if (ret != EFI_SECURITY_VIOLATION)
+ ret = efi_status;
+ perror(L"Could not create %s: %r\n", v->rtname,
+ efi_status);
+ }
+ }
+ return ret;
+}
+
/*
* Verify our non-volatile MoK state. This checks the variables above
* accessable and have valid attributes. If they don't, it removes
@@ -232,7 +256,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
*v->guid, &attrs);
if (efi_status == EFI_NOT_FOUND) {
if (addend)
- goto mirror_addend;
+ ret = maybe_mirror_one_mok_variable(v, ret);
/*
* after possibly adding, we can continue, no
* further checks to be done.
@@ -312,16 +336,8 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
}
}
-mirror_addend:
- if (v->rtname && (present || addend)) {
- if (v->flags & MOK_MIRROR_DELETE_FIRST)
- LibDeleteVariable(v->rtname, v->guid);
-
- efi_status = mirror_one_mok_variable(v);
- if (EFI_ERROR(efi_status) &&
- ret != EFI_SECURITY_VIOLATION)
- ret = efi_status;
- }
+ if (present)
+ ret = maybe_mirror_one_mok_variable(v, ret);
}
/*
@@ -340,4 +356,4 @@ mirror_addend:
return ret;
}
-// vim:fenc=utf-8:tw=75
+// vim:fenc=utf-8:tw=75:noet
diff --git a/shim.h b/shim.h
index 2b359d821e3..c26d5f06538 100644
--- a/shim.h
+++ b/shim.h
@@ -30,6 +30,8 @@
#include <stddef.h>
+#define nonnull(...) __attribute__((__nonnull__(__VA_ARGS__)))
+
#define min(a, b) ({(a) < (b) ? (a) : (b);})
#ifdef __x86_64__
--
2.26.2

View File

@ -1,82 +0,0 @@
From 7a3638173e406ce7cbd682213606e3152244fcb2 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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 <openssl/err.h>
#include <openssl/bn.h>
@@ -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

View File

@ -1,153 +0,0 @@
From 3d62232feb296b238ca5d7963ba40a2c346767e7 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,37 +0,0 @@
From ff890cf45224926574eee93b0ea1494468870bd3 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 31 Jan 2019 14:04:57 -0500
Subject: [PATCH 25/62] mok: minor cleanups
Signed-off-by: Peter Jones <pjones@redhat.com>
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

View File

@ -1,91 +0,0 @@
From cf3f99c3b1e11c8c83938784975331db5efb410f Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@google.com>
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 <mjg59@google.com>
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

View File

@ -1,48 +0,0 @@
From 95bd1d88003a9a7c2732472b061ad2a9c7140419 Mon Sep 17 00:00:00 2001
From: Patrick Uiterwijk <patrick@puiterwijk.org>
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 <patrick@puiterwijk.org>
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

View File

@ -1,66 +0,0 @@
From 344a8364cb05cdaafc43231d0f73d5217c4e118c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 12 Feb 2019 18:04:49 -0500
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 <pjones@redhat.com>
Fixes: 25f6fd08cd26 ("try to show errors more usefully.")
[dannf: commit message ]
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Upstream-commit-id: 20e731f423a
---
errlog.c | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/errlog.c b/errlog.c
index 18be4822d53..eebb266d396 100644
--- a/errlog.c
+++ b/errlog.c
@@ -14,29 +14,20 @@ EFI_STATUS
VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args)
{
va_list args2;
- UINTN size = 0, size2;
CHAR16 **newerrs;
- size = SPrint(NULL, 0, L"%a:%d %a() ", file, line, func);
- va_copy(args2, args);
- size2 = VSPrint(NULL, 0, fmt, args2);
- va_end(args2);
-
newerrs = ReallocatePool(errs, (nerrs + 1) * sizeof(*errs),
(nerrs + 3) * sizeof(*errs));
if (!newerrs)
return EFI_OUT_OF_RESOURCES;
- newerrs[nerrs] = AllocatePool(size*2+2);
+ newerrs[nerrs] = PoolPrint(L"%a:%d %a() ", file, line, func);
if (!newerrs[nerrs])
return EFI_OUT_OF_RESOURCES;
- newerrs[nerrs+1] = AllocatePool(size2*2+2);
+ va_copy(args2, args);
+ newerrs[nerrs+1] = VPoolPrint(fmt, args2);
if (!newerrs[nerrs+1])
return EFI_OUT_OF_RESOURCES;
-
- SPrint(newerrs[nerrs], size*2+2, L"%a:%d %a() ", file, line, func);
- va_copy(args2, args);
- VSPrint(newerrs[nerrs+1], size2*2+2, fmt, args2);
va_end(args2);
nerrs += 2;
--
2.26.2

View File

@ -1,98 +0,0 @@
From 10d6e3d90f1ea504a1dedaea50478c444e92951c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 youre
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 <pjones@redhat.com>
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

View File

@ -1,280 +0,0 @@
From 1b382ef850de5a6c59b192c146a0e8d898d2d961 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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 <pjones@redhat.com>
+ */
+
+#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 <pjones@redhat.com>
+ */
+
+#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

View File

@ -1,49 +0,0 @@
From b5e10f70c7a495dc1788e3604803ee633f1e5f76 Mon Sep 17 00:00:00 2001
From: Stuart Hayes <stuart.w.hayes@gmail.com>
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 <stuart.w.hayes@gmail.com>
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

View File

@ -1,89 +0,0 @@
From 2cbf56b82a5102777b37c4f7f47c8cf058cea027 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <anonymous> 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 <pjones@redhat.com>
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

View File

@ -1,27 +0,0 @@
From c372ec7a254147f70d62c1f72da5806d42df6994 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,72 +0,0 @@
From 5d30a31fef4eb7e773da24c5e6c20576282a9c3a Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
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 <glin@suse.com>
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

View File

@ -1,32 +0,0 @@
From 44b211bcf7ad58ff29e6495e1c3978e4660cb7d1 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,42 +0,0 @@
From 07de085dabab8daaea589b597e3915893cc98445 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Forsman?= <bjorn.forsman@gmail.com>
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

View File

@ -1,44 +0,0 @@
From 6fd8db6bb3b23b9e41f109135253f77263071f46 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
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

View File

@ -1,36 +0,0 @@
From 9f80be9f16a854e3946568fa92edebe26eb79e78 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
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

View File

@ -1,223 +0,0 @@
From 55163bc82c5179adb109c3d8b982c2689d68b4c9 Mon Sep 17 00:00:00 2001
From: Ivan Hu <ivan.hu@canonical.com>
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 <ivan.hu@canonical.com>
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

View File

@ -1,111 +0,0 @@
From d57e53f3bddc4bc7299b3d5efd5ba8c547e8dfa5 Mon Sep 17 00:00:00 2001
From: Jonas Witschel <diabonas@gmx.de>
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 <anonymous> 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

View File

@ -1,31 +0,0 @@
From 58df8d745c6516818ba6ebfa8fe826702c1621a0 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
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<measuredcount; i++) {
if ((StrCmp (VarName, measureddata[i].VariableName) == 0) &&
- (CompareGuid (&VendorGuid, measureddata[i].VendorGuid)) &&
+ (CompareGuid (&VendorGuid, measureddata[i].VendorGuid) == 0) &&
(VarSize == measureddata[i].Size) &&
(CompareMem (VarData, measureddata[i].Data, VarSize) == 0)) {
return TRUE;
--
2.26.2

View File

@ -1,57 +0,0 @@
From 5e6e0792cedb3b71cbe061ae56e96906cf710579 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 18 Nov 2019 13:59:14 -0500
Subject: [PATCH 42/62] Slightly better debugging messages
Signed-off-by: Peter Jones <pjones@redhat.com>
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

View File

@ -1,69 +0,0 @@
From 959f5e4e993a82020fef48c7e7c012a44074645c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,140 +0,0 @@
From c6bedd5b83529925c3ec08f96a3bf61c81bff0ae Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
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 <lersek@redhat.com>
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

View File

@ -1,93 +0,0 @@
From 89d72301aa67c82f00fe7fa4f42d7f6eb6045538 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
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 <javierm@redhat.com>
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

View File

@ -1,124 +0,0 @@
From 0a8f7ade76ff3eede486027eaa638181e6bed3b8 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
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 <javierm@redhat.com>
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

View File

@ -1,27 +0,0 @@
From dce3659ac3d14ed338cdb37798a429751898c078 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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 <err.h>
--
2.26.2

View File

@ -1,27 +0,0 @@
From 633169fe3291c832236ca1074fc679852f9caee1 Mon Sep 17 00:00:00 2001
From: noahbliss <noah@superuser.sh>
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

View File

@ -1,61 +0,0 @@
From 9a209af5d84f4015ec399e1d1fa9dab31ef4d2b7 Mon Sep 17 00:00:00 2001
From: Thomas Frauendorfer | Miray Software <tf@miray.de>
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

View File

@ -1,46 +0,0 @@
From e8a04c1d84d2ebd0dbdf7bda26d7a22017100586 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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 <pjones@redhat.com>
- *
- * 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 <pjones@redhat.com>
- *
- * Distributed under terms of the GPLv3 license.
*/
#include "shim.h"
--
2.26.2

View File

@ -1,27 +0,0 @@
From 7b77bee7966a1aa5f00a9b34aeb7e550bfa47be1 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 22 Jul 2020 23:53:09 -0400
Subject: [PATCH 51/62] MokManager: fix uninitialized value
Signed-off-by: Peter Jones <pjones@redhat.com>
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

View File

@ -1,41 +0,0 @@
From d3b7dc54cdac474a57b67cf9bcdb15bcb131d06c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,31 +0,0 @@
From 6df96cdb20b84b33027d2e40bc0dbe0676d31282 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,33 +0,0 @@
From c186bdddaa7b103aef9d4a164ac0a07499dba112 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,27 +0,0 @@
From a7f9911b776f3cdc12e42bf5990ddef0b08d3701 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 23 Jul 2020 20:35:56 -0400
Subject: [PATCH 55/62] Fix a broken tpm type
Signed-off-by: Peter Jones <pjones@redhat.com>
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

View File

@ -1,279 +0,0 @@
From 7d542805ba5c48185128a2351bb315a5648fe3d7 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,943 +0,0 @@
From dd3a5d71252a1f94e37f1a4c8841d253630b305a Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <stdint.h>
+
/*
* 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

View File

@ -1,366 +0,0 @@
From 76c0447e204c7e4ce918c4887ce8aae0e0816271 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,119 +0,0 @@
From 705d47ac2c90b8de07a4ef3e1930de6c4b8fece0 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
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

View File

@ -1,451 +0,0 @@
From fc4368fed53837e00d303600d8b628cb0392b629 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 23 Jul 2020 20:29:52 -0400
Subject: [PATCH 60/62] Improve debug output some
Signed-off-by: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
*/
#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 <stdint.h>
-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

View File

@ -1,352 +0,0 @@
From fecc2dfb8e408526221091923d9345796b8e294e Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
Upstream: not yet, I don't want people to read this before Wednesday.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
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

View File

@ -1,991 +0,0 @@
From 65be350308783a8ef537246c8ad0545b4e6ad069 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Sat, 25 Jul 2020 22:13:57 -0400
Subject: [PATCH 62/62] Implement lennysz's suggestions for MokListRT
Signed-off-by: Peter Jones <pjones@redhat.com>
---
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 <stdint.h>
+#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

View File

@ -1,77 +0,0 @@
From 9313a515432ba938e66f2edc1e22d548fed1eb5c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 30 Jul 2020 14:34:22 -0400
Subject: [PATCH] hexdump.h: fix arithmetic error.
When I modified the hexdumper to help debug MokListRT mirroring not
working because of PcdMaxVolatileVariableSize being tiny, I
inadvertently added something that is effectively:
hexdump(..., char *buf, ..., int position)
{
unsigned long begin = (position % 16);
unsigned long i;
...
for (i = 0; i < begin; i++) {
...
}
...
}
Unfortunately, in c if 0x8 is set in position, that means begin is
0xfffffffffffff8, because signed integer math is horrifying:
include/hexdump.h:99:vhexdumpf() &data[offset]:0x9E77E6BC size-offset:0x14
include/hexdump.h:15:prepare_hex() position:0x9E77E6BC
include/hexdump.h:17:prepare_hex() before:0xFFFFFFFFFFFFFFFC size:0x14
include/hexdump.h:19:prepare_hex() before:0xFFFFFFFFFFFFFFFC after:0x0
include/hexdump.h:21:prepare_hex() buf:0x000000009E77E2BC offset:0 &buf[offset]:0x000000009E77E2BC
Woops.
This could further have been prevented in /some/ cases by simply not
preparing the hexdump buffer when "verbose" is disabled.
This patch makes "pos" be unsigned in all cases, and also checks for
verbose in vhexdumpf() and simply returns if it is 0.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
include/hexdump.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/hexdump.h b/include/hexdump.h
index f3f3ac284a3..b2968cd4f85 100644
--- a/include/hexdump.h
+++ b/include/hexdump.h
@@ -4,7 +4,7 @@
#include <stdint.h>
static inline unsigned long UNUSED
-prepare_hex(const void *data, size_t size, char *buf, int position)
+prepare_hex(const void *data, size_t size, char *buf, unsigned int position)
{
char hexchars[] = "0123456789abcdef";
int offset = 0;
@@ -48,7 +48,7 @@ prepare_hex(const void *data, size_t size, char *buf, int position)
#define isprint(c) ((c) >= 0x20 && (c) <= 0x7e)
static inline void UNUSED
-prepare_text(const void *data, size_t size, char *buf, int position)
+prepare_text(const void *data, size_t size, char *buf, unsigned int position)
{
int offset = 0;
unsigned long i;
@@ -84,6 +84,9 @@ vhexdumpf(const char *file, int line, const char *func, const CHAR16 * const fmt
unsigned long display_offset = at;
unsigned long offset = 0;
+ if (verbose == 0)
+ return;
+
while (offset < size) {
char hexbuf[49];
char txtbuf[19];
--
2.26.2

View File

@ -1,122 +0,0 @@
From 18843127dc0eace16d43d479bd091e221e8785c4 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 17 Aug 2020 15:47:19 -0400
Subject: [PATCH] Fix some mokmanager deletion paths
This fixes several codepaths where MokList and MokListX are supposed to
be deleted, but are not. It also adds debug logging to much of the
deletion codepath.
---
MokManager.c | 24 +++++++++++++++++++++++-
Makefile | 2 +-
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index c9949e33bcf..9bae3414fe7 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -9,6 +9,8 @@
#include "shim.h"
+#include "hexdump.h"
+
#define PASSWORD_MAX 256
#define PASSWORD_MIN 1
#define SB_PASSWORD_LEN 16
@@ -1050,9 +1052,11 @@ static EFI_STATUS mok_reset_prompt(BOOLEAN MokX)
if (MokX) {
LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID);
LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID);
+ LibDeleteVariable(L"MokListX", &SHIM_LOCK_GUID);
} else {
LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID);
LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID);
+ LibDeleteVariable(L"MokList", &SHIM_LOCK_GUID);
}
return EFI_SUCCESS;
@@ -1075,6 +1079,7 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
else
db_name = L"MokList";
+ dprint(L"Writing back %s (%d entries)\n", db_name, key_num);
for (i = 0; i < key_num; i++) {
if (list[i].Mok == NULL)
continue;
@@ -1085,8 +1090,15 @@ static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
DataSize += sizeof(EFI_GUID);
DataSize += list[i].MokSize;
}
- if (DataSize == 0)
+ if (DataSize == 0) {
+ dprint(L"DataSize = 0; deleting variable %s\n", db_name);
+ efi_status = gRT->SetVariable(db_name, &SHIM_LOCK_GUID,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ DataSize, Data);
+ dprint(L"efi_status:%llu\n", efi_status);
return EFI_SUCCESS;
+ }
Data = AllocatePool(DataSize);
if (Data == NULL)
@@ -1291,11 +1303,15 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
}
if (auth_size == PASSWORD_CRYPT_SIZE) {
+ dprint(L"matching password with CRYPT");
efi_status = match_password((PASSWORD_CRYPT *) auth, NULL, 0,
NULL, NULL);
+ dprint(L"match_password(0x%llx, NULL, 0, NULL, NULL) = %lu\n", auth, efi_status);
} else {
+ dprint(L"matching password as sha256sum");
efi_status =
match_password(NULL, MokDel, MokDelSize, auth, NULL);
+ dprint(L"match_password(NULL, 0x%llx, %llu, 0x%llx, NULL) = %lu\n", MokDel, MokDelSize, auth, efi_status);
}
if (EFI_ERROR(efi_status))
return EFI_ACCESS_DENIED;
@@ -1365,12 +1381,17 @@ static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
}
/* Search and destroy */
+ dprint(L"deleting certs from %a\n", MokX ? "MokListX" : "MokList");
for (i = 0; i < del_num; i++) {
type = del_key[i].Type; /* avoid -Werror=address-of-packed-member */
if (CompareGuid(&type, &X509_GUID) == 0) {
+ dprint(L"deleting key %d (total %d):\n", i, mok_num);
+ dhexdumpat(del_key[i].Mok, del_key[i].MokSize, 0);
delete_cert(del_key[i].Mok, del_key[i].MokSize,
mok, mok_num);
} else if (is_sha2_hash(del_key[i].Type)) {
+ dprint(L"deleting hash %d (total %d):\n", i, mok_num);
+ dhexdumpat(del_key[i].Mok, del_key[i].MokSize, 0);
delete_hash_list(del_key[i].Type, del_key[i].Mok,
del_key[i].MokSize, mok, mok_num);
}
@@ -2564,6 +2585,7 @@ EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * systab)
InitializeLib(image_handle, systab);
+ setup_verbosity();
setup_rand();
console_mode_handle();
diff --git a/Makefile b/Makefile
index 49e14a26521..a17fa2bef14 100644
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,7 @@ endif
OBJS = shim.o mok.o netboot.o cert.o replacements.o tpm.o version.o errlog.o
KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer
ORIG_SOURCES = shim.c mok.c netboot.c replacements.c tpm.c errlog.c shim.h version.h $(wildcard include/*.h)
-MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o
+MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o errlog.o
ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h)
FALLBACK_OBJS = fallback.o tpm.o errlog.o
ORIG_FALLBACK_SRCS = fallback.c
--
2.26.2

View File

@ -1,37 +0,0 @@
From ac610fe45491deccaab2c4ee689cbbdac117930a Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Tue, 8 Sep 2020 12:26:45 +0200
Subject: [PATCH] Fix buffer overrun due DEFAULT_LOADER length miscalculation
The DEFAULT_LOADER is a UCS-2 string and the StrLen() function returns the
number of UCS-2 encoded characters in the string. But the allocated memory
is in bytes, so only half of the needed memory to store it is allocated.
This leads to a buffer overrun when the StrCpy() function attempts to copy
the DEFAULT_LOADER to the allocated buffer.
Fixes: 354bd9b1931 ("Actually check for errors from set_second_stage()")
Reported-by: Stuart Hayes <stuart_hayes@dell.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
shim.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/shim.c b/shim.c
index 34dce25c330..82913c934f6 100644
--- a/shim.c
+++ b/shim.c
@@ -2096,8 +2096,9 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
unsigned int i;
UINTN second_stage_len;
- second_stage_len = StrLen(DEFAULT_LOADER) + 1;
+ second_stage_len = (StrLen(DEFAULT_LOADER) + 1) * sizeof(CHAR16);
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;
--
2.28.0

Binary file not shown.

View File

@ -0,0 +1 @@
shim.almalinux,2,AlmaLinux,shim,15.6,security@almalinux.org
1 shim.almalinux 2 AlmaLinux shim 15.6 security@almalinux.org

0
SOURCES/shim.patches Normal file
View File

BIN
SOURCES/vendor_db.esl Normal file

Binary file not shown.

View File

@ -17,91 +17,29 @@
%global shimaltdir %{shimversiondir}/%{efialtarch}
Name: shim-unsigned-%{efiarch}
Version: 15
Release: 9.el8.alma
Version: 15.6
Release: 1.el8.alma.1
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: clsecureboot001.cer
Source1: vendor_db.esl
# currently here's what's in our dbx:
# nothing.
Source2: dbx.esl
Source3: sbat.almalinux.csv
Source4: shim.patches
Source100: shim-find-debuginfo.sh
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
Patch0063: 0063-hexdump.h-fix-arithmetic-error.patch
Patch0064: 0064-Fix-some-mokmanager-deletion-paths.patch
Patch0065: 0065-Fix-buffer-overrun-due-DEFAULT_LOADER-length-miscalc.patch
%include %{SOURCE4}
BuildRequires: gcc make
BuildRequires: elfutils-libelf-devel
BuildRequires: git openssl-devel openssl
BuildRequires: pesign >= %{pesign_vre}
BuildRequires: gnu-efi >= %{gnuefi_vre}
BuildRequires: gnu-efi-devel >= %{gnuefi_vre}
BuildRequires: dos2unix findutils
# Shim uses OpenSSL, but cannot use the system copy as the UEFI ABI is not
# compatible with SysV (there's no red zone under UEFI) and there isn't a
@ -157,31 +95,36 @@ BuildArch: noarch
%debug_desc
%prep
%autosetup -S git -n shim-%{version}
%autosetup -S git_am -n shim-%{version}
git config --unset user.email
git config --unset user.name
mkdir build-%{efiarch}
mkdir build-%{efialtarch}
cp %{SOURCE3} data/
%build
COMMITID=$(cat commit)
MAKEFLAGS="TOPDIR=.. -f ../Makefile COMMITID=${COMMITID} "
MAKEFLAGS+="EFIDIR=%{efidir} PKGNAME=shim RELEASE=%{release} "
MAKEFLAGS+="ENABLE_HTTPBOOT=true ENABLE_SHIM_HASH=true "
MAKEFLAGS+="ENABLE_SHIM_HASH=true "
MAKEFLAGS+="%{_smp_mflags}"
if [ -s "%{SOURCE1}" ]; then
MAKEFLAGS="$MAKEFLAGS VENDOR_CERT_FILE=%{SOURCE1}"
MAKEFLAGS="$MAKEFLAGS VENDOR_DB_FILE=%{SOURCE1}"
fi
if [ -s "%{SOURCE2}" ]; then
MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE2}"
fi
cd build-%{efiarch}
make ${MAKEFLAGS} DEFAULT_LOADER='\\\\grub%{efiarch}.efi' all
make ${MAKEFLAGS} \
DEFAULT_LOADER='\\\\grub%{efiarch}.efi' \
all
cd ..
cd build-%{efialtarch}
setarch linux32 -B make ${MAKEFLAGS} ARCH=%{efialtarch} DEFAULT_LOADER='\\\\grub%{efialtarch}.efi' all
setarch linux32 -B make ${MAKEFLAGS} ARCH=%{efialtarch} \
DEFAULT_LOADER='\\\\grub%{efialtarch}.efi' \
all
cd ..
%install
@ -190,7 +133,7 @@ MAKEFLAGS="TOPDIR=.. -f ../Makefile COMMITID=${COMMITID} "
MAKEFLAGS+="EFIDIR=%{efidir} PKGNAME=shim RELEASE=%{release} "
MAKEFLAGS+="ENABLE_HTTPBOOT=true ENABLE_SHIM_HASH=true "
if [ -s "%{SOURCE1}" ]; then
MAKEFLAGS="$MAKEFLAGS VENDOR_CERT_FILE=%{SOURCE1}"
MAKEFLAGS="$MAKEFLAGS VENDOR_DB_FILE=%{SOURCE1}"
fi
if [ -s "%{SOURCE2}" ]; then
MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE2}"
@ -215,6 +158,7 @@ cd ..
%dir %{shimrootdir}
%dir %{shimversiondir}
%dir %{shimdir}
%{shimdir}/*.CSV
%{shimdir}/*.efi
%{shimdir}/*.hash
@ -223,6 +167,7 @@ cd ..
%dir %{shimrootdir}
%dir %{shimversiondir}
%dir %{shimaltdir}
%{shimaltdir}/*.CSV
%{shimaltdir}/*.efi
%{shimaltdir}/*.hash
@ -233,8 +178,12 @@ cd ..
%files debugsource -f build-%{efiarch}/debugsource.list
%changelog
* Fri Mar 18 2022 Eduard Abdullin <eabdullin@almalinux.org> - 15.4-4.alma
- Use CloudLinux vendor cert
* Mon Jun 20 2022 Andrew Lukoshko <alukoshko@almalinux.org> - 15.6-1.el8.alma.1
- Use AlmaLinux cert and SBAT entry
* Wed Jun 01 2022 Peter Jones <pjones@redhat.com> - 15.6-1.el8
- Update to shim-15.6
Resolves: CVE-2022-28737
* Thu Sep 17 2020 Peter Jones <pjones@redhat.com> - 15-9.el8
- Fix an incorrect allocation size.