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