Philipp Deppenwiese has uploaded this change for review. ( https://review.coreboot.org/29563
Change subject: security/tpm: Fix TCPA log feature ......................................................................
security/tpm: Fix TCPA log feature
* Refactor TCPA log code * Add TCPA log dump fucntion * Make TCPA log available in bootblock * Fix TCPA log formatting
Change-Id: Ic93133531b84318f48940d34bded48cbae739c44 Signed-off-by: Philipp Deppenwiese zaolin.daisuki@gmail.com --- M src/arch/x86/car.ld M src/commonlib/include/commonlib/tcpa_log_serialized.h M src/include/memlayout.h M src/security/tpm/tspi.h M src/security/tpm/tspi/log.c M src/security/vboot/Kconfig M src/security/vboot/symbols.h M src/security/vboot/vboot_crtm.c M src/soc/cavium/cn81xx/include/soc/memlayout.ld M util/cbmem/cbmem.c 10 files changed, 111 insertions(+), 42 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/63/29563/1
diff --git a/src/arch/x86/car.ld b/src/arch/x86/car.ld index 33fb5c9..ea1c5f1 100644 --- a/src/arch/x86/car.ld +++ b/src/arch/x86/car.ld @@ -31,6 +31,12 @@ #if IS_ENABLED(CONFIG_VBOOT_SEPARATE_VERSTAGE) VBOOT2_WORK(., 16K) #endif + /* Vboot measured boot TCPA log measurements + * Needs to be transfered until CBMEM is available + */ +#if IS_ENABLED(CONFIG_VBOOT_TCPA_LOG_RECOVERY) + VBOOT2_TPM_LOG(., 2K) +#endif /* Stack for CAR stages. Since it persists across all stages that * use CAR it can be reused. The chipset/SoC is expected to provide * the stack size. */ diff --git a/src/commonlib/include/commonlib/tcpa_log_serialized.h b/src/commonlib/include/commonlib/tcpa_log_serialized.h index 1e9ffaa..f5ebfb1 100644 --- a/src/commonlib/include/commonlib/tcpa_log_serialized.h +++ b/src/commonlib/include/commonlib/tcpa_log_serialized.h @@ -18,11 +18,12 @@
#include <stdint.h>
+#define MAX_PREMEM_TCPA_LOG_ENTRIES 14 #define MAX_TCPA_LOG_ENTRIES 50 -#define TCPA_LOG_STRING_LENGTH 512 +#define TCPA_LOG_STRING_LENGTH 256 #define TCPA_FORMAT_HASH_LENGTH 128 #define TCPA_DIGEST_MAX_LENGTH 64 -#define TCPA_PCR_HASH_NAME 256 +#define TCPA_PCR_HASH_NAME 64
struct tcpa_entry { uint32_t pcr; diff --git a/src/include/memlayout.h b/src/include/memlayout.h index 5de2370..ba6644f 100644 --- a/src/include/memlayout.h +++ b/src/include/memlayout.h @@ -165,6 +165,10 @@ REGION(vboot2_work, addr, size, 16) \ _ = ASSERT(size >= 12K, "vboot2 work buffer must be at least 12K!");
+#define VBOOT2_TPM_LOG(addr, size) \ + REGION(vboot2_tpm_log, addr, size, 2) \ + _ = ASSERT(size >= 2K, "vboot2 tpm log buffer must be at least 2K!"); + #if ENV_VERSTAGE #define VERSTAGE(addr, sz) \ SYMBOL(verstage, addr) \ diff --git a/src/security/tpm/tspi.h b/src/security/tpm/tspi.h index d69b976..99a7e1d 100644 --- a/src/security/tpm/tspi.h +++ b/src/security/tpm/tspi.h @@ -33,6 +33,11 @@ const size_t digest_length);
/** + * Dump TCPA log entries on console + */ +void tcpa_log_dump(void); + +/** * Ask vboot for a digest and extend a TPM PCR with it. * @param pcr sets the pcr index * @param digest sets the hash to extend into the tpm diff --git a/src/security/tpm/tspi/log.c b/src/security/tpm/tspi/log.c index 17f6f1f..33486a5 100644 --- a/src/security/tpm/tspi/log.c +++ b/src/security/tpm/tspi/log.c @@ -14,67 +14,92 @@ */
#include <string.h> -#include <cbmem.h> #include <console/console.h> #include <security/tpm/tspi.h> +#include <arch/early_variables.h> +#include <fmap.h> +#include <region_file.h> +#include <string.h> +#include <cbmem.h> +#include <security/vboot/symbols.h>
static struct tcpa_table *tcpa_log_init(void) { - MAYBE_STATIC struct tcpa_table *tclt = NULL; + struct tcpa_table *tclt;
- if (!cbmem_possibly_online()) - return NULL; + if (!cbmem_possibly_online()) { + tclt = (struct tcpa_table*)_vboot2_tpm_log; + tclt->max_entries = MAX_PREMEM_TCPA_LOG_ENTRIES; + tclt->num_entries = 0; + } else { + tclt = cbmem_find(CBMEM_ID_TCPA_LOG); + if (!tclt) { + tclt = cbmem_add(CBMEM_ID_TCPA_LOG, + sizeof(struct tcpa_table) + + MAX_TCPA_LOG_ENTRIES * + sizeof(struct tcpa_entry));
- if (tclt != NULL) - return tclt; - - tclt = (struct tcpa_table *) cbmem_entry_find(CBMEM_ID_TCPA_LOG); - if (tclt) - return tclt; - - tclt = cbmem_add(CBMEM_ID_TCPA_LOG, - sizeof(struct tcpa_table) + - MAX_TCPA_LOG_ENTRIES * - sizeof(struct tcpa_entry)); - - if (!tclt) { - printk(BIOS_ERR, "ERROR: Could not create TCPA log table\n"); - return NULL; + tclt->max_entries = MAX_TCPA_LOG_ENTRIES; + tclt->num_entries = 0; + } }
- tclt->max_entries = MAX_TCPA_LOG_ENTRIES; - tclt->num_entries = 0; - - printk(BIOS_DEBUG, "TCPA log created at %p\n", tclt); - + printk(BIOS_DEBUG, "TPM: TCPA log created at %p\n", tclt); return tclt; }
+void tcpa_log_dump(void) +{ + int i, j; + char log_string[TCPA_LOG_STRING_LENGTH]; + char hash[TCPA_FORMAT_HASH_LENGTH]; + struct tcpa_table *tclt; + + tclt = tcpa_log_init(); + if (!tclt) + return; + + printk(BIOS_INFO, "coreboot TCPA log:\n"); + for (i = 0; i < tclt->num_entries; i++) { + struct tcpa_entry *tce = &tclt->entries[i]; + if (tce) { + memset(log_string, 0, TCPA_LOG_STRING_LENGTH); + memset(hash, 0, TCPA_LOG_STRING_LENGTH); + + for (j = 0; j < tce->digest_length; j++) + snprintf((char *)&(hash[j * 2]), tce->digest_length, "%02x", tce->digest[j]); + + snprintf(log_string, TCPA_LOG_STRING_LENGTH, " %u %s 00 [%s]\n", + tce->pcr, hash, tce->name); + printk(BIOS_INFO, "%s", log_string); + } + } +} + void tcpa_log_add_table_entry(const char *name, const uint32_t pcr, const uint8_t *digest, const size_t digest_length) { - struct tcpa_table *tclt; - struct tcpa_entry *tce; - - tclt = tcpa_log_init(); - + struct tcpa_table *tclt = tcpa_log_init(); if (!tclt) return;
- if (tclt->num_entries == tclt->max_entries) { - printk(BIOS_WARNING, "ERROR: TCPA log table is full\n"); + if (tclt->num_entries >= tclt->max_entries) { + printk(BIOS_WARNING, "TPM: TCPA log table is full\n"); return; }
- tce = &tclt->entries[tclt->num_entries++]; + struct tcpa_entry *tce = &tclt->entries[tclt->num_entries++]; + if (tce) { + strncpy(tce->name, name, TCPA_PCR_HASH_NAME - 1); + tce->pcr = pcr;
- strncpy(tce->name, name, TCPA_PCR_HASH_NAME - 1); - tce->pcr = pcr; + if (digest_length > TCPA_DIGEST_MAX_LENGTH) { + printk(BIOS_WARNING, "TPM: PCR digest too long for TCPA log entry\n"); + return; + }
- if (digest_length > TCPA_DIGEST_MAX_LENGTH) { - printk(BIOS_WARNING, "ERROR: PCR digest too long for TCPA log entry\n"); + memcpy(tce->digest, digest, digest_length); + tce->digest_length = digest_length; return; } - memcpy(tce->digest, digest, digest_length); - tce->digest_length = digest_length; } diff --git a/src/security/vboot/Kconfig b/src/security/vboot/Kconfig index e7cb43a..fd69114 100644 --- a/src/security/vboot/Kconfig +++ b/src/security/vboot/Kconfig @@ -241,6 +241,13 @@ Add a space delimited list of filenames that should only be in the RO section.
+config VBOOT_TCPA_LOG_RECOVERY + bool + default y + help + Enables TCPA log measurements recovery from bootblock to + romstage. + menu "GBB configuration"
config GBB_HWID diff --git a/src/security/vboot/symbols.h b/src/security/vboot/symbols.h index ddf9d95..92cbeea 100644 --- a/src/security/vboot/symbols.h +++ b/src/security/vboot/symbols.h @@ -20,4 +20,6 @@ extern u8 _evboot2_work[]; #define _vboot2_work_size (_evboot2_work - _vboot2_work)
+extern u8 _vboot2_tpm_log[]; + #endif /* __VBOOT_SYMBOLS_H__ */ diff --git a/src/security/vboot/vboot_crtm.c b/src/security/vboot/vboot_crtm.c index 5b76aa8..b71fce8 100644 --- a/src/security/vboot/vboot_crtm.c +++ b/src/security/vboot/vboot_crtm.c @@ -18,7 +18,9 @@ #include <fmap.h> #include <security/tpm/tspi.h> #include <security/vboot/vboot_crtm.h> +#include <security/vboot/symbols.h> #include <program_loading.h> +#include <cbmem.h>
uint32_t vboot_init_crtm(void) { @@ -132,6 +134,8 @@ case PROG_PAYLOAD: tpm_measure_region(prog_rdev(prog), TPM_PAYLOAD_PCR, prog->name); + /* Last measurement, afterwards dump completed log */ + tcpa_log_dump(); break; case PROG_REFCODE: tpm_measure_region(prog_rdev(prog), TPM_INTEL_FSP_PCR, @@ -152,3 +156,15 @@ break; } } + +static void recover_tcpa_log(int is_recovery) +{ + const struct tcpa_table *tclt = (struct tcpa_table*)_vboot2_tpm_log; + if (tclt) { + int i; + for (i = 0; i < tclt->num_entries; i++) { + tcpa_log_add_table_entry(tclt->entries[i].name, tclt->entries[i].pcr, tclt->entries[i].digest, tclt->entries[i].digest_length); + } + } +} +ROMSTAGE_CBMEM_INIT_HOOK(recover_tcpa_log); diff --git a/src/soc/cavium/cn81xx/include/soc/memlayout.ld b/src/soc/cavium/cn81xx/include/soc/memlayout.ld index e3bf61f..0562ed6 100644 --- a/src/soc/cavium/cn81xx/include/soc/memlayout.ld +++ b/src/soc/cavium/cn81xx/include/soc/memlayout.ld @@ -35,7 +35,10 @@ PRERAM_CBMEM_CONSOLE(BOOTROM_OFFSET + 0x8000, 8K) BOOTBLOCK(BOOTROM_OFFSET + 0x20000, 64K) VBOOT2_WORK(BOOTROM_OFFSET + 0x30000, 12K) - VERSTAGE(BOOTROM_OFFSET + 0x33000, 52K) +#if IS_ENABLED(CONFIG_VBOOT_TCPA_LOG_RECOVERY) + VBOOT2_TPM_LOG(BOOTROM_OFFSET + 0x33000, 2K) +#endif + VERSTAGE(BOOTROM_OFFSET + 0x34000, 50K) ROMSTAGE(BOOTROM_OFFSET + 0x40000, 256K)
SRAM_END(BOOTROM_OFFSET + 0x80000) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index 8ab80b0..79852da 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -720,7 +720,7 @@ for (j = 0; j < tce->digest_length; j++) sprintf((char *)&(hash[j * 2]), "%02x", tce->digest[j]);
- snprintf(log_string, TCPA_LOG_STRING_LENGTH, "%u %s 00 [%s]\n", + snprintf(log_string, TCPA_LOG_STRING_LENGTH, " %u %s 00 [%s]\n", tce->pcr, hash, tce->name); printf("%s", log_string); }