From 26203e729251816f8a98814112730daf61492a3e Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 10 Nov 2022 17:56:26 +0200 Subject: [PATCH] security/tpm: make tspi/crtm.c agnostic to log format Change-Id: I3013bd5f29f1412fbe646dc74d8946704b750a66 Ticket: https://ticket.coreboot.org/issues/423 Signed-off-by: Sergii Dmytruk Reviewed-on: https://review.coreboot.org/c/coreboot/+/69445 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- .../include/commonlib/tpm_log_serialized.h | 3 - src/security/tpm/tspi.h | 27 ++++- src/security/tpm/tspi/crtm.c | 78 +++++++++++---- src/security/tpm/tspi/log.c | 98 +++++++++---------- 4 files changed, 134 insertions(+), 72 deletions(-) diff --git a/src/commonlib/include/commonlib/tpm_log_serialized.h b/src/commonlib/include/commonlib/tpm_log_serialized.h index dc58dc09c3..8372f94dab 100644 --- a/src/commonlib/include/commonlib/tpm_log_serialized.h +++ b/src/commonlib/include/commonlib/tpm_log_serialized.h @@ -6,12 +6,9 @@ #include #include -#define MAX_TPM_LOG_ENTRIES 50 #define TPM_CB_LOG_DIGEST_MAX_LENGTH 64 #define TPM_CB_LOG_PCR_HASH_NAME 50 #define TPM_CB_LOG_PCR_HASH_LEN 10 -/* Assumption of 2K TCPA log size reserved for CAR/SRAM */ -#define MAX_PRERAM_TPM_LOG_ENTRIES 15 struct tpm_cb_log_entry { uint32_t pcr; diff --git a/src/security/tpm/tspi.h b/src/security/tpm/tspi.h index aee38aa902..b081439c44 100644 --- a/src/security/tpm/tspi.h +++ b/src/security/tpm/tspi.h @@ -10,12 +10,21 @@ #define TPM_PCR_MAX_LEN 64 #define HASH_DATA_CHUNK_SIZE 1024 +#define MAX_TPM_LOG_ENTRIES 50 +/* Assumption of 2K TCPA log size reserved for CAR/SRAM */ +#define MAX_PRERAM_TPM_LOG_ENTRIES 15 /** * Get the pointer to the single instance of global * TPM log data, and initialize it when necessary */ -struct tpm_cb_log_table *tpm_log_init(void); +void *tpm_log_init(void); + +/** + * Get the pointer to the single CBMEM instance of global + * TPM log data, and initialize it when necessary + */ +void *tpm_log_cbmem_init(void); /** * Clears the pre-RAM TPM log data and initializes @@ -23,6 +32,22 @@ struct tpm_cb_log_table *tpm_log_init(void); */ void tpm_preram_log_clear(void); +/** + * Retrieves number of entries currently stored in the log. + */ +uint16_t tpm_log_get_size(const void *log_table); + +/** + * Copies data from pre-RAM TPM log to CBMEM (RAM) log + */ +void tpm_log_copy_entries(const void *from, void *to); + +/** + * Retrieves an entry from a log. Returns non-zero on invalid index or error. + */ +int tpm_log_get(int entry_idx, int *pcr, const uint8_t **digest_data, + enum vb2_hash_algorithm *digest_algo, const char **event_name); + /** * Add table entry for cbmem TPM log. * @param name Name of the hashed data diff --git a/src/security/tpm/tspi/crtm.c b/src/security/tpm/tspi/crtm.c index 6e4fadad2b..a7efcf2145 100644 --- a/src/security/tpm/tspi/crtm.c +++ b/src/security/tpm/tspi/crtm.c @@ -2,7 +2,9 @@ #include #include +#include #include +#include #include "crtm.h" #include @@ -148,39 +150,79 @@ uint32_t tspi_cbfs_measurement(const char *name, uint32_t type, const struct vb2 tpm_log_metadata); } +void *tpm_log_init(void) +{ + static void *tclt; + + /* We are dealing here with pre CBMEM environment. + * If cbmem isn't available use CAR or SRAM */ + if (!cbmem_possibly_online() && + !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)) + return _tpm_log; + else if (ENV_CREATES_CBMEM + && !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)) { + tclt = tpm_log_cbmem_init(); + if (!tclt) + return _tpm_log; + } else { + tclt = tpm_log_cbmem_init(); + } + + return tclt; +} + int tspi_measure_cache_to_pcr(void) { int i; - struct tpm_cb_log_table *tclt = tpm_log_init(); + int pcr; + const char *event_name; + const uint8_t *digest_data; + enum vb2_hash_algorithm digest_algo; /* This means the table is empty. */ if (!tpm_log_available()) return VB2_SUCCESS; - if (!tclt) { + if (tpm_log_init() == NULL) { printk(BIOS_WARNING, "TPM LOG: log non-existent!\n"); return VB2_ERROR_UNKNOWN; } printk(BIOS_DEBUG, "TPM: Write digests cached in TPM log to PCR\n"); - for (i = 0; i < tclt->num_entries; i++) { - struct tpm_cb_log_entry *tce = &tclt->entries[i]; - if (tce) { - printk(BIOS_DEBUG, "TPM: Write digest for" - " %s into PCR %d\n", - tce->name, tce->pcr); - int result = tlcl_extend(tce->pcr, - tce->digest, - TPM_MEASURE_ALGO); - if (result != TPM_SUCCESS) { - printk(BIOS_ERR, "TPM: Writing digest" - " of %s into PCR failed with error" - " %d\n", - tce->name, result); - return VB2_ERROR_UNKNOWN; - } + i = 0; + while (!tpm_log_get(i++, &pcr, &digest_data, &digest_algo, &event_name)) { + printk(BIOS_DEBUG, "TPM: Write digest for %s into PCR %d\n", event_name, pcr); + int result = tlcl_extend(pcr, digest_data, digest_algo); + if (result != TPM_SUCCESS) { + printk(BIOS_ERR, + "TPM: Writing digest of %s into PCR failed with error %d\n", + event_name, result); + return VB2_ERROR_UNKNOWN; } } return VB2_SUCCESS; } + +#if !CONFIG(VBOOT_RETURN_FROM_VERSTAGE) +static void recover_tpm_log(int is_recovery) +{ + const void *preram_log = _tpm_log; + void *ram_log = tpm_log_cbmem_init(); + + if (tpm_log_get_size(preram_log) > MAX_PRERAM_TPM_LOG_ENTRIES) { + printk(BIOS_WARNING, "TPM LOG: pre-RAM log is too full, possible corruption\n"); + return; + } + + if (ram_log == NULL) { + printk(BIOS_WARNING, "TPM LOG: CBMEM not available, something went wrong\n"); + return; + } + + tpm_log_copy_entries(_tpm_log, ram_log); +} +CBMEM_CREATION_HOOK(recover_tpm_log); +#endif + +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, tpm_log_dump, NULL); diff --git a/src/security/tpm/tspi/log.c b/src/security/tpm/tspi/log.c index fa95b80e81..96c3087f95 100644 --- a/src/security/tpm/tspi/log.c +++ b/src/security/tpm/tspi/log.c @@ -6,10 +6,9 @@ #include #include #include -#include #include -static struct tpm_cb_log_table *tpm_log_cbmem_init(void) +void *tpm_log_cbmem_init(void) { static struct tpm_cb_log_table *tclt; if (tclt) @@ -30,27 +29,6 @@ static struct tpm_cb_log_table *tpm_log_cbmem_init(void) return tclt; } -struct tpm_cb_log_table *tpm_log_init(void) -{ - static struct tpm_cb_log_table *tclt; - - /* We are dealing here with pre CBMEM environment. - * If cbmem isn't available use CAR or SRAM */ - if (!cbmem_possibly_online() && - !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)) - return (struct tpm_cb_log_table *)_tpm_log; - else if (ENV_CREATES_CBMEM - && !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)) { - tclt = tpm_log_cbmem_init(); - if (!tclt) - return (struct tpm_cb_log_table *)_tpm_log; - } else { - tclt = tpm_log_cbmem_init(); - } - - return tclt; -} - void tpm_log_dump(void *unused) { int i, j; @@ -121,42 +99,62 @@ void tpm_preram_log_clear(void) tclt->num_entries = 0; } -#if !CONFIG(VBOOT_RETURN_FROM_VERSTAGE) -static void recover_tpm_log(int is_recovery) +int tpm_log_get(int entry_idx, int *pcr, const uint8_t **digest_data, + enum vb2_hash_algorithm *digest_algo, const char **event_name) { - struct tpm_cb_log_table *preram_log = (struct tpm_cb_log_table *)_tpm_log; - struct tpm_cb_log_table *ram_log = NULL; + struct tpm_cb_log_table *tclt; + struct tpm_cb_log_entry *tce; + enum vb2_hash_algorithm algo; + + tclt = tpm_log_init(); + if (!tclt) + return 1; + + if (entry_idx < 0 || entry_idx >= tclt->num_entries) + return 1; + + tce = &tclt->entries[entry_idx]; + + *pcr = tce->pcr; + *digest_data = tce->digest; + *event_name = tce->name; + + *digest_algo = VB2_HASH_INVALID; + for (algo = VB2_HASH_INVALID; algo != VB2_HASH_ALG_COUNT; ++algo) { + if (strcmp(tce->digest_type, vb2_hash_names[algo]) == 0) { + *digest_algo = algo; + break; + } + } + return 0; +} + +uint16_t tpm_log_get_size(const void *log_table) +{ + const struct tpm_cb_log_table *tclt = log_table; + return tclt->num_entries; +} + +void tpm_log_copy_entries(const void *from, void *to) +{ + const struct tpm_cb_log_table *from_log = from; + struct tpm_cb_log_table *to_log = to; int i; - if (preram_log->num_entries > MAX_PRERAM_TPM_LOG_ENTRIES) { - printk(BIOS_WARNING, "TPM LOG: pre-RAM log is too full, possible corruption\n"); - return; - } + for (i = 0; i < from_log->num_entries; i++) { + struct tpm_cb_log_entry *tce = &to_log->entries[to_log->num_entries++]; + strncpy(tce->name, from_log->entries[i].name, TPM_CB_LOG_PCR_HASH_NAME - 1); + tce->pcr = from_log->entries[i].pcr; - ram_log = tpm_log_cbmem_init(); - if (!ram_log) { - printk(BIOS_WARNING, "TPM LOG: CBMEM not available something went wrong\n"); - return; - } - - for (i = 0; i < preram_log->num_entries; i++) { - struct tpm_cb_log_entry *tce = &ram_log->entries[ram_log->num_entries++]; - strncpy(tce->name, preram_log->entries[i].name, TPM_CB_LOG_PCR_HASH_NAME - 1); - tce->pcr = preram_log->entries[i].pcr; - - if (preram_log->entries[i].digest_length > TPM_CB_LOG_DIGEST_MAX_LENGTH) { + if (from_log->entries[i].digest_length > TPM_CB_LOG_DIGEST_MAX_LENGTH) { printk(BIOS_WARNING, "TPM LOG: PCR digest too long for log entry\n"); return; } - strncpy(tce->digest_type, preram_log->entries[i].digest_type, + strncpy(tce->digest_type, from_log->entries[i].digest_type, TPM_CB_LOG_PCR_HASH_LEN - 1); - tce->digest_length = MIN(preram_log->entries[i].digest_length, + tce->digest_length = MIN(from_log->entries[i].digest_length, TPM_CB_LOG_DIGEST_MAX_LENGTH); - memcpy(tce->digest, preram_log->entries[i].digest, tce->digest_length); + memcpy(tce->digest, from_log->entries[i].digest, tce->digest_length); } } -CBMEM_CREATION_HOOK(recover_tpm_log); -#endif - -BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, tpm_log_dump, NULL);