[SeaBIOS] [PATCH 3/3] tpm: Support 2.0 TPM devices connected to a TIS host

Stephen Douthit stephend at silicom-usa.com
Mon Feb 26 23:44:47 CET 2018


On 02/26/2018 05:09 PM, Stefan Berger wrote:
> On 02/26/2018 03:37 PM, Stephen Douthit wrote:
>> tis_get_tpm_version() was returning the interface version, which is always
>> 1.2 since tis_probe() would have failed if the interface wasn't TIS.
>>
>> New version check is based on the tpm2_probe() function from the Linux
>> tpm_tis driver.
>>
>> Signed-off-by: Stephen Douthit <stephend at silicom-usa.com>
>> Tested-by: Stephen Douthit <stephend at silicom-usa.com>
>> ---
>>   src/hw/tpm_drivers.c | 21 +++++++++++++++------
>>   src/std/tcg.h        |  1 +
>>   src/tcgbios.c        |  2 +-
>>   src/tcgbios.h        |  4 ++++
>>   4 files changed, 21 insertions(+), 7 deletions(-)
>>
>> diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c
>> index 789d70a..32c34df 100644
>> --- a/src/hw/tpm_drivers.c
>> +++ b/src/hw/tpm_drivers.c
>> @@ -11,6 +11,7 @@
>>   #include "config.h" // CONFIG_TPM_TIS_SHA1THRESHOLD
>>   #include "hw/tpm_drivers.h" // struct tpm_driver
>>   #include "std/tcg.h" // TCG_RESPONSE_TIMEOUT
>> +#include "tcgbios.h" // tpm20_getcapability
>>   #include "output.h" // warn_timeout
>>   #include "stacks.h" // yield
>>   #include "string.h" // memcpy
>> @@ -119,7 +120,7 @@ static u32 tis_probe(void)
>>       if ((didvid != 0) && (didvid != 0xffffffff))
>>           rc = 1;
>>
>> -    /* TPM 2 has an interface register */
>> +    /* Low 32 bits of CRB interface register overlap TIS interface register */
>>       u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID));
> 
> Since this is tis_probe, I don't think we need to mention the CRB here ...

I think that was a note to myself I forgot to strip out when I
dropped my debug prints.  I'll change the comment back.

>>
>>       if ((ifaceid & 0xf) != 0xf) {
>> @@ -142,13 +143,21 @@ static u32 tis_probe(void)
>>
>>   static TPMVersion tis_get_tpm_version(void)
>>   {
>> -    /* TPM 2 has an interface register */
>> -    u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID));
>> +    u8 buffer[128];
>> +    int ret;
>> +    struct tpm2_res_getcapability *trg =
>> +      (struct tpm2_res_getcapability *)&buffer;
>> +
>> +    ret = tpm20_getcapability(TPM2_CAP_TPM_PROPERTIES, cpu_to_be32(0x100),
>> +                              cpu_to_be32(1), &trg->hdr, sizeof(buffer));
>> +    if (ret == TPM2_RC_INITIALIZE)
>> +        return TPM_VERSION_2;
>> +    else if (ret)
>> +        return TPM_VERSION_NONE;
> I haven't tried yet, but likely this will not work for TPM 1.2 since it will also return an error.

Doh.  That makes sense.  I'll need to find a 1.2 system to test on to
avoid stupid mistakes like that.

> Wouldn't the check for the tag below not be sufficient? We are doing something similar in QEMU when probing for the TPM. Here we send TPM 2 command TPM_CC_ReadClock and check the tag for TPM 2 type and then TPM 1.2 command TPM_ORD_GetTicks and check for TPM 1.2 tag.

It might be, it wasn't clear to me if the tag could be trusted if the
return code wasn't success.  The Linux tpm2_probe() code bails before
the tag comparison if tpm_transmit_cmd() returns an error.

Is there a block of QEMU code you would recommend as a reference for
probing TPMs?  I'm not very familiar with that code base, and a
pointer would be handy.

> Do you know what value does the InterfaceType show on your TIS? I only tested this with QEMU TIS and here we return 0x0 in those 4 bits, which means, following specs, 'FIFO interface as defined in PTP for TPM 2.0 is active'.

I don't see it in my notes, I can put some debug prints back in
tomorrow and will get back to you.

Thanks,
Steve

>>
>> -    if ((ifaceid & 0xf) == 0) {
>> -        /* TPM 2 */
>> +    if (cpu_to_be32(trg->hdr.tag) == TPM2_ST_NO_SESSIONS)
>>           return TPM_VERSION_2;
>> -    }
>> +
>>       return TPM_VERSION_1_2;
>>   }
>>
>> diff --git a/src/std/tcg.h b/src/std/tcg.h
>> index 09a92d8..4c07493 100644
>> --- a/src/std/tcg.h
>> +++ b/src/std/tcg.h
>> @@ -357,6 +357,7 @@ struct tpm_res_sha1complete {
>>
>>   /* TPM 2 Capabilities */
>>   #define TPM2_CAP_PCRS               0x00000005
>> +#define TPM2_CAP_TPM_PROPERTIES     0x00000006
>>
>>   /* TPM 2 data structures */
>>
>> diff --git a/src/tcgbios.c b/src/tcgbios.c
>> index 40b3028..b86bf64 100644
>> --- a/src/tcgbios.c
>> +++ b/src/tcgbios.c
>> @@ -381,7 +381,7 @@ tpm_simple_cmd(u8 locty, u32 ordinal
>>       return ret;
>>   }
>>
>> -static int
>> +int
>>   tpm20_getcapability(u32 capability, u32 property, u32 count,
>>                       struct tpm_rsp_header *rsp, u32 rsize)
>>   {
>> diff --git a/src/tcgbios.h b/src/tcgbios.h
>> index 32fb941..9fc711a 100644
>> --- a/src/tcgbios.h
>> +++ b/src/tcgbios.h
>> @@ -1,6 +1,7 @@
>>   #ifndef TCGBIOS_H
>>   #define TCGBIOS_H
>>
>> +#include "std/tcg.h" // struct tpm_rsp_header
>>   #include "types.h"
>>
>>   struct bregs;
>> @@ -15,5 +16,8 @@ void tpm_add_cdrom_catalog(const u8 *addr, u32 length);
>>   void tpm_option_rom(const void *addr, u32 len);
>>   int tpm_can_show_menu(void);
>>   void tpm_menu(void);
>> +int
>> +tpm20_getcapability(u32 capability, u32 property, u32 count,
>> +                    struct tpm_rsp_header *rsp, u32 rsize);
>>
>>   #endif /* TCGBIOS_H */
> 
> 




More information about the SeaBIOS mailing list