[SeaBIOS] [PATCH 2/2] tpm: Write logs in TPM 2 format

Kevin O'Connor kevin at koconnor.net
Sat Feb 6 19:35:55 CET 2016


Add support for the TPM 2 format of log messages.

Write the logs in the format that is appropriate for the version of
the host's TPM. For TPM 1.2 write it in the 'pcpes' structure's
format, for TPM 2 in the new TPM 2 format.

By using this method we can keep the API interface on systems with a
TPM 2 even though applications pass in the 'pcpes' structures
directly. The log will still be written in the appropriate format.

The TPM 2 log contains a TPM 1.2 type of entry of event type
EV_NO_ACTION and entry of type TCG_EfiSpeIdEventStruct as the first
entry. This is described in the EFI specification (section 5.3):

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/std/tcg.h | 35 +++++++++++++++++++++++++++
 src/tcgbios.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/src/std/tcg.h b/src/std/tcg.h
index dbb3a60..c59f671 100644
--- a/src/std/tcg.h
+++ b/src/std/tcg.h
@@ -91,6 +91,7 @@ enum irq_ids {
 
 /* event types: 10.4.1 / table 11 */
 #define EV_POST_CODE             1
+#define EV_NO_ACTION             3
 #define EV_SEPARATOR             4
 #define EV_ACTION                5
 #define EV_EVENT_TAG             6
@@ -474,4 +475,38 @@ struct tpm2_req_hierarchycontrol {
     u8 state;
 } PACKED;
 
+/* TPM 2 log entry */
+
+struct tpml_digest_values_sha1 {
+    u16 hashtype;
+    u8 sha1[SHA1_BUFSIZE];
+};
+
+struct tcg_pcr_event2_sha1 {
+    u32 pcrindex;
+    u32 eventtype;
+    u32 count; /* number of digests */
+    struct tpml_digest_values_sha1 digests[1];
+    u32 eventdatasize;
+    u8 event[0];
+} PACKED;
+
+struct TCG_EfiSpecIdEventStruct {
+    u8 signature[16];
+    u32 platformClass;
+    u8 specVersionMinor;
+    u8 specVersionMajor;
+    u8 specErrata;
+    u8 uintnSize;
+    u32 numberOfAlgorithms;
+    struct TCG_EfiSpecIdEventAlgorithmSize {
+        u16 algorithmId;
+        u16 digestSize;
+    } digestSizes[1];
+    u8 vendorInfoSize;
+    u8 vendorInfo[0];
+};
+
+#define TPM_TCPA_ACPI_CLASS_CLIENT 0
+
 #endif // tcg.h
diff --git a/src/tcgbios.c b/src/tcgbios.c
index cddc99b..f0ab188 100644
--- a/src/tcgbios.c
+++ b/src/tcgbios.c
@@ -141,7 +141,7 @@ tpm_tcpa_probe(void)
  *  Returns an error code in case of faiure, 0 in case of success
  */
 static int
-tpm_log_event(struct pcpes *pcpes, const void *event)
+tpm_log_event(struct tcg_pcr_event2_sha1 *entry, const void *event)
 {
     dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n",
             tpm_state.log_area_start_address, tpm_state.log_area_next_entry);
@@ -149,7 +149,7 @@ tpm_log_event(struct pcpes *pcpes, const void *event)
     if (tpm_state.log_area_next_entry == NULL)
         return -1;
 
-    u32 size = sizeof(*pcpes) + pcpes->eventdatasize;
+    u32 size = sizeof(*entry) + entry->eventdatasize;
 
     if ((tpm_state.log_area_next_entry + size - tpm_state.log_area_start_address) >
          tpm_state.log_area_minimum_length) {
@@ -157,9 +157,19 @@ tpm_log_event(struct pcpes *pcpes, const void *event)
         return -1;
     }
 
-    memcpy(tpm_state.log_area_next_entry, pcpes, sizeof(*pcpes));
-    memcpy(tpm_state.log_area_next_entry + sizeof(*pcpes),
-           event, pcpes->eventdatasize);
+    if (TPM_version == TPM_VERSION_1_2 || entry->eventtype == EV_NO_ACTION) {
+        struct pcpes *pcpes = (void*)tpm_state.log_area_next_entry;
+        pcpes->pcrindex = entry->pcrindex;
+        pcpes->eventtype = entry->eventtype;
+        memcpy(pcpes->digest, entry->digests[0].sha1, sizeof(pcpes->digest));
+        pcpes->eventdatasize = entry->eventdatasize;
+        memcpy(pcpes->event, event, entry->eventdatasize);
+        size = sizeof(*pcpes) + entry->eventdatasize;
+    } else {
+        struct tcg_pcr_event2_sha1 *e = (void*)tpm_state.log_area_next_entry;
+        memcpy(e, entry, sizeof(*e));
+        memcpy(e->event, event, entry->eventdatasize);
+    }
 
     tpm_state.log_area_last_entry = tpm_state.log_area_next_entry;
     tpm_state.log_area_next_entry += size;
@@ -168,6 +178,40 @@ tpm_log_event(struct pcpes *pcpes, 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
+ */
+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);
+    }
+}
+
 
 /****************************************************************
  * Helper functions
@@ -457,18 +501,20 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type,
     if (!tpm_is_working())
         return;
 
-    struct pcpes pcpes = {
+    struct tcg_pcr_event2_sha1 entry = {
         .pcrindex = pcrindex,
         .eventtype = event_type,
         .eventdatasize = event_length,
+        .count = 1,
+        .digests[0].hashtype  = TPM2_ALG_SHA1,
     };
-    sha1(hashdata, hashdata_length, pcpes.digest);
-    int ret = tpm_extend(pcpes.pcrindex, pcpes.digest);
+    sha1(hashdata, hashdata_length, entry.digests[0].sha1);
+    int ret = tpm_extend(entry.pcrindex, entry.digests[0].sha1);
     if (ret) {
         tpm_set_failure();
         return;
     }
-    tpm_log_event(&pcpes, event);
+    tpm_log_event(&entry, event);
 }
 
 
@@ -690,6 +736,8 @@ tpm_setup(void)
     if (ret)
         return;
 
+    tpm_log_init();
+
     TPM_working = 1;
 
     if (runningOnXen())
@@ -992,7 +1040,15 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length
         if (ret)
             return TCG_TCG_COMMAND_ERROR;
     }
-    int ret = tpm_log_event(pcpes, pcpes->event);
+    struct tcg_pcr_event2_sha1 entry = {
+        .pcrindex = pcpes->pcrindex,
+        .eventtype = pcpes->eventtype,
+        .eventdatasize = pcpes->eventdatasize,
+        .count = 1,
+        .digests[0].hashtype = TPM2_ALG_SHA1,
+    };
+    memcpy(entry.digests[0].sha1, pcpes->digest, sizeof(entry.digests[0].sha1));
+    int ret = tpm_log_event(&entry, pcpes->event);
     if (ret)
         return TCG_PC_LOGOVERFLOW;
     return 0;
-- 
2.5.0




More information about the SeaBIOS mailing list