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> Reviewed-on: https://review.coreboot.org/c/coreboot/+/69445 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
2710df765b
commit
26203e7292
|
@ -6,12 +6,9 @@
|
||||||
#include <commonlib/bsd/helpers.h>
|
#include <commonlib/bsd/helpers.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define MAX_TPM_LOG_ENTRIES 50
|
|
||||||
#define TPM_CB_LOG_DIGEST_MAX_LENGTH 64
|
#define TPM_CB_LOG_DIGEST_MAX_LENGTH 64
|
||||||
#define TPM_CB_LOG_PCR_HASH_NAME 50
|
#define TPM_CB_LOG_PCR_HASH_NAME 50
|
||||||
#define TPM_CB_LOG_PCR_HASH_LEN 10
|
#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 {
|
struct tpm_cb_log_entry {
|
||||||
uint32_t pcr;
|
uint32_t pcr;
|
||||||
|
|
|
@ -10,12 +10,21 @@
|
||||||
|
|
||||||
#define TPM_PCR_MAX_LEN 64
|
#define TPM_PCR_MAX_LEN 64
|
||||||
#define HASH_DATA_CHUNK_SIZE 1024
|
#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
|
* Get the pointer to the single instance of global
|
||||||
* TPM log data, and initialize it when necessary
|
* 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
|
* 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);
|
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.
|
* Add table entry for cbmem TPM log.
|
||||||
* @param name Name of the hashed data
|
* @param name Name of the hashed data
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <fmap.h>
|
#include <fmap.h>
|
||||||
|
#include <bootstate.h>
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
|
#include <symbols.h>
|
||||||
#include "crtm.h"
|
#include "crtm.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -148,39 +150,79 @@ uint32_t tspi_cbfs_measurement(const char *name, uint32_t type, const struct vb2
|
||||||
tpm_log_metadata);
|
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 tspi_measure_cache_to_pcr(void)
|
||||||
{
|
{
|
||||||
int i;
|
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. */
|
/* This means the table is empty. */
|
||||||
if (!tpm_log_available())
|
if (!tpm_log_available())
|
||||||
return VB2_SUCCESS;
|
return VB2_SUCCESS;
|
||||||
|
|
||||||
if (!tclt) {
|
if (tpm_log_init() == NULL) {
|
||||||
printk(BIOS_WARNING, "TPM LOG: log non-existent!\n");
|
printk(BIOS_WARNING, "TPM LOG: log non-existent!\n");
|
||||||
return VB2_ERROR_UNKNOWN;
|
return VB2_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "TPM: Write digests cached in TPM log to PCR\n");
|
printk(BIOS_DEBUG, "TPM: Write digests cached in TPM log to PCR\n");
|
||||||
for (i = 0; i < tclt->num_entries; i++) {
|
i = 0;
|
||||||
struct tpm_cb_log_entry *tce = &tclt->entries[i];
|
while (!tpm_log_get(i++, &pcr, &digest_data, &digest_algo, &event_name)) {
|
||||||
if (tce) {
|
printk(BIOS_DEBUG, "TPM: Write digest for %s into PCR %d\n", event_name, pcr);
|
||||||
printk(BIOS_DEBUG, "TPM: Write digest for"
|
int result = tlcl_extend(pcr, digest_data, digest_algo);
|
||||||
" %s into PCR %d\n",
|
if (result != TPM_SUCCESS) {
|
||||||
tce->name, tce->pcr);
|
printk(BIOS_ERR,
|
||||||
int result = tlcl_extend(tce->pcr,
|
"TPM: Writing digest of %s into PCR failed with error %d\n",
|
||||||
tce->digest,
|
event_name, result);
|
||||||
TPM_MEASURE_ALGO);
|
return VB2_ERROR_UNKNOWN;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return VB2_SUCCESS;
|
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);
|
||||||
|
|
|
@ -6,10 +6,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <bootstate.h>
|
|
||||||
#include <vb2_sha.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;
|
static struct tpm_cb_log_table *tclt;
|
||||||
if (tclt)
|
if (tclt)
|
||||||
|
@ -30,27 +29,6 @@ static struct tpm_cb_log_table *tpm_log_cbmem_init(void)
|
||||||
return tclt;
|
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)
|
void tpm_log_dump(void *unused)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -121,42 +99,62 @@ void tpm_preram_log_clear(void)
|
||||||
tclt->num_entries = 0;
|
tclt->num_entries = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)
|
int tpm_log_get(int entry_idx, int *pcr, const uint8_t **digest_data,
|
||||||
static void recover_tpm_log(int is_recovery)
|
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 *tclt;
|
||||||
struct tpm_cb_log_table *ram_log = NULL;
|
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;
|
int i;
|
||||||
|
|
||||||
if (preram_log->num_entries > MAX_PRERAM_TPM_LOG_ENTRIES) {
|
for (i = 0; i < from_log->num_entries; i++) {
|
||||||
printk(BIOS_WARNING, "TPM LOG: pre-RAM log is too full, possible corruption\n");
|
struct tpm_cb_log_entry *tce = &to_log->entries[to_log->num_entries++];
|
||||||
return;
|
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 (from_log->entries[i].digest_length > TPM_CB_LOG_DIGEST_MAX_LENGTH) {
|
||||||
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) {
|
|
||||||
printk(BIOS_WARNING, "TPM LOG: PCR digest too long for log entry\n");
|
printk(BIOS_WARNING, "TPM LOG: PCR digest too long for log entry\n");
|
||||||
return;
|
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);
|
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);
|
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);
|
|
||||||
|
|
Loading…
Reference in New Issue