[SeaBIOS] [PATCH 2/2] tpm: Write logs in TPM 2 format
Stefan Berger
stefanb at linux.vnet.ibm.com
Mon Feb 8 13:25:35 CET 2016
On 02/06/2016 01:35 PM, Kevin O'Connor wrote:
> Add support for the TPM 2 format of log messages.
>
> Write the logs in the format that is appropriate for the version of
> the host's TPM. For TPM 1.2 write it in the 'pcpes' structure's
> format, for TPM 2 in the new TPM 2 format.
>
> By using this method we can keep the API interface on systems with a
> TPM 2 even though applications pass in the 'pcpes' structures
> directly. The log will still be written in the appropriate format.
>
> The TPM 2 log contains a TPM 1.2 type of entry of event type
> EV_NO_ACTION and entry of type TCG_EfiSpeIdEventStruct as the first
> entry. This is described in the EFI specification (section 5.3):
>
> Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
> ---
> src/std/tcg.h | 35 +++++++++++++++++++++++++++
> src/tcgbios.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
> 2 files changed, 101 insertions(+), 10 deletions(-)
>
> diff --git a/src/std/tcg.h b/src/std/tcg.h
> index dbb3a60..c59f671 100644
> --- a/src/std/tcg.h
> +++ b/src/std/tcg.h
> @@ -91,6 +91,7 @@ enum irq_ids {
>
> /* event types: 10.4.1 / table 11 */
> #define EV_POST_CODE 1
> +#define EV_NO_ACTION 3
> #define EV_SEPARATOR 4
> #define EV_ACTION 5
> #define EV_EVENT_TAG 6
> @@ -474,4 +475,38 @@ struct tpm2_req_hierarchycontrol {
> u8 state;
> } PACKED;
>
> +/* TPM 2 log entry */
> +
> +struct tpml_digest_values_sha1 {
> + u16 hashtype;
> + u8 sha1[SHA1_BUFSIZE];
> +};
> +
> +struct tcg_pcr_event2_sha1 {
> + u32 pcrindex;
> + u32 eventtype;
> + u32 count; /* number of digests */
> + struct tpml_digest_values_sha1 digests[1];
> + u32 eventdatasize;
> + u8 event[0];
> +} PACKED;
> +
> +struct TCG_EfiSpecIdEventStruct {
> + u8 signature[16];
> + u32 platformClass;
> + u8 specVersionMinor;
> + u8 specVersionMajor;
> + u8 specErrata;
> + u8 uintnSize;
> + u32 numberOfAlgorithms;
> + struct TCG_EfiSpecIdEventAlgorithmSize {
> + u16 algorithmId;
> + u16 digestSize;
> + } digestSizes[1];
> + u8 vendorInfoSize;
> + u8 vendorInfo[0];
> +};
> +
> +#define TPM_TCPA_ACPI_CLASS_CLIENT 0
> +
> #endif // tcg.h
> diff --git a/src/tcgbios.c b/src/tcgbios.c
> index cddc99b..f0ab188 100644
> --- a/src/tcgbios.c
> +++ b/src/tcgbios.c
> @@ -141,7 +141,7 @@ tpm_tcpa_probe(void)
> * Returns an error code in case of faiure, 0 in case of success
> */
> static int
> -tpm_log_event(struct pcpes *pcpes, const void *event)
> +tpm_log_event(struct tcg_pcr_event2_sha1 *entry, const void *event)
> {
> dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n",
> tpm_state.log_area_start_address, tpm_state.log_area_next_entry);
> @@ -149,7 +149,7 @@ tpm_log_event(struct pcpes *pcpes, const void *event)
> if (tpm_state.log_area_next_entry == NULL)
> return -1;
>
> - u32 size = sizeof(*pcpes) + pcpes->eventdatasize;
> + u32 size = sizeof(*entry) + entry->eventdatasize;
This is only the correct size for TPM 2. I think there should be a case
statement here.
>
> if ((tpm_state.log_area_next_entry + size - tpm_state.log_area_start_address) >
> tpm_state.log_area_minimum_length) {
> @@ -157,9 +157,19 @@ tpm_log_event(struct pcpes *pcpes, const void *event)
> return -1;
> }
>
> - memcpy(tpm_state.log_area_next_entry, pcpes, sizeof(*pcpes));
> - memcpy(tpm_state.log_area_next_entry + sizeof(*pcpes),
> - event, pcpes->eventdatasize);
> + if (TPM_version == TPM_VERSION_1_2 || entry->eventtype == EV_NO_ACTION) {
This only works if TPM 2 entries don't have a EV_NO_ACTION (= 3). I
think the cleaner solution would be to differentiate by version only.
The main difference here between parts of my code and yours is that you
are inlining it.
> + struct pcpes *pcpes = (void*)tpm_state.log_area_next_entry;
> + pcpes->pcrindex = entry->pcrindex;
> + pcpes->eventtype = entry->eventtype;
> + memcpy(pcpes->digest, entry->digests[0].sha1, sizeof(pcpes->digest));
> + pcpes->eventdatasize = entry->eventdatasize;
> + memcpy(pcpes->event, event, entry->eventdatasize);
> + size = sizeof(*pcpes) + entry->eventdatasize;
> + } else {
> + struct tcg_pcr_event2_sha1 *e = (void*)tpm_state.log_area_next_entry;
> + memcpy(e, entry, sizeof(*e));
> + memcpy(e->event, event, entry->eventdatasize);
> + }
>
> tpm_state.log_area_last_entry = tpm_state.log_area_next_entry;
> tpm_state.log_area_next_entry += size;
> @@ -168,6 +178,40 @@ tpm_log_event(struct pcpes *pcpes, const void *event)
> return 0;
> }
>
> +/*
> + * Initialize the log; a TPM2 log needs a special TPM 1.2 log entry
> + * as the first entry serving identification purposes
> + */
> +void tpm_log_init(void)
> +{
> + struct TCG_EfiSpecIdEventStruct event = {
> + .signature = "Spec ID Event03",
> + .platformClass = TPM_TCPA_ACPI_CLASS_CLIENT,
> + .specVersionMinor = 0,
> + .specVersionMajor = 2,
> + .specErrata = 0,
> + .uintnSize = 2,
> + .numberOfAlgorithms = 1,
> + .digestSizes[0] = {
> + .algorithmId = TPM2_ALG_SHA1,
> + .digestSize = SHA1_BUFSIZE,
> + },
> + .vendorInfoSize = 0,
> + };
> + struct tcg_pcr_event2_sha1 entry = {
> + .eventtype = EV_NO_ACTION,
> + .eventdatasize = sizeof(event),
> + };
> +
> + switch (TPM_version) {
> + case TPM_VERSION_1_2:
> + break;
> + case TPM_VERSION_2:
> + /* write a 1.2 type of entry */
> + tpm_log_event(&entry, &event);
> + }
> +}
> +
>
> /****************************************************************
> * Helper functions
> @@ -457,18 +501,20 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type,
> if (!tpm_is_working())
> return;
>
> - struct pcpes pcpes = {
> + struct tcg_pcr_event2_sha1 entry = {
> .pcrindex = pcrindex,
> .eventtype = event_type,
> .eventdatasize = event_length,
> + .count = 1,
> + .digests[0].hashtype = TPM2_ALG_SHA1,
> };
> - sha1(hashdata, hashdata_length, pcpes.digest);
> - int ret = tpm_extend(pcpes.pcrindex, pcpes.digest);
> + sha1(hashdata, hashdata_length, entry.digests[0].sha1);
> + int ret = tpm_extend(entry.pcrindex, entry.digests[0].sha1);
> if (ret) {
> tpm_set_failure();
> return;
> }
> - tpm_log_event(&pcpes, event);
> + tpm_log_event(&entry, event);
> }
>
>
> @@ -690,6 +736,8 @@ tpm_setup(void)
> if (ret)
> return;
>
> + tpm_log_init();
> +
> TPM_working = 1;
>
> if (runningOnXen())
> @@ -992,7 +1040,15 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length
> if (ret)
> return TCG_TCG_COMMAND_ERROR;
> }
> - int ret = tpm_log_event(pcpes, pcpes->event);
> + struct tcg_pcr_event2_sha1 entry = {
> + .pcrindex = pcpes->pcrindex,
> + .eventtype = pcpes->eventtype,
> + .eventdatasize = pcpes->eventdatasize,
> + .count = 1,
> + .digests[0].hashtype = TPM2_ALG_SHA1,
> + };
> + memcpy(entry.digests[0].sha1, pcpes->digest, sizeof(entry.digests[0].sha1));
> + int ret = tpm_log_event(&entry, pcpes->event);
> if (ret)
> return TCG_PC_LOGOVERFLOW;
> return 0;
The rest looks good.
Stefan
More information about the SeaBIOS
mailing list