Re: [tboot-devel] Add support for TPM2 TCG log format

2018-05-21 Thread Sun, Ning
Thanks for the patch, it was validated and merged…

Br.
-Ning

From: Sahil Rihan [mailto:sri...@fb.com]
Sent: Monday, May 14, 2018 3:37 PM
To: tboot-devel@lists.sourceforge.net
Subject: [tboot-devel] Add support for TPM2 TCG log format

Tboot didn’t have support for appending to a TPM2 TCG style event log. As a 
result it would crash with a “generic fatal error” when it ran with an SINIT 
that supports the TCG log format.

This change addresses that by adding code to handle the new log format.

Testing done: Verify tboot crashes on Skylake system without patch, and 
successfully boots kernel with the patch.

Signed-off-by: Sahil Rihan <sri...@fb.com<mailto:sri...@fb.com>>

diff -r 57c7d147daec -r 8bcaa41a5769 tboot/txt/txt.c
--- a/tboot/txt/txt.c   Fri May 04 17:10:58 2018 -0700
+++ b/tboot/txt/txt.c   Mon May 14 15:26:18 2018 -0700
@@ -69,6 +69,12 @@
/* counter timeout for waiting for all APs to enter wait-for-sipi */
#define AP_WFS_TIMEOUT 0x1000

+/* TPM event log types */
+#define EVTLOG_UNKNOWN   0
+#define EVTLOG_TPM12 1
+#define EVTLOG_TPM2_LEGACY   2
+#define EVTLOG_TPM2_TCG  3
+
__data struct acpi_rsdp g_rsdp;
extern char _start[]; /* start of module */
extern char _end[];   /* end of module */
@@ -87,6 +93,7 @@
extern void cpu_wakeup(uint32_t cpuid, uint32_t sipi_vec);
extern void print_event(const tpm12_pcr_event_t *evt);
extern void print_event_2(void *evt, uint16_t alg);
+extern uint32_t print_event_2_1(void *evt);


/*
@@ -282,6 +289,26 @@
 }
}

+int get_evtlog_type(void)
+{
+struct tpm_if *tpm = get_tpm();
+
+if (tpm->major == TPM12_VER_MAJOR) {
+return EVTLOG_TPM12;
+} else if (tpm->major == TPM20_VER_MAJOR) {
+if (g_sinit) {
+txt_caps_t sinit_caps = get_sinit_capabilities(g_sinit);
+return sinit_caps.tcg_event_log_format ? EVTLOG_TPM2_TCG : 
EVTLOG_TPM2_LEGACY;
+} else {
+printk(TBOOT_ERR"SINIT not found\n");
+}
+} else {
+printk(TBOOT_ERR"Unknown TPM major version: %d\n", tpm->major);
+}
+printk(TBOOT_ERR"Unable to determine log type\n");
+return EVTLOG_UNKNOWN;
+}
+
static void init_os_sinit_ext_data(heap_ext_data_element_t* elts)
{
 heap_ext_data_element_t* elt = elts;
@@ -391,7 +418,7 @@
 }
}

-bool evtlog_append_tpm20(uint8_t pcr, uint16_t alg, tb_hash_t *hash, uint32_t 
type)
+bool evtlog_append_tpm2_legacy(uint8_t pcr, uint16_t alg, tb_hash_t *hash, 
uint32_t type)
{
 heap_event_log_descr_t *cur_desc = NULL;
 uint32_t hash_size;
@@ -428,21 +455,79 @@
 return true;
}

+bool evtlog_append_tpm2_tcg(uint8_t pcr, uint32_t type, hash_list_t *hl)
+{
+uint32_t i, event_size;
+unsigned int hash_size;
+tcg_pcr_event2 *event;
+uint8_t *hash_entry;
+tcg_pcr_event2 dummy;
+
+/*
+ * Dont't use sizeof(tcg_pcr_event2) since that has 
TPML_DIGESTV_VALUES_1.digests
+ * set to 5. Compute the static size as pcr_index + event_type +
+ * digest.count + event_size. Then add the space taken up by the hashes.
+ */
+event_size = sizeof(dummy.pcr_index) + sizeof(dummy.event_type) +
+sizeof(dummy.digest.count) + sizeof(dummy.event_size);
+
+for (i = 0; i < hl->count; i++) {
+hash_size = get_hash_size(hl->entries[i].alg);
+if (hash_size == 0) {
+return false;
+}
+event_size += sizeof(uint16_t); // hash_alg field
+event_size += hash_size;
+}
+
+// Check if event will fit in buffer.
+if (event_size + g_elog_2_1->next_record_offset >
+g_elog_2_1->allcoated_event_container_size) {
+return false;
+}
+
+event = (tcg_pcr_event2*)(void *)(unsigned long)g_elog_2_1->phys_addr +
+g_elog_2_1->next_record_offset;
+event->pcr_index = pcr;
+event->event_type = type;
+event->event_size = 0;  // No event data passed by tboot.
+event->digest.count = hl->count;
+
+hash_entry = (uint8_t *)>digest.digests[0];
+for (i = 0; i < hl->count; i++) {
+// Populate individual TPMT_HA_1 structs.
+*((uint16_t *)hash_entry) = hl->entries[i].alg; // TPMT_HA_1.hash_alg
+hash_entry += sizeof(uint16_t);
+hash_size = get_hash_size(hl->entries[i].alg);  // already checked 
above
+memcpy(hash_entry, &(hl->entries[i].hash), hash_size);
+hash_entry += hash_size;
+}
+
+g_elog_2_1->next_record_offset += event_size;
+print_event_2_1(event);
+return true;
+}
+
+
bool evtlog_append(uint8_t pcr, hash_list_t *hl, uint32_t type)
{
-struct tpm_if *tpm = get_tpm();
-switch (tpm->major) {
-case TPM12_VER_MAJOR:
+int log_type = get_evtlog_type();
+switch (log_type) {
+case EVTLOG_TPM12:
 if ( !evtlog_append_tpm12(pcr, >entries[0].hash, type) )
 return 

[tboot-devel] Add support for TPM2 TCG log format

2018-05-14 Thread Sahil Rihan
Tboot didn’t have support for appending to a TPM2 TCG style event log. As a 
result it would crash with a “generic fatal error” when it ran with an SINIT 
that supports the TCG log format.

This change addresses that by adding code to handle the new log format.

Testing done: Verify tboot crashes on Skylake system without patch, and 
successfully boots kernel with the patch.

Signed-off-by: Sahil Rihan 

diff -r 57c7d147daec -r 8bcaa41a5769 tboot/txt/txt.c
--- a/tboot/txt/txt.c   Fri May 04 17:10:58 2018 -0700
+++ b/tboot/txt/txt.c   Mon May 14 15:26:18 2018 -0700
@@ -69,6 +69,12 @@
/* counter timeout for waiting for all APs to enter wait-for-sipi */
#define AP_WFS_TIMEOUT 0x1000

+/* TPM event log types */
+#define EVTLOG_UNKNOWN   0
+#define EVTLOG_TPM12 1
+#define EVTLOG_TPM2_LEGACY   2
+#define EVTLOG_TPM2_TCG  3
+
__data struct acpi_rsdp g_rsdp;
extern char _start[]; /* start of module */
extern char _end[];   /* end of module */
@@ -87,6 +93,7 @@
extern void cpu_wakeup(uint32_t cpuid, uint32_t sipi_vec);
extern void print_event(const tpm12_pcr_event_t *evt);
extern void print_event_2(void *evt, uint16_t alg);
+extern uint32_t print_event_2_1(void *evt);


/*
@@ -282,6 +289,26 @@
 }
}

+int get_evtlog_type(void)
+{
+struct tpm_if *tpm = get_tpm();
+
+if (tpm->major == TPM12_VER_MAJOR) {
+return EVTLOG_TPM12;
+} else if (tpm->major == TPM20_VER_MAJOR) {
+if (g_sinit) {
+txt_caps_t sinit_caps = get_sinit_capabilities(g_sinit);
+return sinit_caps.tcg_event_log_format ? EVTLOG_TPM2_TCG : 
EVTLOG_TPM2_LEGACY;
+} else {
+printk(TBOOT_ERR"SINIT not found\n");
+}
+} else {
+printk(TBOOT_ERR"Unknown TPM major version: %d\n", tpm->major);
+}
+printk(TBOOT_ERR"Unable to determine log type\n");
+return EVTLOG_UNKNOWN;
+}
+
static void init_os_sinit_ext_data(heap_ext_data_element_t* elts)
{
 heap_ext_data_element_t* elt = elts;
@@ -391,7 +418,7 @@
 }
}

-bool evtlog_append_tpm20(uint8_t pcr, uint16_t alg, tb_hash_t *hash, uint32_t 
type)
+bool evtlog_append_tpm2_legacy(uint8_t pcr, uint16_t alg, tb_hash_t *hash, 
uint32_t type)
{
 heap_event_log_descr_t *cur_desc = NULL;
 uint32_t hash_size;
@@ -428,21 +455,79 @@
 return true;
}

+bool evtlog_append_tpm2_tcg(uint8_t pcr, uint32_t type, hash_list_t *hl)
+{
+uint32_t i, event_size;
+unsigned int hash_size;
+tcg_pcr_event2 *event;
+uint8_t *hash_entry;
+tcg_pcr_event2 dummy;
+
+/*
+ * Dont't use sizeof(tcg_pcr_event2) since that has 
TPML_DIGESTV_VALUES_1.digests
+ * set to 5. Compute the static size as pcr_index + event_type +
+ * digest.count + event_size. Then add the space taken up by the hashes.
+ */
+event_size = sizeof(dummy.pcr_index) + sizeof(dummy.event_type) +
+sizeof(dummy.digest.count) + sizeof(dummy.event_size);
+
+for (i = 0; i < hl->count; i++) {
+hash_size = get_hash_size(hl->entries[i].alg);
+if (hash_size == 0) {
+return false;
+}
+event_size += sizeof(uint16_t); // hash_alg field
+event_size += hash_size;
+}
+
+// Check if event will fit in buffer.
+if (event_size + g_elog_2_1->next_record_offset >
+g_elog_2_1->allcoated_event_container_size) {
+return false;
+}
+
+event = (tcg_pcr_event2*)(void *)(unsigned long)g_elog_2_1->phys_addr +
+g_elog_2_1->next_record_offset;
+event->pcr_index = pcr;
+event->event_type = type;
+event->event_size = 0;  // No event data passed by tboot.
+event->digest.count = hl->count;
+
+hash_entry = (uint8_t *)>digest.digests[0];
+for (i = 0; i < hl->count; i++) {
+// Populate individual TPMT_HA_1 structs.
+*((uint16_t *)hash_entry) = hl->entries[i].alg; // TPMT_HA_1.hash_alg
+hash_entry += sizeof(uint16_t);
+hash_size = get_hash_size(hl->entries[i].alg);  // already checked 
above
+memcpy(hash_entry, &(hl->entries[i].hash), hash_size);
+hash_entry += hash_size;
+}
+
+g_elog_2_1->next_record_offset += event_size;
+print_event_2_1(event);
+return true;
+}
+
+
bool evtlog_append(uint8_t pcr, hash_list_t *hl, uint32_t type)
{
-struct tpm_if *tpm = get_tpm();
-switch (tpm->major) {
-case TPM12_VER_MAJOR:
+int log_type = get_evtlog_type();
+switch (log_type) {
+case EVTLOG_TPM12:
 if ( !evtlog_append_tpm12(pcr, >entries[0].hash, type) )
 return false;
 break;
-case TPM20_VER_MAJOR:
+case EVTLOG_TPM2_LEGACY:
 for (unsigned int i=0; icount; i++) {
-if ( !evtlog_append_tpm20(pcr, hl->entries[i].alg,
+if ( !evtlog_append_tpm2_legacy(pcr, hl->entries[i].alg,
 >entries[i].hash, type))
 return false;
}
 break;
+case EVTLOG_TPM2_TCG:
+  if (