File shim-more-tpm-measurement.patch of Package shim

From 0ed82edaf88e51b2e4da26104202d681bb78f948 Mon Sep 17 00:00:00 2001
From: Lans Zhang <jia.zhang@windriver.com>
Date: Wed, 21 Sep 2016 11:17:29 +0800
Subject: [PATCH 1/9] update verification_method if the loaded image is signed
 by shim/vendor cert

Signed-off-by: Lans Zhang <jia.zhang@windriver.com>
(cherry picked from commit 6d4498fb3b66621992ef61f163befd1c8374781b)
---
 shim.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/shim.c b/shim.c
index 48c8797..7081be2 100644
--- a/shim.c
+++ b/shim.c
@@ -1025,6 +1025,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
 			       cert->Hdr.dwLength - sizeof(cert->Hdr),
 			       shim_cert, sizeof(shim_cert), sha256hash,
 			       SHA256_DIGEST_SIZE)) {
+			update_verification_method(VERIFIED_BY_CERT);
 			status = EFI_SUCCESS;
 			return status;
 		}
@@ -1037,6 +1038,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
 				       cert->Hdr.dwLength - sizeof(cert->Hdr),
 				       vendor_cert, vendor_cert_size,
 				       sha256hash, SHA256_DIGEST_SIZE)) {
+			update_verification_method(VERIFIED_BY_CERT);
 			status = EFI_SUCCESS;
 			return status;
 		}
-- 
2.14.1


From 36719046eba3e92ec91887391648d551412f47db Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 15 Jun 2017 15:16:04 +0200
Subject: [PATCH 2/9] shim/tpm: Remove magic numbers

When measuring data into the TPM and generating events logs, the event
type is set to EV_IPL (0xd), and for TPM1.2 the algorithm will always
be set to SHA-1 (0x4).

So, add some macro-defined constants for these instead of having them
as magic numbers to make the code more readable.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
(cherry picked from commit 9c40fb7c0570430e28c8e5bc34223d6e3a59a929)
---
 tpm.c | 9 ++++-----
 tpm.h | 3 +++
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/tpm.c b/tpm.c
index 88920bb..99486b1 100644
--- a/tpm.c
+++ b/tpm.c
@@ -110,7 +110,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
 		event->Header.HeaderVersion = 1;
 		event->Header.PCRIndex = pcr;
-		event->Header.EventType = 0x0d;
+		event->Header.EventType = EV_IPL;
 		event->Size = sizeof(*event) - sizeof(event->Event) + strlen(description) + 1;
 		memcpy(event->Event, description, strlen(description) + 1);
 		status = uefi_call_wrapper(tpm2->hash_log_extend_event, 5, tpm2,
@@ -119,7 +119,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		return status;
 	} else {
 		TCG_PCR_EVENT *event;
-		UINT32 algorithm, eventnum = 0;
+		UINT32 eventnum = 0;
 		EFI_PHYSICAL_ADDRESS lastevent;
 
 		status = LibLocateProtocol(&tpm_guid, (VOID **)&tpm);
@@ -138,11 +138,10 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		}
 
 		event->PCRIndex = pcr;
-		event->EventType = 0x0d;
+		event->EventType = EV_IPL;
 		event->EventSize = strlen(description) + 1;
-		algorithm = 0x00000004;
 		status = uefi_call_wrapper(tpm->log_extend_event, 7, tpm, buf,
-					   (UINT64)size, algorithm, event,
+					   (UINT64)size, TPM_ALG_SHA, event,
 					   &eventnum, &lastevent);
 		FreePool(event);
 		return status;
diff --git a/tpm.h b/tpm.h
index 7c83644..27cb418 100644
--- a/tpm.h
+++ b/tpm.h
@@ -1,6 +1,9 @@
 #define EFI_TPM_GUID {0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }};
 #define EFI_TPM2_GUID {0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }};
 
+#define TPM_ALG_SHA 0x00000004
+#define EV_IPL      0x0000000d
+
 EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 			 const CHAR8 *description);
 
-- 
2.14.1


From 69f0b00e0fba6a08455e0e2f72726b73ad0c2cc6 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 15 Jun 2017 15:16:05 +0200
Subject: [PATCH 3/9] shim/tpm: Take out GetCapability() call from
 tpm2_present() logic

The EFI_TCG2_PROTOCOL.GetCapability() function is used to learn if a TPM2
chip is present. But the protocol capability information is also needed
for other reasons, for example to determine what event log formats are
supported by the firmware.

Take out the GetCapability() call from the tpm2_present() logic and reduce
that function to just checking if a TPM2 chip is available or not, so the
capabilities can later be used to determine the supported TPM log formats.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
(cherry picked from commit 0baa915056b6dc3dbea51c045e1e3ef8a0d86a08)
---
 tpm.c | 44 +++++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/tpm.c b/tpm.c
index 99486b1..2ca5845 100644
--- a/tpm.c
+++ b/tpm.c
@@ -35,29 +35,41 @@ static BOOLEAN tpm_present(efi_tpm_protocol_t *tpm)
 	return TRUE;
 }
 
-static BOOLEAN tpm2_present(efi_tpm2_protocol_t *tpm)
+static EFI_STATUS tpm2_get_caps(efi_tpm2_protocol_t *tpm,
+				EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
+				BOOLEAN *old_caps)
 {
 	EFI_STATUS status;
-	EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
-	TREE_BOOT_SERVICE_CAPABILITY *caps_1_0;
 
-	caps.Size = (UINT8)sizeof(caps);
+	caps->Size = (UINT8)sizeof(*caps);
 
-	status = uefi_call_wrapper(tpm->get_capability, 2, tpm, &caps);
+	status = uefi_call_wrapper(tpm->get_capability, 2, tpm, caps);
 
 	if (status != EFI_SUCCESS)
-		return FALSE;
+		return status;
+
+	if (caps->StructureVersion.Major == 1 &&
+	    caps->StructureVersion.Minor == 0)
+		*old_caps = TRUE;
 
-	if (caps.StructureVersion.Major == 1 &&
-	    caps.StructureVersion.Minor == 0) {
-		caps_1_0 = (TREE_BOOT_SERVICE_CAPABILITY *)&caps;
+	return EFI_SUCCESS;
+}
+
+static BOOLEAN tpm2_present(efi_tpm2_protocol_t *tpm,
+			    EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
+			    BOOLEAN old_caps)
+{
+	TREE_BOOT_SERVICE_CAPABILITY *caps_1_0;
+
+	if (old_caps) {
+		caps_1_0 = (TREE_BOOT_SERVICE_CAPABILITY *)caps;
 		if (caps_1_0->TrEEPresentFlag)
 			return TRUE;
-	} else {
-		if (caps.TPMPresentFlag)
-			return TRUE;
 	}
 
+	if (caps->TPMPresentFlag)
+		return TRUE;
+
 	return FALSE;
 }
 
@@ -90,9 +102,15 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 	status = LibLocateProtocol(&tpm2_guid, (VOID **)&tpm2);
 	/* TPM 2.0 */
 	if (status == EFI_SUCCESS) {
+		BOOLEAN old_caps;
 		EFI_TCG2_EVENT *event;
+		EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
+
+		status = tpm2_get_caps(tpm2, &caps, &old_caps);
+		if (status != EFI_SUCCESS)
+			return EFI_SUCCESS;
 
-		if (!tpm2_present(tpm2))
+		if (!tpm2_present(tpm2, &caps, old_caps))
 			return EFI_SUCCESS;
 
 		status = trigger_tcg2_final_events_table(tpm2);
-- 
2.14.1


From 947f9d7e70cc899997a1cfe89ee08152c6f921be Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 15 Jun 2017 15:16:06 +0200
Subject: [PATCH 4/9] shim/tpm: Avoid passing an usupported event log format to
 GetEventLogs()

The TCG EFI Protocol Specification for family "2.0" mentions that not all
TPM2 chips may support the EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 (crypto agile)
log format. So instead of always use this log format, the GetCapability()
function should be used to determine which format is supported by the TPM.

For example, the Intel PTT firmware based TPM found in Lenovo Thinkapd X1
Carbon (4th gen), only supports SHA-1 (EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2)
log format. So a call to GetEventLog() using the crypto agile format was
returning EFI_INVALID_PARAMETER, making tpm_log_event() function to fail.

This was preventing shim to correctly measure the second stage bootloader:

$ tpm2_listpcrs -L 0x04:9

Bank/Algorithm: TPM_ALG_SHA1(0x0004)
PCR_09: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

After passing a supported log format to GetEventLog(), it succeeds and so
shim is able to call the HashLogExtendEvent() EFI function correctly:

$ tpm2_listpcrs -L 0x04:9

Bank/Algorithm: TPM_ALG_SHA1(0x0004)
PCR_09: 07 5a 7e d3 75 64 ad 91 1a 34 17 17 c2 34 10 2b 58 5b de b7

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
(cherry picked from commit 55c65546e46a78edbe41e88cb4ccbd2522e09625)
---
 tpm.c | 30 +++++++++++++++++++++++++-----
 tpm.h |  3 ++-
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/tpm.c b/tpm.c
index 2ca5845..b2f9c46 100644
--- a/tpm.c
+++ b/tpm.c
@@ -73,6 +73,17 @@ static BOOLEAN tpm2_present(efi_tpm2_protocol_t *tpm,
 	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
@@ -81,15 +92,21 @@ static BOOLEAN tpm2_present(efi_tpm2_protocol_t *tpm,
  * 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)
+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;
 
-	return uefi_call_wrapper(tpm2->get_event_log, 5, tpm2,
-				 EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, &start,
-				 &end, &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 uefi_call_wrapper(tpm2->get_event_log, 5, tpm2, log_fmt,
+				 &start, &end, &truncated);
 }
 
 EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
@@ -105,6 +122,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		BOOLEAN old_caps;
 		EFI_TCG2_EVENT *event;
 		EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
+		EFI_TCG2_EVENT_LOG_BITMAP supported_logs;
 
 		status = tpm2_get_caps(tpm2, &caps, &old_caps);
 		if (status != EFI_SUCCESS)
@@ -113,7 +131,9 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		if (!tpm2_present(tpm2, &caps, old_caps))
 			return EFI_SUCCESS;
 
-		status = trigger_tcg2_final_events_table(tpm2);
+		supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps);
+
+		status = trigger_tcg2_final_events_table(tpm2, supported_logs);
 		if (EFI_ERROR(status)) {
 			perror(L"Unable to trigger tcg2 final events table: %r\n", status);
 			return status;
diff --git a/tpm.h b/tpm.h
index 27cb418..cc1bbed 100644
--- a/tpm.h
+++ b/tpm.h
@@ -122,7 +122,8 @@ typedef struct tdEFI_TCG2_EVENT {
   uint8_t Event[1];
 } __attribute__ ((packed)) EFI_TCG2_EVENT;
 
-#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2   0x00000002
 
 struct efi_tpm2_protocol
 {
-- 
2.14.1


From 7518101bcca0213afe1ca94fbedb76a06d644d1d Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 20 Jun 2017 16:41:44 -0400
Subject: [PATCH 5/9] tpm2_present(): remove unused tpm2 protocol argument.

Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 919c17a45fe722dcc2b9bdaba538c738f97f88cd)
---
 tpm.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/tpm.c b/tpm.c
index b2f9c46..c37cc48 100644
--- a/tpm.c
+++ b/tpm.c
@@ -55,8 +55,7 @@ static EFI_STATUS tpm2_get_caps(efi_tpm2_protocol_t *tpm,
 	return EFI_SUCCESS;
 }
 
-static BOOLEAN tpm2_present(efi_tpm2_protocol_t *tpm,
-			    EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
+static BOOLEAN tpm2_present(EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
 			    BOOLEAN old_caps)
 {
 	TREE_BOOT_SERVICE_CAPABILITY *caps_1_0;
@@ -128,7 +127,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		if (status != EFI_SUCCESS)
 			return EFI_SUCCESS;
 
-		if (!tpm2_present(tpm2, &caps, old_caps))
+		if (!tpm2_present(&caps, old_caps))
 			return EFI_SUCCESS;
 
 		supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps);
-- 
2.14.1


From 4d722aae64e74192c16682caa204c90013cc42c0 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@google.com>
Date: Mon, 22 May 2017 15:36:48 -0700
Subject: [PATCH 6/9] Extend PCR 7

It's desirable to be able to use PCR 7 for all TPM policy on Secure Boot
systems, but right now Shim doesn't record any information about its
configuration or the signature used to launch the second stage loader. Add
support for that.

(cherry picked from commit 8af7c4cacaf753f38f2564b26b962a7a2942d664)
---
 shim.c |  41 +++++++++++++++-----
 tpm.c  | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 tpm.h  |  16 ++++++++
 3 files changed, 174 insertions(+), 19 deletions(-)

diff --git a/shim.c b/shim.c
index 7081be2..f621af9 100644
--- a/shim.c
+++ b/shim.c
@@ -428,7 +428,8 @@ static BOOLEAN verify_eku(UINT8 *Cert, UINTN CertSize)
 static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
 					 UINTN dbsize,
 					 WIN_CERTIFICATE_EFI_PKCS *data,
-					 UINT8 *hash)
+					 UINT8 *hash, CHAR16 *dbname,
+					 EFI_GUID guid)
 {
 	EFI_SIGNATURE_DATA *Cert;
 	UINTN CertSize;
@@ -446,8 +447,10 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
 								      Cert->SignatureData,
 								      CertSize,
 								      hash, SHA256_DIGEST_SIZE);
-					if (IsFound)
+					if (IsFound) {
+						tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData);
 						return DATA_FOUND;
+					}
 				}
 			} else if (verbose) {
 				console_notify(L"Not a DER encoding x.509 Certificate");
@@ -477,7 +480,7 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
 
 	CertList = (EFI_SIGNATURE_LIST *)db;
 
-	rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
+	rc = check_db_cert_in_ram(CertList, dbsize, data, hash, dbname, guid);
 
 	FreePool(db);
 
@@ -489,7 +492,8 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
  */
 static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
 					 UINTN dbsize, UINT8 *data,
-					 int SignatureSize, EFI_GUID CertType)
+					 int SignatureSize, EFI_GUID CertType,
+					 CHAR16 *dbname, EFI_GUID guid)
 {
 	EFI_SIGNATURE_DATA *Cert;
 	UINTN CertCount, Index;
@@ -505,6 +509,7 @@ static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
 					// Find the signature in database.
 					//
 					IsFound = TRUE;
+					tpm_measure_variable(dbname, guid, SignatureSize, data);
 					break;
 				}
 
@@ -545,7 +550,8 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
 	CertList = (EFI_SIGNATURE_LIST *)db;
 
 	CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data,
-						SignatureSize, CertType);
+					       SignatureSize, CertType,
+					       dbname, guid);
 	FreePool(db);
 	return rc;
 
@@ -563,15 +569,18 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
 	EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
 
 	if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
-				 SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) ==
+				 SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID,
+				 L"dbx", secure_var) ==
 				DATA_FOUND)
 		return EFI_SECURITY_VIOLATION;
 	if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash,
-				 SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) ==
+				 SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID,
+				 L"dbx", secure_var) ==
 				DATA_FOUND)
 		return EFI_SECURITY_VIOLATION;
 	if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert,
-					 sha256hash) == DATA_FOUND)
+					 sha256hash, L"dbx",
+					 secure_var) == DATA_FOUND)
 		return EFI_SECURITY_VIOLATION;
 
 	if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
@@ -960,6 +969,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
 	EFI_STATUS status = EFI_SECURITY_VIOLATION;
 	WIN_CERTIFICATE_EFI_PKCS *cert = NULL;
 	unsigned int size = datasize;
+	EFI_GUID shim_var = SHIM_LOCK_GUID;
 
 	if (context->SecDir->Size != 0) {
 		if (context->SecDir->Size >= size) {
@@ -1026,6 +1036,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
 			       shim_cert, sizeof(shim_cert), sha256hash,
 			       SHA256_DIGEST_SIZE)) {
 			update_verification_method(VERIFIED_BY_CERT);
+			tpm_measure_variable(L"Shim", shim_var, sizeof(shim_cert), shim_cert);
 			status = EFI_SUCCESS;
 			return status;
 		}
@@ -1039,6 +1050,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
 				       vendor_cert, vendor_cert_size,
 				       sha256hash, SHA256_DIGEST_SIZE)) {
 			update_verification_method(VERIFIED_BY_CERT);
+			tpm_measure_variable(L"Shim", shim_var, vendor_cert_size, vendor_cert);
 			status = EFI_SUCCESS;
 			return status;
 		}
@@ -1888,7 +1900,11 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle)
 }
 
 /*
- * Measure some of the MOK variables into the TPM
+ * Measure some of the MOK variables into the TPM. We measure the entirety
+ * of MokList into PCR 14, and also measure the raw MokSBState there. PCR 7
+ * will be extended with MokSBState in the Microsoft format, and we'll
+ * measure any matching hashes or certificates later on in order to behave
+ * consistently with the PCR 7 spec.
  */
 EFI_STATUS measure_mok()
 {
@@ -1915,9 +1931,14 @@ EFI_STATUS measure_mok()
 	if (efi_status != EFI_SUCCESS)
 		return efi_status;
 
+	efi_status = tpm_measure_variable(L"MokSBState", shim_lock_guid,
+					  DataSize, Data);
+	if (efi_status != EFI_SUCCESS)
+		goto out;
+
 	efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
 				   DataSize, 14, (CHAR8 *)"MokSBState");
-
+out:
 	FreePool(Data);
 
 	return efi_status;
diff --git a/tpm.c b/tpm.c
index c37cc48..6e3933c 100644
--- a/tpm.c
+++ b/tpm.c
@@ -14,6 +14,16 @@ extern UINT8 in_protocol;
 		})
 
 
+typedef struct {
+	CHAR16 *VariableName;
+	EFI_GUID *VendorGuid;
+	VOID *Data;
+	UINTN Size;
+} VARIABLE_RECORD;
+
+UINTN measuredcount = 0;
+VARIABLE_RECORD *measureddata = NULL;
+
 EFI_GUID tpm_guid = EFI_TPM_GUID;
 EFI_GUID tpm2_guid = EFI_TPM2_GUID;
 
@@ -108,8 +118,9 @@ static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2,
 				 &start, &end, &truncated);
 }
 
-EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
-			 const CHAR8 *description)
+static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
+				    UINT8 pcr, const CHAR8 *log, UINTN logsize,
+				    UINT32 type)
 {
 	EFI_STATUS status;
 	efi_tpm_protocol_t *tpm;
@@ -138,7 +149,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 			return status;
 		}
 
-		event = AllocatePool(sizeof(*event) + strlen(description) + 1);
+		event = AllocatePool(sizeof(*event) + logsize);
 		if (!event) {
 			perror(L"Unable to allocate event structure\n");
 			return EFI_OUT_OF_RESOURCES;
@@ -147,9 +158,9 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
 		event->Header.HeaderVersion = 1;
 		event->Header.PCRIndex = pcr;
-		event->Header.EventType = EV_IPL;
-		event->Size = sizeof(*event) - sizeof(event->Event) + strlen(description) + 1;
-		memcpy(event->Event, description, strlen(description) + 1);
+		event->Header.EventType = type;
+		event->Size = sizeof(*event) - sizeof(event->Event) + logsize + 1;
+		CopyMem(event->Event, (VOID *)log, logsize);
 		status = uefi_call_wrapper(tpm2->hash_log_extend_event, 5, tpm2,
 					   0, buf, (UINT64) size, event);
 		FreePool(event);
@@ -167,7 +178,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		if (!tpm_present(tpm))
 			return EFI_SUCCESS;
 
-		event = AllocatePool(sizeof(*event) + strlen(description) + 1);
+		event = AllocatePool(sizeof(*event) + logsize);
 
 		if (!event) {
 			perror(L"Unable to allocate event structure\n");
@@ -175,8 +186,9 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 		}
 
 		event->PCRIndex = pcr;
-		event->EventType = EV_IPL;
-		event->EventSize = strlen(description) + 1;
+		event->EventType = type;
+		event->EventSize = logsize;
+		CopyMem(event->Event, (VOID *)log, logsize);
 		status = uefi_call_wrapper(tpm->log_extend_event, 7, tpm, buf,
 					   (UINT64)size, TPM_ALG_SHA, event,
 					   &eventnum, &lastevent);
@@ -186,3 +198,109 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 
 	return EFI_SUCCESS;
 }
+EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
+			 const CHAR8 *description)
+{
+	return tpm_log_event_raw(buf, size, pcr, description,
+				 strlen(description) + 1, 0xd);
+}
+
+typedef struct {
+	EFI_GUID VariableName;
+	UINT64 UnicodeNameLength;
+	UINT64 VariableDataLength;
+	CHAR16 UnicodeName[1];
+	INT8 VariableData[1];
+} EFI_VARIABLE_DATA_TREE;
+
+static BOOLEAN tpm_data_measured(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData)
+{
+	UINTN i;
+
+	for (i=0; i<measuredcount; i++) {
+		if ((StrCmp (VarName, measureddata[i].VariableName) == 0) &&
+		    (CompareGuid (&VendorGuid, measureddata[i].VendorGuid)) &&
+		    (VarSize == measureddata[i].Size) &&
+		    (CompareMem (VarData, measureddata[i].Data, VarSize) == 0)) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static EFI_STATUS tpm_record_data_measurement(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData)
+{
+	if (measureddata == NULL) {
+		measureddata = AllocatePool(sizeof(*measureddata));
+	} else {
+		measureddata = ReallocatePool(measureddata, measuredcount * sizeof(*measureddata),
+					      (measuredcount + 1) * sizeof(*measureddata));
+	}
+
+	if (measureddata == NULL)
+		return EFI_OUT_OF_RESOURCES;
+
+	measureddata[measuredcount].VariableName = AllocatePool(StrSize(VarName));
+	measureddata[measuredcount].VendorGuid = AllocatePool(sizeof(EFI_GUID));
+	measureddata[measuredcount].Data = AllocatePool(VarSize);
+
+	if (measureddata[measuredcount].VariableName == NULL ||
+	    measureddata[measuredcount].VendorGuid == NULL ||
+	    measureddata[measuredcount].Data == NULL) {
+		return EFI_OUT_OF_RESOURCES;
+	}
+
+	StrCpy(measureddata[measuredcount].VariableName, VarName);
+	CopyMem(measureddata[measuredcount].VendorGuid, &VendorGuid, sizeof(EFI_GUID));
+	CopyMem(measureddata[measuredcount].Data, VarData, VarSize);
+	measureddata[measuredcount].Size = VarSize;
+	measuredcount++;
+
+	return EFI_SUCCESS;
+}
+
+EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData)
+{
+	EFI_STATUS Status;
+	UINTN VarNameLength;
+	EFI_VARIABLE_DATA_TREE *VarLog;
+	UINT32 VarLogSize;
+
+	/* Don't measure something that we've already measured */
+	if (tpm_data_measured(VarName, VendorGuid, VarSize, VarData))
+		return EFI_SUCCESS;
+
+	VarNameLength = StrLen (VarName);
+	VarLogSize = (UINT32)(sizeof (*VarLog) +
+			      VarNameLength * sizeof (*VarName) +
+			      VarSize -
+			      sizeof (VarLog->UnicodeName) -
+			      sizeof (VarLog->VariableData));
+
+	VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);
+	if (VarLog == NULL) {
+		return EFI_OUT_OF_RESOURCES;
+	}
+
+	CopyMem (&VarLog->VariableName, &VendorGuid,
+		 sizeof(VarLog->VariableName));
+	VarLog->UnicodeNameLength  = VarNameLength;
+	VarLog->VariableDataLength = VarSize;
+	CopyMem (VarLog->UnicodeName, VarName,
+		 VarNameLength * sizeof (*VarName));
+	CopyMem ((CHAR16 *)VarLog->UnicodeName + VarNameLength, VarData,
+		 VarSize);
+
+	Status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)VarLog, VarLogSize, 7,
+				   (CHAR8 *)VarLog, VarLogSize,
+				   EV_EFI_VARIABLE_AUTHORITY);
+
+	FreePool(VarLog);
+
+	if (Status != EFI_SUCCESS)
+		return Status;
+
+	return tpm_record_data_measurement(VarName, VendorGuid, VarSize,
+					   VarData);
+}
diff --git a/tpm.h b/tpm.h
index cc1bbed..3769a1d 100644
--- a/tpm.h
+++ b/tpm.h
@@ -7,6 +7,8 @@
 EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 			 const CHAR8 *description);
 
+EFI_STATUS tpm_measure_variable(CHAR16 *dbname, EFI_GUID guid, UINTN size, void *data);
+
 typedef struct {
   uint8_t Major;
   uint8_t Minor;
@@ -154,3 +156,17 @@ struct efi_tpm2_protocol
 };
 
 typedef struct efi_tpm2_protocol efi_tpm2_protocol_t;
+
+typedef UINT32                     TCG_EVENTTYPE;
+
+#define EV_EFI_EVENT_BASE                   ((TCG_EVENTTYPE) 0x80000000)
+#define EV_EFI_VARIABLE_DRIVER_CONFIG       (EV_EFI_EVENT_BASE + 1)
+#define EV_EFI_VARIABLE_BOOT                (EV_EFI_EVENT_BASE + 2)
+#define EV_EFI_BOOT_SERVICES_APPLICATION    (EV_EFI_EVENT_BASE + 3)
+#define EV_EFI_BOOT_SERVICES_DRIVER         (EV_EFI_EVENT_BASE + 4)
+#define EV_EFI_RUNTIME_SERVICES_DRIVER      (EV_EFI_EVENT_BASE + 5)
+#define EV_EFI_GPT_EVENT                    (EV_EFI_EVENT_BASE + 6)
+#define EV_EFI_ACTION                       (EV_EFI_EVENT_BASE + 7)
+#define EV_EFI_PLATFORM_FIRMWARE_BLOB       (EV_EFI_EVENT_BASE + 8)
+#define EV_EFI_HANDOFF_TABLES               (EV_EFI_EVENT_BASE + 9)
+#define EV_EFI_VARIABLE_AUTHORITY           (EV_EFI_EVENT_BASE + 0xE0)
-- 
2.14.1


From 6572858b0c39cd8ba32e7e0d3f6791ccbe4d69c7 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@google.com>
Date: Wed, 12 Jul 2017 15:29:24 -0700
Subject: [PATCH 7/9] Measure stage 2 according to spec

We're currently measuring the raw second stage loader into PCR 9, but
we're closer to spec if we measure the semi-parsed PE into PCR 4. The
hash that's logged is the same as the hash used for the Authenticode
validation, so refactor shim.c a little to separate out the hash
generation.

(cherry picked from commit 22f2737535ca09faf48762df89b61e81b8d4a2f8)
---
 shim.c | 30 +++++++++++++++++++++---------
 tpm.c  | 55 +++++++++++++++++++++++++++++++++++++++++++++++--------
 tpm.h  | 15 +++++++++++++++
 3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/shim.c b/shim.c
index f621af9..8feed6d 100644
--- a/shim.c
+++ b/shim.c
@@ -962,10 +962,9 @@ static EFI_STATUS verify_mok (void) {
  * Check that the signature is valid and matches the binary
  */
 static EFI_STATUS verify_buffer (char *data, int datasize,
-			 PE_COFF_LOADER_IMAGE_CONTEXT *context)
+				 PE_COFF_LOADER_IMAGE_CONTEXT *context,
+				 UINT8 *sha256hash, UINT8 *sha1hash)
 {
-	UINT8 sha256hash[SHA256_DIGEST_SIZE];
-	UINT8 sha1hash[SHA1_DIGEST_SIZE];
 	EFI_STATUS status = EFI_SECURITY_VIOLATION;
 	WIN_CERTIFICATE_EFI_PKCS *cert = NULL;
 	unsigned int size = datasize;
@@ -1206,6 +1205,8 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
 	unsigned int alignment, alloc_size;
 	EFI_PHYSICAL_ADDRESS alloc_address;
 	int found_entry_point = 0;
+	UINT8 sha1hash[SHA1_DIGEST_SIZE];
+	UINT8 sha256hash[SHA256_DIGEST_SIZE];
 
 	/*
 	 * The binary header contains relevant context and section pointers
@@ -1219,8 +1220,17 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
 	/*
 	 * We only need to verify the binary if we're in secure mode
 	 */
+	efi_status = generate_hash(data, datasize, &context, sha256hash,
+				   sha1hash);
+	if (efi_status != EFI_SUCCESS)
+		return efi_status;
+
+	/* Measure the binary into the TPM */
+	tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, sha1hash, 4);
+
 	if (secure_mode ()) {
-		efi_status = verify_buffer(data, datasize, &context);
+		efi_status = verify_buffer(data, datasize, &context,
+					   sha256hash, sha1hash);
 
 		if (EFI_ERROR(efi_status)) {
 			console_error(L"Verification failed", efi_status);
@@ -1711,6 +1721,8 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size)
 {
 	EFI_STATUS status = EFI_SUCCESS;
 	PE_COFF_LOADER_IMAGE_CONTEXT context;
+	UINT8 sha1hash[SHA1_DIGEST_SIZE];
+	UINT8 sha256hash[SHA256_DIGEST_SIZE];
 
 	loader_is_participating = 1;
 	in_protocol = 1;
@@ -1722,7 +1734,11 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size)
 	if (status != EFI_SUCCESS)
 		goto done;
 
-	status = verify_buffer(buffer, size, &context);
+	status = generate_hash(buffer, size, &context, sha256hash, sha1hash);
+	if (status != EFI_SUCCESS)
+		goto done;
+
+	status = verify_buffer(buffer, size, &context, sha256hash, sha1hash);
 done:
 	in_protocol = 0;
 	return status;
@@ -1826,10 +1842,6 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
 		}
 	}
 
-	/* Measure the binary into the TPM */
-	tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize,
-		      9, (CHAR8 *)"Second stage bootloader");
-
 	/*
 	 * We need to modify the loaded image protocol entry before running
 	 * the new binary, so back it up
diff --git a/tpm.c b/tpm.c
index 6e3933c..af6b126 100644
--- a/tpm.c
+++ b/tpm.c
@@ -120,7 +120,7 @@ static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2,
 
 static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
 				    UINT8 pcr, const CHAR8 *log, UINTN logsize,
-				    UINT32 type)
+				    UINT32 type, CHAR8 *hash)
 {
 	EFI_STATUS status;
 	efi_tpm_protocol_t *tpm;
@@ -161,8 +161,18 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
 		event->Header.EventType = type;
 		event->Size = sizeof(*event) - sizeof(event->Event) + logsize + 1;
 		CopyMem(event->Event, (VOID *)log, logsize);
-		status = uefi_call_wrapper(tpm2->hash_log_extend_event, 5, tpm2,
-					   0, buf, (UINT64) size, event);
+		if (hash) {
+			/* TPM 2 systems will generate the appropriate hash
+			   themselves if we pass PE_COFF_IMAGE
+			*/
+			status = uefi_call_wrapper(tpm2->hash_log_extend_event,
+						   5, tpm2, PE_COFF_IMAGE, buf,
+						   (UINT64) size, event);
+		} else {
+			status = uefi_call_wrapper(tpm2->hash_log_extend_event,
+						   5, tpm2, 0, buf,
+						   (UINT64) size, event);
+		}
 		FreePool(event);
 		return status;
 	} else {
@@ -189,9 +199,21 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
 		event->EventType = type;
 		event->EventSize = logsize;
 		CopyMem(event->Event, (VOID *)log, logsize);
-		status = uefi_call_wrapper(tpm->log_extend_event, 7, tpm, buf,
-					   (UINT64)size, TPM_ALG_SHA, event,
-					   &eventnum, &lastevent);
+		if (hash) {
+			/* TPM 1.2 devices require us to pass the Authenticode
+			   hash rather than allowing the firmware to attempt
+			   to calculate it */
+			CopyMem(event->digest, hash, sizeof(event->digest));
+			status = uefi_call_wrapper(tpm->log_extend_event, 7,
+						   tpm, 0, 0, TPM_ALG_SHA,
+						   event, &eventnum,
+						   &lastevent);
+		} else {
+			status = uefi_call_wrapper(tpm->log_extend_event, 7,
+						   tpm, buf, (UINT64)size,
+						   TPM_ALG_SHA, event,
+						   &eventnum, &lastevent);
+		}
 		FreePool(event);
 		return status;
 	}
@@ -202,7 +224,24 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 			 const CHAR8 *description)
 {
 	return tpm_log_event_raw(buf, size, pcr, description,
-				 strlen(description) + 1, 0xd);
+				 strlen(description) + 1, 0xd, NULL);
+}
+
+EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, 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);
 }
 
 typedef struct {
@@ -294,7 +333,7 @@ EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarS
 
 	Status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)VarLog, VarLogSize, 7,
 				   (CHAR8 *)VarLog, VarLogSize,
-				   EV_EFI_VARIABLE_AUTHORITY);
+				   EV_EFI_VARIABLE_AUTHORITY, NULL);
 
 	FreePool(VarLog);
 
diff --git a/tpm.h b/tpm.h
index 3769a1d..e3c2b92 100644
--- a/tpm.h
+++ b/tpm.h
@@ -1,3 +1,5 @@
+#include <efilib.h>
+
 #define EFI_TPM_GUID {0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }};
 #define EFI_TPM2_GUID {0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }};
 
@@ -7,6 +9,9 @@
 EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 			 const CHAR8 *description);
 
+EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash,
+		      UINT8 pcr);
+
 EFI_STATUS tpm_measure_variable(CHAR16 *dbname, EFI_GUID guid, UINTN size, void *data);
 
 typedef struct {
@@ -33,6 +38,14 @@ typedef struct _TCG_PCR_EVENT {
   uint8_t  Event[1];
 } TCG_PCR_EVENT;
 
+typedef struct _EFI_IMAGE_LOAD_EVENT {
+  EFI_PHYSICAL_ADDRESS ImageLocationInMemory;
+  UINTN ImageLengthInMemory;
+  UINTN ImageLinkTimeAddress;
+  UINTN LengthOfDevicePath;
+  EFI_DEVICE_PATH DevicePath[1];
+} EFI_IMAGE_LOAD_EVENT;
+
 struct efi_tpm_protocol
 {
   EFI_STATUS (EFIAPI *status_check) (struct efi_tpm_protocol *this,
@@ -170,3 +183,5 @@ typedef UINT32                     TCG_EVENTTYPE;
 #define EV_EFI_PLATFORM_FIRMWARE_BLOB       (EV_EFI_EVENT_BASE + 8)
 #define EV_EFI_HANDOFF_TABLES               (EV_EFI_EVENT_BASE + 9)
 #define EV_EFI_VARIABLE_AUTHORITY           (EV_EFI_EVENT_BASE + 0xE0)
+
+#define PE_COFF_IMAGE 0x0000000000000010
-- 
2.14.1


From c40cc115a60da33ce2291149471bfd740981bc37 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 1 Aug 2017 11:19:33 -0400
Subject: [PATCH 8/9] Always measure all of MokSBState, MokList, and MokListX

Even if errors occurred, always try to measure all of our Mok entries.
This way we won't fail on e.g. MokList not being set.

Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit bdc5d3ec9ca5e0f270dc583c86ef8916ee70ac39)
---
 shim.c | 56 +++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 37 insertions(+), 19 deletions(-)

diff --git a/shim.c b/shim.c
index 8feed6d..32aa521 100644
--- a/shim.c
+++ b/shim.c
@@ -1921,37 +1921,55 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle)
 EFI_STATUS measure_mok()
 {
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
-	EFI_STATUS efi_status;
+	EFI_STATUS efi_status, ret = EFI_SUCCESS;
 	UINT8 *Data = NULL;
 	UINTN DataSize = 0;
 
 	efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid);
-	if (efi_status != EFI_SUCCESS)
-		return efi_status;
+	if (!EFI_ERROR(efi_status)) {
+		efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
+					   DataSize, 14, (CHAR8 *)"MokList");
+		FreePool(Data);
 
-	efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
-				   DataSize, 14, (CHAR8 *)"MokList");
+		if (EFI_ERROR(efi_status))
+			ret = efi_status;
 
-	FreePool(Data);
+	} else {
+		ret = efi_status;
+	}
 
-	if (efi_status != EFI_SUCCESS)
-		return efi_status;
+	efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid);
+	if (!EFI_ERROR(efi_status)) {
+		efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
+					   DataSize, 14, (CHAR8 *)"MokListX");
+		FreePool(Data);
+
+		if (EFI_ERROR(efi_status) && !EFI_ERROR(ret))
+			ret = efi_status;
+
+	} else if (!EFI_ERROR(ret)) {
+		ret = efi_status;
+	}
 
 	efi_status = get_variable(L"MokSBState", &Data, &DataSize,
 				  shim_lock_guid);
+	if (!EFI_ERROR(efi_status)) {
+		efi_status = tpm_measure_variable(L"MokSBState",
+						  shim_lock_guid,
+						  DataSize, Data);
+		if (!EFI_ERROR(efi_status)) {
+			efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)
+						    (UINTN)Data, DataSize, 14,
+						   (CHAR8 *)"MokSBState");
+		}
 
-	if (efi_status != EFI_SUCCESS)
-		return efi_status;
-
-	efi_status = tpm_measure_variable(L"MokSBState", shim_lock_guid,
-					  DataSize, Data);
-	if (efi_status != EFI_SUCCESS)
-		goto out;
+		FreePool(Data);
 
-	efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data,
-				   DataSize, 14, (CHAR8 *)"MokSBState");
-out:
-	FreePool(Data);
+		if (EFI_ERROR(efi_status) && !EFI_ERROR(ret))
+			ret = efi_status;
+	} else if (!EFI_ERROR(ret)) {
+		ret = efi_status;
+	}
 
 	return efi_status;
 }
-- 
2.14.1


From de680d100d94d613be32168fcefa0f47868ba07c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 31 Jul 2017 13:10:41 -0400
Subject: [PATCH 9/9] Make fallback aware of tpm measurements, and reboot if
 tpm is used.

Since booting the entry with fallback in the stack of things that got
measured will result in all the wrong PCR values, in the cases where TPM
is present and enabled, use ->Reset() instead of loading the Boot####
variable and executing its target.

Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 431b8a2e75a71a0b1f47d47d3f045b1e3efbce53)
---
 Makefile   |  2 +-
 fallback.c |  9 +++++++-
 tpm.c      | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 tpm.h      |  1 +
 4 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/Makefile b/Makefile
index d518615..05e8f46 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,7 @@ KEYS	= shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim
 SOURCES	= shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h tpm.c tpm.h version.c version.h
 MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o
 MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h
-FALLBACK_OBJS = fallback.o
+FALLBACK_OBJS = fallback.o tpm.o
 FALLBACK_SRCS = fallback.c
 
 ifneq ($(origin ENABLE_HTTPBOOT), undefined)
diff --git a/fallback.c b/fallback.c
index 8c0369f..55ce79f 100644
--- a/fallback.c
+++ b/fallback.c
@@ -12,6 +12,7 @@
 
 #include "ucs2.h"
 #include "variables.h"
+#include "tpm.h"
 
 EFI_LOADED_IMAGE *this_image = NULL;
 
@@ -1020,7 +1021,13 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
 		return rc;
 	}
 
-	try_start_first_option(image);
+	rc = fallback_should_prefer_reset();
+	if (EFI_ERROR(rc)) {
+		VerbosePrint(L"tpm not present, starting the first image\n");
+		try_start_first_option(image);
+	} else {
+		VerbosePrint(L"tpm present, resetting system\n");
+	}
 
 	Print(L"Reset System\n");
 
diff --git a/tpm.c b/tpm.c
index af6b126..0a36e1c 100644
--- a/tpm.c
+++ b/tpm.c
@@ -118,28 +118,60 @@ static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2,
 				 &start, &end, &truncated);
 }
 
-static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
-				    UINT8 pcr, const CHAR8 *log, UINTN logsize,
-				    UINT32 type, CHAR8 *hash)
+static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm,
+				      efi_tpm2_protocol_t **tpm2,
+				      BOOLEAN *old_caps_p,
+				      EFI_TCG2_BOOT_SERVICE_CAPABILITY *capsp)
 {
 	EFI_STATUS status;
-	efi_tpm_protocol_t *tpm;
-	efi_tpm2_protocol_t *tpm2;
 
-	status = LibLocateProtocol(&tpm2_guid, (VOID **)&tpm2);
+	*tpm = NULL;
+	*tpm2 = NULL;
+	status = LibLocateProtocol(&tpm2_guid, (VOID **)tpm2);
 	/* TPM 2.0 */
 	if (status == EFI_SUCCESS) {
 		BOOLEAN old_caps;
-		EFI_TCG2_EVENT *event;
 		EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
-		EFI_TCG2_EVENT_LOG_BITMAP supported_logs;
 
-		status = tpm2_get_caps(tpm2, &caps, &old_caps);
-		if (status != EFI_SUCCESS)
+		status = tpm2_get_caps(*tpm2, &caps, &old_caps);
+		if (EFI_ERROR(status))
+			return status;
+
+		if (tpm2_present(&caps, old_caps)) {
+			if (old_caps_p)
+				*old_caps_p = old_caps;
+			if (capsp)
+				memcpy(capsp, &caps, sizeof(caps));
 			return EFI_SUCCESS;
+		}
+	} else {
+		status = LibLocateProtocol(&tpm_guid, (VOID **)tpm);
+		if (EFI_ERROR(status))
+			return status;
 
-		if (!tpm2_present(&caps, old_caps))
+		if (tpm_present(*tpm))
 			return EFI_SUCCESS;
+	}
+
+	return EFI_NOT_FOUND;
+}
+
+static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
+				    UINT8 pcr, const CHAR8 *log, UINTN logsize,
+				    UINT32 type, CHAR8 *hash)
+{
+	EFI_STATUS status;
+	efi_tpm_protocol_t *tpm;
+	efi_tpm2_protocol_t *tpm2;
+	BOOLEAN old_caps;
+	EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
+
+	status = tpm_locate_protocol(&tpm, &tpm2, &old_caps, &caps);
+	if (EFI_ERROR(status)) {
+		return status;
+	} else if (tpm2) {
+		EFI_TCG2_EVENT *event;
+		EFI_TCG2_EVENT_LOG_BITMAP supported_logs;
 
 		supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps);
 
@@ -175,7 +207,7 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
 		}
 		FreePool(event);
 		return status;
-	} else {
+	} else if (tpm) {
 		TCG_PCR_EVENT *event;
 		UINT32 eventnum = 0;
 		EFI_PHYSICAL_ADDRESS lastevent;
@@ -220,6 +252,7 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
 
 	return EFI_SUCCESS;
 }
+
 EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
 			 const CHAR8 *description)
 {
@@ -343,3 +376,16 @@ EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarS
 	return tpm_record_data_measurement(VarName, VendorGuid, VarSize,
 					   VarData);
 }
+
+EFI_STATUS
+fallback_should_prefer_reset(void)
+{
+	EFI_STATUS status;
+	efi_tpm_protocol_t *tpm;
+	efi_tpm2_protocol_t *tpm2;
+
+	status = tpm_locate_protocol(&tpm, &tpm2, NULL, NULL);
+	if (EFI_ERROR(status))
+		return EFI_NOT_FOUND;
+	return EFI_SUCCESS;
+}
diff --git a/tpm.h b/tpm.h
index e3c2b92..d11b545 100644
--- a/tpm.h
+++ b/tpm.h
@@ -8,6 +8,7 @@
 
 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);
-- 
2.14.1

openSUSE Build Service is sponsored by