aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2016-08-09 13:24:51 -0400
committerKevin O'Connor <kevin@koconnor.net>2016-08-11 10:42:32 -0400
commit19e8ea6312f3f60c34c2c20f95fb81306b320f74 (patch)
treedc2621386513a14d388c734021bee6b5b22f1dfb
parenta99de5c35df0419ed630437c31031e145351dbc8 (diff)
downloadseabios-19e8ea6312f3f60c34c2c20f95fb81306b320f74.tar.gz
seabios-19e8ea6312f3f60c34c2c20f95fb81306b320f74.tar.xz
seabios-19e8ea6312f3f60c34c2c20f95fb81306b320f74.zip
tpm: Append to TPM2 log the hashes used for PCR extension
Modify the function that writes the TPM logs to take the same digest passed to tpm_extend. Update the tpm2 acpi log header to describe the digest format. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/std/tcg.h24
-rw-r--r--src/tcgbios.c172
2 files changed, 103 insertions, 93 deletions
diff --git a/src/std/tcg.h b/src/std/tcg.h
index 401b20b..3234524 100644
--- a/src/std/tcg.h
+++ b/src/std/tcg.h
@@ -518,22 +518,20 @@ struct tpm2_digest_values {
struct tpm2_digest_value digest[0];
} PACKED;
+// Each entry in the TPM log contains: a tpm_log_header, a variable
+// length digest, a tpm_log_trailer, and a variable length event. The
+// 'digest' matches what is sent to the TPM hardware via the Extend
+// command. On TPM1.2 the digest is a SHA1 hash; on TPM2.0 the digest
+// contains a tpm2_digest_values struct followed by a variable number
+// of tpm2_digest_value structs (as specified by the hardware via the
+// TPM2_CAP_PCRS request).
struct tpm_log_header {
u32 pcrindex;
u32 eventtype;
u8 digest[0];
} PACKED;
-struct tpml_digest_values_sha1 {
- u32 count; /* number of digests */
- u16 hashtype;
- u8 sha1[SHA1_BUFSIZE];
-} PACKED;
-
-struct tcg_pcr_event2_sha1 {
- u32 pcrindex;
- u32 eventtype;
- struct tpml_digest_values_sha1 digest;
+struct tpm_log_trailer {
u32 eventdatasize;
u8 event[0];
} PACKED;
@@ -549,10 +547,12 @@ struct TCG_EfiSpecIdEventStruct {
struct TCG_EfiSpecIdEventAlgorithmSize {
u16 algorithmId;
u16 digestSize;
- } digestSizes[1];
+ } digestSizes[0];
+ /*
u8 vendorInfoSize;
u8 vendorInfo[0];
-};
+ */
+} PACKED;
#define TPM_TCPA_ACPI_CLASS_CLIENT 0
diff --git a/src/tcgbios.c b/src/tcgbios.c
index 57131d7..4cff4ce 100644
--- a/src/tcgbios.c
+++ b/src/tcgbios.c
@@ -137,15 +137,17 @@ tpm_tcpa_probe(void)
* Extend the ACPI log with the given entry by copying the
* entry data into the log.
* Input
- * pcpes : Pointer to the event 'header' to be copied into the log
- * event : Pointer to the event 'body' to be copied into the log
+ * entry : The header data to use (including the variable length digest)
+ * digest_len : Length of the digest in 'entry'
+ * event : Pointer to the event body to be copied into the log
+ * event_len : Length of 'event'
*
* Output:
* Returns an error code in case of faiure, 0 in case of success
*/
static int
-tpm_log_event(struct tcg_pcr_event2_sha1 *entry, const void *event
- , TPMVersion tpm_version)
+tpm_log_event(struct tpm_log_header *entry, int digest_len
+ , const void *event, int event_len)
{
dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n",
tpm_state.log_area_start_address, tpm_state.log_area_next_entry);
@@ -153,7 +155,8 @@ tpm_log_event(struct tcg_pcr_event2_sha1 *entry, const void *event
if (tpm_state.log_area_next_entry == NULL)
return -1;
- u32 size = sizeof(*entry) + entry->eventdatasize;
+ u32 size = (sizeof(*entry) + digest_len
+ + sizeof(struct tpm_log_trailer) + event_len);
u32 logsize = (tpm_state.log_area_next_entry + size
- tpm_state.log_area_start_address);
if (logsize > tpm_state.log_area_minimum_length) {
@@ -161,22 +164,11 @@ tpm_log_event(struct tcg_pcr_event2_sha1 *entry, const void *event
return -1;
}
- switch (tpm_version) {
- case TPM_VERSION_1_2: ;
- struct pcpes *pcpes = (void*)tpm_state.log_area_next_entry;
- pcpes->pcrindex = entry->pcrindex;
- pcpes->eventtype = entry->eventtype;
- memcpy(pcpes->digest, entry->digest.sha1, sizeof(pcpes->digest));
- pcpes->eventdatasize = entry->eventdatasize;
- memcpy(pcpes->event, event, entry->eventdatasize);
- size = sizeof(*pcpes) + entry->eventdatasize;
- break;
- case TPM_VERSION_2: ;
- struct tcg_pcr_event2_sha1 *e = (void*)tpm_state.log_area_next_entry;
- memcpy(e, entry, sizeof(*e));
- memcpy(e->event, event, entry->eventdatasize);
- break;
- }
+ void *dest = tpm_state.log_area_next_entry;
+ memcpy(dest, entry, sizeof(*entry) + digest_len);
+ struct tpm_log_trailer *t = dest + sizeof(*entry) + digest_len;
+ t->eventdatasize = event_len;
+ memcpy(t->event, event, event_len);
tpm_state.log_area_last_entry = tpm_state.log_area_next_entry;
tpm_state.log_area_next_entry += size;
@@ -185,41 +177,6 @@ tpm_log_event(struct tcg_pcr_event2_sha1 *entry, const void *event
return 0;
}
-/*
- * Initialize the log; a TPM2 log needs a special TPM 1.2 log entry
- * as the first entry serving identification purposes
- */
-static void
-tpm_log_init(void)
-{
- struct TCG_EfiSpecIdEventStruct event = {
- .signature = "Spec ID Event03",
- .platformClass = TPM_TCPA_ACPI_CLASS_CLIENT,
- .specVersionMinor = 0,
- .specVersionMajor = 2,
- .specErrata = 0,
- .uintnSize = 2,
- .numberOfAlgorithms = 1,
- .digestSizes[0] = {
- .algorithmId = TPM2_ALG_SHA1,
- .digestSize = SHA1_BUFSIZE,
- },
- .vendorInfoSize = 0,
- };
- struct tcg_pcr_event2_sha1 entry = {
- .eventtype = EV_NO_ACTION,
- .eventdatasize = sizeof(event),
- };
-
- switch (TPM_version) {
- case TPM_VERSION_1_2:
- break;
- case TPM_VERSION_2:
- /* write a 1.2 type of entry */
- tpm_log_event(&entry, &event, TPM_VERSION_1_2);
- }
-}
-
/****************************************************************
* Helper functions
@@ -276,6 +233,74 @@ tpm20_get_hash_buffersize(u16 hashAlg)
}
}
+// Add an entry at the start of the log describing digest formats
+static int
+tpm20_write_EfiSpecIdEventStruct(void)
+{
+ if (!tpm20_pcr_selection)
+ return -1;
+
+ struct {
+ struct TCG_EfiSpecIdEventStruct hdr;
+ u8 pad[256];
+ } event = {
+ .hdr.signature = "Spec ID Event03",
+ .hdr.platformClass = TPM_TCPA_ACPI_CLASS_CLIENT,
+ .hdr.specVersionMinor = 0,
+ .hdr.specVersionMajor = 2,
+ .hdr.specErrata = 0,
+ .hdr.uintnSize = 2,
+ };
+
+ struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections;
+ void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;
+
+ u32 count;
+ for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) {
+ u8 sizeOfSelect = sel->sizeOfSelect;
+
+ nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
+ if (nsel > end)
+ break;
+
+ int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg));
+ if (hsize < 0) {
+ dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n",
+ be16_to_cpu(sel->hashAlg));
+ return -1;
+ }
+
+ int event_size = offsetof(struct TCG_EfiSpecIdEventStruct
+ , digestSizes[count+1]);
+ if (event_size > sizeof(event) - sizeof(u32)) {
+ dprintf(DEBUG_tcg, "EfiSpecIdEventStruct pad too small\n");
+ return -1;
+ }
+
+ event.hdr.digestSizes[count].algorithmId = be16_to_cpu(sel->hashAlg);
+ event.hdr.digestSizes[count].digestSize = hsize;
+
+ sel = nsel;
+ }
+
+ if (sel != end) {
+ dprintf(DEBUG_tcg, "Malformed pcr selection structure fron TPM\n");
+ return -1;
+ }
+
+ event.hdr.numberOfAlgorithms = count;
+ int event_size = offsetof(struct TCG_EfiSpecIdEventStruct
+ , digestSizes[count]);
+ u32 *vendorInfoSize = (void*)&event + event_size;
+ *vendorInfoSize = 0;
+ event_size += sizeof(*vendorInfoSize);
+
+ struct tpm_log_entry le = {
+ .hdr.eventtype = EV_NO_ACTION,
+ };
+ return tpm_log_event(&le.hdr, SHA1_BUFSIZE, &event, event_size);
+}
+
/*
* Build the TPM2 tpm2_digest_values data structure from the given hash.
* Follow the PCR bank configuration of the TPM and write the same hash
@@ -677,22 +702,14 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type,
if (!tpm_is_working())
return;
- struct tcg_pcr_event2_sha1 entry = {
- .pcrindex = pcrindex,
- .eventtype = event_type,
- .eventdatasize = event_length,
- .digest = {
- .count = 1,
- .hashtype = TPM2_ALG_SHA1,
- }
- };
- sha1(hashdata, hashdata_length, entry.digest.sha1);
+ u8 hash[SHA1_BUFSIZE];
+ sha1(hashdata, hashdata_length, hash);
struct tpm_log_entry le = {
.hdr.pcrindex = pcrindex,
.hdr.eventtype = event_type,
};
- int digest_len = tpm_build_digest(&le, entry.digest.sha1);
+ int digest_len = tpm_build_digest(&le, hash);
if (digest_len < 0)
return;
int ret = tpm_extend(&le, digest_len);
@@ -700,7 +717,7 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type,
tpm_set_failure();
return;
}
- tpm_log_event(&entry, event, TPM_version);
+ tpm_log_event(&le.hdr, digest_len, event, event_length);
}
@@ -887,6 +904,10 @@ tpm20_startup(void)
if (ret)
goto err_exit;
+ ret = tpm20_write_EfiSpecIdEventStruct();
+ if (ret)
+ goto err_exit;
+
return 0;
err_exit:
@@ -926,8 +947,6 @@ tpm_setup(void)
if (ret)
return;
- tpm_log_init();
-
TPM_working = 1;
if (runningOnXen())
@@ -1238,17 +1257,8 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length
if (ret)
return TCG_TCG_COMMAND_ERROR;
}
- struct tcg_pcr_event2_sha1 entry = {
- .pcrindex = pcpes->pcrindex,
- .eventtype = pcpes->eventtype,
- .eventdatasize = pcpes->eventdatasize,
- .digest = {
- .count = 1,
- .hashtype = TPM2_ALG_SHA1,
- }
- };
- memcpy(entry.digest.sha1, pcpes->digest, sizeof(entry.digest.sha1));
- int ret = tpm_log_event(&entry, pcpes->event, TPM_version);
+ int ret = tpm_log_event(&le.hdr, digest_len
+ , pcpes->event, pcpes->eventdatasize);
if (ret)
return TCG_PC_LOGOVERFLOW;
return 0;