[SeaBIOS] [PATCH v2 10/10] tpm: Write logs in TPM 2 format

Kevin O'Connor kevin at koconnor.net
Mon Feb 1 23:05:16 CET 2016


On Fri, Jan 22, 2016 at 05:47:20PM -0500, Stefan Berger wrote:
> From: Stefan Berger <stefanb at linux.vnet.ibm.com>
> 
> Introduce a log_entry 'object' that we use to hold the data to be logged in
> one log entry. Pass this object around rather than the TPM 1.2 specific 'pcpes'
> structure.
> 
> Write this log_entry 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):
> 
> TCG EFI Protocol Specification for TPM Family 2.0
> 
> http://www.trustedcomputinggroup.org/resources/tcg_efi_protocol_specification
> 
> 
> Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
> ---
>  src/std/tcg.h |  35 ++++++++++++
>  src/tcgbios.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++---------
>  2 files changed, 183 insertions(+), 25 deletions(-)
> 
> diff --git a/src/std/tcg.h b/src/std/tcg.h
> index 8466b14..1e8b250 100644
> --- a/src/std/tcg.h
> +++ b/src/std/tcg.h
> @@ -89,6 +89,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
> @@ -472,4 +473,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 eventsize;
> +    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 f5500b1..369736c 100644
> --- a/src/tcgbios.c
> +++ b/src/tcgbios.c
> @@ -52,6 +52,71 @@ static const u8 TPM2_SelfTest_YES[] =  { TPM2_YES }; /* full test */
>  
>  typedef u8 tpm_ppi_code;
>  
> +
> +static TPMVersion TPM_version;
> +
> +/****************************************************************
> + * Log entry 'object'
> + ****************************************************************/

This section looks like it could be merged into the "ACPI TCPA table
interface" section as both sections are focused solely on logging.

> +struct log_entry {
> +    u32 pcrindex;
> +    u32 eventtype;
> +    /* we only support SHA1 for TPM 2 */
> +    u8 sha1[SHA1_BUFSIZE];
> +    u32 eventdatasize;
> +    const void *event; /* TPM 1.2 & 2 */
> +};

Instead of introducing 'struct log_entry' to be the superset of
tcg_pcr_event2_sha1 and pcpes, why not use tcg_pcr_event2_sha1
everywhere?  That is, replace all the 'struct pcpes *' with 'struct
tcg_pcr_event2_sha1 *' and then enhance tpm_log_event() to translate
to a pcpes for older logs.

Of course, the above is assuming the log should be in an "efi" format
- see previous email on that.

[...]
> +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 log_entry le = {
> +        .eventtype = EV_NO_ACTION,
> +        .event = &event,
> +    };
> +
> +    switch (TPM_version) {
> +    case TPM_VERSION_NONE:
> +    case TPM_VERSION_1_2:
> +        break;
> +    case TPM_VERSION_2:
> +        /* write a 1.2 type of entry */
> +        TPM_version = 1;
> +        tpm_log_event(&le);
> +        TPM_version = 2;

Altering the TPM_version seems ugly - I think tpm_log_event() could
take the version as a parameter to avoid that.

-Kevin



More information about the SeaBIOS mailing list