From ab26d9a5c035cd56e1b1ae8b0ef74e059fe61d77 Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Sat, 21 Jul 2018 04:12:57 +0200 Subject: [PATCH] Implement vendor EFI Signature List (ESL) Signed-off-by: Patrick Uiterwijk --- 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