[coreboot-gerrit] Change in coreboot[master]: security/tpm: Add TPM measurement code

Philipp Deppenwiese (Code Review) gerrit at coreboot.org
Thu Dec 14 15:51:36 CET 2017


Philipp Deppenwiese has uploaded this change for review. ( https://review.coreboot.org/22867


Change subject: security/tpm: Add TPM measurement code
......................................................................

security/tpm: Add TPM measurement code

* Add TPM hash_{start,update,complete} functionality
* Add TCPA ACPI logging functionality
* Add TSPI functions for measuring and hashing data

Change-Id: I0a52494f647d21e2587231af26ed13d62b3a72f5
Signed-off-by: Philipp Deppenwiese <zaolin at das-labor.org>
---
M src/security/tpm/tspi.h
M src/security/tpm/tspi/tspi.c
M src/security/tpm/tss.h
M src/security/tpm/tss/tcg-1.2/tss.c
M src/security/tpm/tss/tcg-1.2/tss_structures.h
M src/security/tpm/tss/tcg-2.0/tss.c
6 files changed, 196 insertions(+), 18 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/67/22867/1

diff --git a/src/security/tpm/tspi.h b/src/security/tpm/tspi.h
index de3849a..1a84c62 100644
--- a/src/security/tpm/tspi.h
+++ b/src/security/tpm/tspi.h
@@ -18,6 +18,20 @@
 
 #include <security/tpm/tss.h>
 
+#define TPM_PCR_MAX_LENGTH 64
+
+/**
+ * TPM measurement with acpi log functionality based on binary data.
+ */
+uint32_t tpm_measure_data(int pcr, const uint8_t *data, uint32_t data_length,
+			  const char *name);
+
+/**
+ * TPM hash binary data.
+ */
+uint32_t tpm_hash(const uint8_t *data, size_t data_length, uint8_t **digest,
+		  uint32_t *digest_length);
+
 /**
  * Ask vboot for a digest and extend a TPM PCR with it.
  */
@@ -33,5 +47,4 @@
  */
 uint32_t tpm_setup(int s3flag);
 
-
-#endif  /* TSPI_H_ */
+#endif /* TSPI_H_ */
diff --git a/src/security/tpm/tspi/tspi.c b/src/security/tpm/tspi/tspi.c
index 9969cd3..891cc6a 100644
--- a/src/security/tpm/tspi/tspi.c
+++ b/src/security/tpm/tspi/tspi.c
@@ -14,13 +14,13 @@
  * GNU General Public License for more details.
  */
 
+#include <console/cbmem_console.h>
+#include <console/console.h>
+#include <reset.h>
+#include <security/tpm/tspi.h>
+#include <security/tpm/tss.h>
 #include <stdlib.h>
 #include <string.h>
-#include <security/tpm/tss.h>
-#include <security/tpm/tspi.h>
-#include <console/console.h>
-#include <console/cbmem_console.h>
-#include <reset.h>
 
 /*
  * SetupTPM starts the TPM and establishes the root of trust for the
@@ -79,13 +79,16 @@
 		 */
 		result = tlcl_physical_presence_cmd_enable();
 		if (result != TPM_SUCCESS) {
-			printk(BIOS_ERR, "TPM: Can't enable physical presence command.\n");
+			printk(
+			    BIOS_ERR,
+			    "TPM: Can't enable physical presence command.\n");
 			return result;
 		}
 
 		result = tlcl_assert_physical_presence();
 		if (result != TPM_SUCCESS) {
-			printk(BIOS_ERR, "TPM: Can't assert physical presence.\n");
+			printk(BIOS_ERR,
+			       "TPM: Can't assert physical presence.\n");
 			return result;
 		}
 	}
@@ -98,8 +101,9 @@
 	}
 
 	if (disable || deactivated) {
-		printk(BIOS_INFO, "TPM: disabled (%d) or deactivated (%d). Fixing...\n",
-			disable, deactivated);
+		printk(BIOS_INFO,
+		       "TPM: disabled (%d) or deactivated (%d). Fixing...\n",
+		       disable, deactivated);
 
 		result = tlcl_set_enable();
 		if (result != TPM_SUCCESS) {
@@ -130,7 +134,7 @@
 	uint32_t result = __tpm_setup(s3flag);
 
 	if (IS_ENABLED(CONFIG_TPM_INIT_FAILURE_IS_FATAL) &&
-		result != TPM_SUCCESS) {
+	    result != TPM_SUCCESS) {
 		printk(BIOS_ERR, "Hard reset!\n");
 		post_code(POST_TPM_FAILURE);
 		if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART))
@@ -181,3 +185,72 @@
 
 	return tlcl_extend(pcr, digest, NULL);
 }
+
+uint32_t tpm_hash(const uint8_t *data, size_t data_length, uint8_t **digest,
+		  uint32_t *digest_length)
+{
+	uint32_t data_max_length = 0;
+	uint32_t result;
+	size_t i, hash_rounds = 0;
+
+	result = tlcl_hash_start(&data_max_length);
+	if (result != TPM_SUCCESS) {
+		printk(BIOS_ERR, "TPM: Start hash routine.\n");
+		return result;
+	}
+
+	hash_rounds = (size_t)(data_max_length / data_length);
+	for (i = 0; i < hash_rounds; i++) {
+		result = tlcl_hash_update(data + (i * data_max_length),
+					  data_max_length);
+		if (result != TPM_SUCCESS) {
+			printk(BIOS_ERR, "TPM: Update hash routine.\n");
+			return result;
+		}
+	}
+
+	if (data_max_length % data_length == 0) {
+		result = tlcl_hash_complete(NULL, 0, digest, digest_length);
+	} else {
+		result = tlcl_hash_complete(
+		    data + (hash_rounds * data_max_length),
+		    data_max_length % data_length, digest, digest_length);
+	}
+
+	if (result != TPM_SUCCESS) {
+		printk(BIOS_ERR, "TPM: Complete hash routine.\n");
+		return result;
+	}
+
+	return result;
+}
+
+uint32_t tpm_measure_data(int pcr, const uint8_t *data, uint32_t data_length,
+			  const char *name)
+{
+	uint8_t digest[TPM_PCR_MAX_LENGTH];
+	uint32_t digest_length = 0;
+	uint32_t result;
+
+	result =
+	    tpm_hash(data, data_length, (uint8_t **)&digest, &digest_length);
+	if (result != TPM_SUCCESS && digest != NULL) {
+		printk(BIOS_ERR, "TPM: Hashing data failed.\n");
+		return result;
+	}
+
+	result = tlcl_extend(pcr, digest, NULL);
+	if (result != TPM_SUCCESS) {
+		printk(BIOS_ERR, "TPM: Extending hash into PCR failed.\n");
+		return result;
+	}
+
+	result = tlcl_tcpa_log(pcr, digest, digest_length, name);
+	if (result != TPM_SUCCESS) {
+		printk(BIOS_ERR,
+		       "TPM: Writing measurement meta information failed.\n");
+		return result;
+	}
+
+	return result;
+}
diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h
index 612df0f..a423e41 100644
--- a/src/security/tpm/tss.h
+++ b/src/security/tpm/tss.h
@@ -179,7 +179,13 @@
  *
  */
 uint32_t tlcl_hash_complete(const void *message, uint32_t message_length,
-	uint8_t **digest);
+			    uint8_t **digest, uint32_t *digest_length);
+
+/**
+ * TCPA ACPI log
+ */
+uint32_t tlcl_tcpa_log(int pcr, uint8_t *digest, uint32_t digest_length,
+		       const char *name);
 
 /**
  * CR50 specific tpm command to enable nvmem commits before internal timeout
@@ -199,4 +205,4 @@
 uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
 				 uint8_t *num_restored_headers);
 
-#endif  /* TSS_H_ */
+#endif /* TSS_H_ */
diff --git a/src/security/tpm/tss/tcg-1.2/tss.c b/src/security/tpm/tss/tcg-1.2/tss.c
index 2bb2269..3fa31bb 100644
--- a/src/security/tpm/tss/tcg-1.2/tss.c
+++ b/src/security/tpm/tss/tcg-1.2/tss.c
@@ -1,4 +1,5 @@
 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Copyright 2017 Facebook Inc.
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
@@ -16,6 +17,7 @@
 
 #include <arch/early_variables.h>
 #include <assert.h>
+#include <cbmem.h>
 #include <security/tpm/tis.h>
 #include <security/tpm/tss.h>
 #include <string.h>
@@ -386,7 +388,7 @@
 }
 
 uint32_t tlcl_hash_complete(const void *message, uint32_t message_length,
-			    uint8_t **digest)
+			    uint8_t **digest, uint32_t *digest_length)
 {
 	struct s_tpm_sha1_complete_cmd cmd;
 	uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
@@ -405,9 +407,11 @@
 	       message_length);
 
 	result = tlcl_send_receive(cmd.buffer, response, sizeof(response));
-	if (result == TPM_SUCCESS)
+	if (result == TPM_SUCCESS) {
 		memcpy(*digest, response + kTpmResponseHeaderLength,
 		       kPcrDigestLength);
+		*digest_length = TPM_PCR_DIGEST;
+	}
 
 	return result;
 }
@@ -424,7 +428,67 @@
 	result = tlcl_send_receive(cmd.buffer, response, sizeof(response));
 	if (result == TPM_SUCCESS)
 		memcpy(out_digest, response + kTpmResponseHeaderLength,
-				kPcrDigestLength);
+		       kPcrDigestLength);
 
 	return result;
 }
+
+uint32_t tlcl_tcpa_log(int pcr, uint8_t *digest, uint32_t digest_length,
+		       const char *name)
+{
+	const struct cbmem_entry *ce;
+	TPM_PCR_EVENT tcpa_event;
+	TPM_DIGEST pcr_digest;
+	void *lasa;
+	uint8_t *ptr;
+	size_t size;
+
+	if (name == NULL) {
+		printk(BIOS_ERR, "TCPA log message is NULL\n");
+		return 1;
+	}
+
+	if (strlen(name) >= TPM_EVENT_DATA_SIZE) {
+		printk(BIOS_ERR, "TCPA log message is too big\n");
+		return 1;
+	}
+
+	memcpy(pcr_digest.digest, digest, digest_length);
+
+	tcpa_event.PCRIndex = pcr;
+	tcpa_event.EventType = 5; // ACTION type for linux kernel.
+	tcpa_event.Digest = pcr_digest;
+	tcpa_event.EventSize = TPM_EVENT_DATA_SIZE;
+
+	memset(tcpa_event.Event, 0, TPM_EVENT_DATA_SIZE);
+	memcpy(tcpa_event.Event, name, strlen(name));
+
+	ce = cbmem_entry_find(CBMEM_ID_TCPA_LOG);
+	if (ce) {
+		lasa = cbmem_entry_start(ce);
+
+		ptr = (lasa + TCPA_LOG_CBEM_SIZE - 1);
+		size = sizeof(TPM_PCR_EVENT) * (*ptr);
+		if (size >= (TCPA_LOG_CBEM_SIZE - sizeof(TPM_PCR_EVENT))) {
+			printk(BIOS_ERR, "TCPA log is full\n");
+			return 1;
+		}
+
+		lasa += size;
+		*ptr += 1;
+	} else {
+		lasa = cbmem_add(CBMEM_ID_TCPA_LOG, TCPA_LOG_CBEM_SIZE);
+		if (!lasa) {
+			printk(BIOS_ERR, "TCPA log creation failed\n");
+			return 1;
+		}
+	}
+
+	memset(lasa, 0, TCPA_LOG_CBEM_SIZE);
+	ptr = (lasa + TCPA_LOG_CBEM_SIZE - 1);
+	*ptr += 1;
+
+	memcpy(lasa, &tcpa_event, sizeof(TPM_PCR_EVENT));
+
+	return 0;
+}
diff --git a/src/security/tpm/tss/tcg-1.2/tss_structures.h b/src/security/tpm/tss/tcg-1.2/tss_structures.h
index c06bbf7..37ff3b7 100644
--- a/src/security/tpm/tss/tcg-1.2/tss_structures.h
+++ b/src/security/tpm/tss/tcg-1.2/tss_structures.h
@@ -14,6 +14,9 @@
 #define TPM_LARGE_ENOUGH_COMMAND_SIZE 256  /* saves space in the firmware */
 #define TPM_PUBEK_SIZE 256
 #define TPM_PCR_DIGEST 20
+#define TPM_EVENT_DATA_SIZE 25
+#define MAX_EVENT_STRUCT_SIZE 100
+#define TCPA_LOG_CBEM_SIZE 2000
 
 #define TPM_E_NON_FATAL 0x800
 
@@ -64,6 +67,8 @@
 
 typedef uint8_t TSS_BOOL;
 typedef uint16_t TPM_STRUCTURE_TAG;
+typedef uint32_t TSS_EVENTTYPE;
+typedef uint32_t TSS_PCRINDEX;
 
 typedef struct tdTPM_PERMANENT_FLAGS {
 	TPM_STRUCTURE_TAG tag;
@@ -98,4 +103,16 @@
 	TSS_BOOL bGlobalLock;
 } TPM_STCLEAR_FLAGS;
 
+typedef struct tdTPM_DIGEST {
+	uint8_t	digest[TPM_PCR_DIGEST];
+} TPM_DIGEST;
+
+typedef struct tdTPM_PCR_EVENT {
+	TSS_PCRINDEX PCRIndex; //PCRIndex event extended to
+	TSS_EVENTTYPE EventType; //See Table 7-1, below
+	TPM_DIGEST Digest; //Value extended into PCRIndex
+	uint32_t EventSize; //Size of the event data
+	uint8_t Event[TPM_EVENT_DATA_SIZE]; //The event data
+} TPM_PCR_EVENT;
+
 #endif  /* TCG_TSS_STRUCTURES_H_ */
diff --git a/src/security/tpm/tss/tcg-2.0/tss.c b/src/security/tpm/tss/tcg-2.0/tss.c
index 0bee09b..d31028f 100644
--- a/src/security/tpm/tss/tcg-2.0/tss.c
+++ b/src/security/tpm/tss/tcg-2.0/tss.c
@@ -412,7 +412,7 @@
 }
 
 uint32_t tlcl_hash_complete(const void *message, uint32_t message_length,
-	uint8_t **digest)
+	uint8_t **digest, uint32_t *digest_length)
 {
 	return TPM_SUCCESS;
 }
@@ -421,3 +421,8 @@
 {
 	return TPM_SUCCESS;
 }
+
+uint32_t tlcl_tcpa_log(int pcr, const uint8_t *digest, const char *name)
+{
+	return TPM_SUCCESS;
+}

-- 
To view, visit https://review.coreboot.org/22867
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0a52494f647d21e2587231af26ed13d62b3a72f5
Gerrit-Change-Number: 22867
Gerrit-PatchSet: 1
Gerrit-Owner: Philipp Deppenwiese <zaolin.daisuki at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20171214/940ebf36/attachment.html>


More information about the coreboot-gerrit mailing list