<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>