[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