From ab26d9a5c035cd56e1b1ae8b0ef74e059fe61d77 Mon Sep 17 00:00:00 2001
From: Patrick Uiterwijk <patrick@puiterwijk.org>
Date: Sat, 21 Jul 2018 04:12:57 +0200
Subject: [PATCH] Implement vendor EFI Signature List (ESL)
Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
---
Make.defaults | 3 ++
cert.S | 30 ++++++++++++++++++
mok.c | 86 +++++++++++++++++++++++++++------------------------
shim.c | 25 +++++++++++++++
shim.h | 2 ++
5 files changed, 106 insertions(+), 40 deletions(-)
diff --git a/Make.defaults b/Make.defaults
index 4c26c1a..0f9b979 100644
--- a/Make.defaults
+++ b/Make.defaults
@@ -126,6 +126,9 @@ CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/sha
ifneq ($(origin VENDOR_CERT_FILE), undefined)
CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\"
endif
+ifneq ($(origin VENDOR_ESL_FILE), undefined)
+ CFLAGS += -DVENDOR_ESL_FILE=\"$(VENDOR_ESL_FILE)\"
+endif
ifneq ($(origin VENDOR_DBX_FILE), undefined)
CFLAGS += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\"
endif
diff --git a/cert.S b/cert.S
index cfc4525..7ad782a 100644
--- a/cert.S
+++ b/cert.S
@@ -8,12 +8,18 @@ cert_table:
#else
.long 0
#endif
+#if defined(VENDOR_ESL_FILE)
+ .long vendor_esl_priv_end - vendor_esl_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_esl_priv - cert_table
.long vendor_dbx_priv - cert_table
#if defined(VENDOR_CERT_FILE)
.data
@@ -39,6 +45,30 @@ vendor_cert_priv:
.section .vendor_cert, "a", %progbits
vendor_cert_priv_end:
#endif
+#if defined(VENDOR_ESL_FILE)
+ .data
+ .align 1
+ .type vendor_esl_priv, %object
+ .size vendor_esl_priv, vendor_esl_priv_end-vendor_esl_priv
+ .section .vendor_cert, "a", %progbits
+vendor_esl_priv:
+.incbin VENDOR_ESL_FILE
+vendor_esl_priv_end:
+#else
+ .bss
+ .type vendor_esl_priv, %object
+ .size vendor_esl_priv, 1
+ .section .vendor_cert, "a", %progbits
+vendor_esl_priv:
+ .zero 1
+
+ .data
+ .align 4
+ .type vendor_esl_size_priv, %object
+ .size vendor_esl_size_priv, 4
+ .section .vendor_cert, "a", %progbits
+vendor_esl_priv_end:
+#endif
#if defined(VENDOR_DBX_FILE)
.data
.align 1
diff --git a/mok.c b/mok.c
index 2b9d796..f52e286 100644
--- a/mok.c
+++ b/mok.c
@@ -62,12 +62,6 @@ struct mok_state_variable {
EFI_GUID *guid;
UINT8 *data;
UINTN data_size;
- /*
- * These two are indirect pointers just to make initialization
- * saner...
- */
- UINT8 **addend_source;
- UINT32 *addend_size;
UINT32 yes_attr;
UINT32 no_attr;
UINT32 flags;
@@ -75,10 +69,11 @@ struct mok_state_variable {
UINT8 *state;
};
-#define MOK_MIRROR_KEYDB 0x01
-#define MOK_MIRROR_DELETE_FIRST 0x02
-#define MOK_VARIABLE_MEASURE 0x04
-#define MOK_VARIABLE_LOG 0x08
+#define MOK_MIRROR_KEYDB 0x01
+#define MOK_MIRROR_DELETE_FIRST 0x02
+#define MOK_VARIABLE_MEASURE 0x04
+#define MOK_VARIABLE_LOG 0x08
+#define MOK_VARIABLE_APPEND_CERT 0x10
struct mok_state_variable mok_state_variables[] = {
{.name = L"MokList",
@@ -88,10 +83,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,
.flags = MOK_MIRROR_KEYDB |
- MOK_VARIABLE_LOG,
+ MOK_VARIABLE_LOG |
+ MOK_VARIABLE_APPEND_CERT,
.pcr = 14,
},
{.name = L"MokListX",
@@ -139,40 +133,54 @@ mirror_one_mok_variable(struct mok_state_variable *v)
uint8_t *p = NULL;
if ((v->flags & MOK_MIRROR_KEYDB) &&
- v->addend_source && *v->addend_source &&
- v->addend_size && *v->addend_size) {
- EFI_SIGNATURE_LIST *CertList = NULL;
- EFI_SIGNATURE_DATA *CertData = NULL;
- FullDataSize = v->data_size
- + sizeof (*CertList)
- + sizeof (EFI_GUID)
- + *v->addend_size;
+ (v->flags & MOK_VARIABLE_APPEND_CERT)) {
+ FullDataSize = v->data_size;
+
+ if (vendor_esl_size) {
+ FullDataSize += vendor_esl_size;
+ }
+ if (vendor_cert_size) {
+ FullDataSize += sizeof (EFI_SIGNATURE_LIST)
+ + sizeof (EFI_GUID)
+ + vendor_cert_size;
+ }
+
FullData = AllocatePool(FullDataSize);
if (!FullData) {
perror(L"Failed to allocate space for MokListRT\n");
return EFI_OUT_OF_RESOURCES;
}
p = FullData;
-
if (!EFI_ERROR(efi_status) && v->data_size > 0) {
CopyMem(p, v->data, v->data_size);
p += v->data_size;
}
- 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->addend_size
- + sizeof (*CertList)
- + sizeof (*CertData)
- -1;
- CertList->SignatureHeaderSize = 0;
- CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID);
-
- CertData->SignatureOwner = SHIM_LOCK_GUID;
- CopyMem(p, *v->addend_source, *v->addend_size);
+
+ if (vendor_esl_size) {
+ CopyMem(p, vendor_esl, vendor_esl_size);
+ p += vendor_esl_size;
+ }
+
+ if (vendor_cert_size) {
+ EFI_SIGNATURE_LIST *CertList = NULL;
+ EFI_SIGNATURE_DATA *CertData = NULL;
+
+ 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 = vendor_cert_size
+ + sizeof (*CertList)
+ + sizeof (*CertData)
+ -1;
+ CertList->SignatureHeaderSize = 0;
+ CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID);
+
+ CertData->SignatureOwner = SHIM_LOCK_GUID;
+ CopyMem(p, vendor_cert, vendor_cert_size);
+ }
if (v->data && v->data_size)
FreePool(v->data);
@@ -247,9 +255,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 = (v->flags & MOK_VARIABLE_APPEND_CERT) != 0;
efi_status = get_variable_attr(v->name,
&v->data, &v->data_size,
diff --git a/shim.c b/shim.c
index 0015534..15b29fb 100644
--- a/shim.c
+++ b/shim.c
@@ -66,14 +66,18 @@ static UINT32 load_options_size;
*/
extern struct {
UINT32 vendor_cert_size;
+ UINT32 vendor_esl_size;
UINT32 vendor_dbx_size;
UINT32 vendor_cert_offset;
+ UINT32 vendor_esl_offset;
UINT32 vendor_dbx_offset;
} cert_table;
UINT32 vendor_cert_size;
+UINT32 vendor_esl_size;
UINT32 vendor_dbx_size;
UINT8 *vendor_cert;
+UINT8 *vendor_esl;
UINT8 *vendor_dbx;
/*
@@ -1059,6 +1063,25 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
}
#endif /* defined(ENABLE_SHIM_CERT) */
+ /*
+ * Check against a built-in EFI Signature List (ESL)
+ */
+ if (vendor_esl_size &&
+ check_db_cert_in_ram((EFI_SIGNATURE_LIST*)vendor_esl,
+ vendor_esl_size,
+ cert,
+ sha256hash,
+ L"Shim",
+ SHIM_LOCK_GUID) == DATA_FOUND) {
+ update_verification_method(VERIFIED_BY_CERT);
+ // tpm_measurement is done by check_db_cert_in_ram
+ efi_status = EFI_SUCCESS;
+ drain_openssl_errors();
+ return efi_status;
+ } else {
+ LogError(L"check_db_cert_in_ram(vendor_esl) failed\n");
+ }
+
/*
* And finally, check against shim's built-in key
*/
@@ -2535,8 +2558,10 @@ 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_esl_size = cert_table.vendor_esl_size;
vendor_dbx_size = cert_table.vendor_dbx_size;
vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset;
+ vendor_esl = (UINT8 *)&cert_table + cert_table.vendor_esl_offset;
vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset;
CHAR16 *msgs[] = {
L"import_mok_state() failed\n",
diff --git a/shim.h b/shim.h
index 04e770b..fb58b69 100644
--- a/shim.h
+++ b/shim.h
@@ -169,8 +169,10 @@ 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_esl_size;
extern UINT32 vendor_dbx_size;
extern UINT8 *vendor_cert;
+extern UINT8 *vendor_esl;
extern UINT8 *vendor_dbx;
extern UINT8 user_insecure_mode;
--
2.18.1