arrfab / rpms / shim

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