Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/51710 )
Change subject: [WIP]security/tpm: Implement TCG TPM2 compatible eventlog ......................................................................
[WIP]security/tpm: Implement TCG TPM2 compatible eventlog
This copies the measurement from the TCPA eventlog into a TCG TPM2 compatible format.
TODO: - It only works with TPM2 and assumes SHA256 is used. - It assumes nothing is measured after BS_PAYLOAD_BOOT BS.
Change-Id: I99c2fff0cde6d1e68b802c8810fefecda9f11eb4 Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/acpi/acpi.c M src/include/acpi/acpi.h M src/security/tpm/Kconfig M src/security/tpm/Makefile.inc A src/security/tpm/tspi/tcg_log.c 5 files changed, 195 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/10/51710/1
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c index 867e163..6430fa1 100644 --- a/src/acpi/acpi.c +++ b/src/acpi/acpi.c @@ -348,7 +348,7 @@ header->checksum = acpi_checksum((void *)tcpa, header->length); }
-static void *get_tpm2_log(u32 *size) +void *get_tpm2_log(u32 *size) { const struct cbmem_entry *ce; const u32 tpm2_default_log_len = 0x10000; diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h index 775fc31..8919712 100644 --- a/src/include/acpi/acpi.h +++ b/src/include/acpi/acpi.h @@ -1086,6 +1086,8 @@ void mainboard_suspend_resume(void); void *acpi_find_wakeup_vector(void);
+void *get_tpm2_log(u32 *size); + /* ACPI_Sn assignments are defined to always equal the sleep state numbers */ enum { ACPI_S0 = 0, diff --git a/src/security/tpm/Kconfig b/src/security/tpm/Kconfig index e1255d1..f28529a 100644 --- a/src/security/tpm/Kconfig +++ b/src/security/tpm/Kconfig @@ -114,4 +114,11 @@ Runtime data whitelist of cbfs filenames. Needs to be a space delimited list
+config TPM2_TCG_LOG + bool "Generate TPM2 TCG log" + default n + depends on TPM2 && TPM_MEASURED_BOOT + help + Report + endmenu # Trusted Platform Module (tpm) diff --git a/src/security/tpm/Makefile.inc b/src/security/tpm/Makefile.inc index c36183d..ef83a02 100644 --- a/src/security/tpm/Makefile.inc +++ b/src/security/tpm/Makefile.inc @@ -61,4 +61,6 @@ postcar-y += tspi/log.c bootblock-y += tspi/log.c
+ramstage-$(CONFIG_TPM2_TCG_LOG) += tspi/tcg_log.c + endif # CONFIG_TPM_MEASURED_BOOT diff --git a/src/security/tpm/tspi/tcg_log.c b/src/security/tpm/tspi/tcg_log.c new file mode 100644 index 0000000..5c84966 --- /dev/null +++ b/src/security/tpm/tspi/tcg_log.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "commonlib/tcpa_log_serialized.h" +#include "security/tpm/tspi.h" +#include "security/tpm/tss/tcg-2.0/tss_structures.h" +#include <acpi/acpi.h> +#include <cbmem.h> +#include <commonlib/bsd/helpers.h> +#include <console/console.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <bootstate.h> + +/* Some hardcoded algorithm values. */ +/* Table 7 - TPM_ALG_ID Constants */ +#define TPM2_ALG_ERROR 0x0000 +#define TPM2_ALG_HMAC 0x0005 +#define TPM2_ALG_NULL 0x0010 +#define TPM2_ALG_SHA1 0x0004 +#define TPM2_ALG_SHA256 0x000b +#define TPM2_ALG_SHA384 0x000c +#define TPM2_ALG_SHA512 0x000d +#define TPM2_ALG_SM3_256 0x0012 +/* Annex A Algorithm Constants */ +/* Table 205 - Defines for SHA1 Hash Values */ +#define SHA1_DIGEST_SIZE 20 +/* Table 206 - Defines for SHA256 Hash Values */ +#define SHA256_DIGEST_SIZE 32 +/* Table 207 - Defines for SHA384 Hash Values */ +#define SHA384_DIGEST_SIZE 48 +/* Table 208 - Defines for SHA512 Hash Values */ +#define SHA512_DIGEST_SIZE 64 +/* Table 209 - Defines for SM3_256 Hash Values */ +#define SM3_256_DIGEST_SIZE 32 + +#define TCG_HASH_COUNT 1 + +/* Table 66 - TPMU_HA Union */ +typedef union { + uint8_t sha1[SHA1_DIGEST_SIZE]; + uint8_t sha256[SHA256_DIGEST_SIZE]; + uint8_t sm3_256[SM3_256_DIGEST_SIZE]; + uint8_t sha384[SHA384_DIGEST_SIZE]; + uint8_t sha512[SHA512_DIGEST_SIZE]; +} tpm_hash_digest; + +typedef struct { + uint16_t hashAlg; + tpm_hash_digest digest; +} tpm_hash_algorithm; + +/* Table 96 -- TPML_DIGEST_VALUES Structure <I/O> */ +typedef struct { + uint32_t count; + tpm_hash_algorithm digests[TCG_HASH_COUNT]; +} tpm_digest_values; + +typedef struct { + uint16_t alg_id; + uint16_t digest_size; +} __packed tpm_digest_sizes; + +typedef struct { + uint32_t pcr_index; + uint32_t event_type; +} __packed tcg_pcr_event2_header; + +typedef struct { + uint32_t event_size; + uint8_t event[0]; +} __packed tcg_pcr_event2_footer; + +typedef struct { + uint32_t pcr_index; + uint32_t event_type; + uint8_t digest[20]; + uint32_t event_size; + uint8_t signature[16]; + uint32_t platform_class; + uint8_t spec_version_minor; + uint8_t spec_version_major; + uint8_t spec_errata; + uint8_t uintn_size; + uint32_t num_of_algorithms; + tpm_digest_sizes digest_sizes[TCG_HASH_COUNT]; + uint8_t vendor_info_size; + uint8_t vendor_info[0]; +} __packed tcg_efi_spec_id_event; + +#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE "Spec ID Event03" +#define EV_PREBOOT_CERT 0x00000000 +#define EV_POST_CODE 0x00000001 +#define EV_UNUSED 0x00000002 +#define EV_NO_ACTION 0x00000003 +#define EV_SEPARATOR 0x00000004 +#define EV_ACTION 0x00000005 +#define EV_EVENT_TAG 0x00000006 +#define EV_S_CRTM_CONTENTS 0x00000007 +#define EV_S_CRTM_VERSION 0x00000008 +#define EV_CPU_MICROCODE 0x00000009 +#define EV_PLATFORM_CONFIG_FLAGS 0x0000000A +#define EV_TABLE_OF_DEVICES 0x0000000B +#define EV_COMPACT_HASH 0x0000000C +#define EV_IPL 0x0000000D +#define EV_IPL_PARTITION_DATA 0x0000000E +#define EV_NONHOST_CODE 0x0000000F +#define EV_NONHOST_CONFIG 0x00000010 +#define EV_NONHOST_INFO 0x00000011 +#define EV_OMIT_BOOT_DEVICE_EVENTS 0x00000012 + +#define TPM_TCPA_ACPI_CLASS_CLIENT 0 + +static char *tpm2_log; + +static void *write_efi_spec_id_event(void *tpm2) +{ + const uint8_t signature[16] = TCG_EFI_SPEC_ID_EVENT_SIGNATURE; + + tcg_efi_spec_id_event *spec_id_event = tpm2; + memset(spec_id_event, 0, sizeof(*spec_id_event)); + spec_id_event->pcr_index = 0; + spec_id_event->event_type = EV_NO_ACTION; + spec_id_event->event_size = sizeof(tcg_efi_spec_id_event) - offsetof(tcg_efi_spec_id_event, signature); + strncpy((char *)spec_id_event->signature, (char *)signature, ARRAY_SIZE(spec_id_event->signature)); + spec_id_event->platform_class = TPM_TCPA_ACPI_CLASS_CLIENT; + spec_id_event->spec_version_minor = 0; + spec_id_event->spec_version_major = 2; + spec_id_event->spec_errata = 0; + spec_id_event->uintn_size = 2; /* Assume the hardware supports long mode. */ + spec_id_event->num_of_algorithms = 1; /* Coreboot TCPA only used 1 hash algo. */ + spec_id_event->digest_sizes[0].alg_id = TPM2_ALG_SHA256; + spec_id_event->digest_sizes[0].digest_size = SHA256_DIGEST_SIZE; + spec_id_event->vendor_info_size = 0; + return (char *)tpm2 + offsetof(tcg_efi_spec_id_event, vendor_info); +} + +static void tpm2_log_entry_sha256(uint8_t pcr, uint8_t digest[SHA256_DIGEST_SIZE], char *event, + size_t event_size) +{ + tcg_pcr_event2_header *header = (tcg_pcr_event2_header *)tpm2_log; + header->pcr_index = pcr; + header->event_type = EV_ACTION; + tpm2_log += sizeof(*header); + + tpm_digest_values *entry_digest = (tpm_digest_values *)tpm2_log; + entry_digest->count = TCG_HASH_COUNT; + entry_digest->digests[0].hashAlg = TPM2_ALG_SHA256; + memcpy(entry_digest->digests[0].digest.sha256, digest, SHA256_DIGEST_SIZE); + tpm2_log += sizeof(entry_digest->count) + sizeof(entry_digest->digests[0].hashAlg) + + sizeof(entry_digest->digests[0].digest.sha256); + + tcg_pcr_event2_footer *footer = (tcg_pcr_event2_footer *)tpm2_log; + footer->event_size = event_size; + memcpy(footer->event, event, event_size); + tpm2_log += sizeof(footer->event_size) + event_size; +} + +static void copy_tcpa_log(void) +{ + struct tcpa_table *tcpa_log = tcpa_log_init(); + + for (int i = 0; i < tcpa_log->num_entries; i++) { + struct tcpa_entry *tce = &tcpa_log->entries[i]; + tpm2_log_entry_sha256(tce->pcr, tce->digest, tce->name, sizeof(tce->name)); + } +} + +static void init_tpm2_tcg(void *unused) +{ + uint32_t tpm2_log_size; + tpm2_log = get_tpm2_log(&tpm2_log_size); + if (!tpm2_log) { + printk(BIOS_ERR, "Could not find TPM2 TCG log\n"); + return; + } + write_efi_spec_id_event(tpm2_log); + tpm2_log += sizeof(tcg_efi_spec_id_event); + + copy_tcpa_log(); +} + +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, init_tpm2_tcg, NULL);