Attention is currently required from: Christian Walter.
Sergii Dmytruk has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/69445 )
Change subject: security/tpm: make tspi/crtm.c agnostic to log format ......................................................................
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 sergii.dmytruk@3mdeb.com --- M src/commonlib/include/commonlib/tpm_log_serialized.h M src/security/tpm/tspi.h M src/security/tpm/tspi/crtm.c M src/security/tpm/tspi/log.c 4 files changed, 145 insertions(+), 72 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/45/69445/1
diff --git a/src/commonlib/include/commonlib/tpm_log_serialized.h b/src/commonlib/include/commonlib/tpm_log_serialized.h index dc58dc0..8372f94 100644 --- a/src/commonlib/include/commonlib/tpm_log_serialized.h +++ b/src/commonlib/include/commonlib/tpm_log_serialized.h @@ -6,12 +6,9 @@ #include <commonlib/bsd/helpers.h> #include <stdint.h>
-#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 865c3f4..00a7326 100644 --- a/src/security/tpm/tspi.h +++ b/src/security/tpm/tspi.h @@ -11,12 +11,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 @@ -25,6 +34,22 @@ 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 * @param pcr PCR used to extend hashed data diff --git a/src/security/tpm/tspi/crtm.c b/src/security/tpm/tspi/crtm.c index 6e4fada..a7efcf2 100644 --- a/src/security/tpm/tspi/crtm.c +++ b/src/security/tpm/tspi/crtm.c @@ -2,7 +2,9 @@
#include <console/console.h> #include <fmap.h> +#include <bootstate.h> #include <cbfs.h> +#include <symbols.h> #include "crtm.h" #include <string.h>
@@ -148,39 +150,79 @@ 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 fa95b80..96c3087 100644 --- a/src/security/tpm/tspi/log.c +++ b/src/security/tpm/tspi/log.c @@ -6,10 +6,9 @@ #include <string.h> #include <symbols.h> #include <cbmem.h> -#include <bootstate.h> #include <vb2_sha.h>
-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 @@ 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 @@ 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);