[SeaBIOS] [RFC PATCH v1 6/9] tpm: Implement tpm2_prepboot

Kevin O'Connor kevin at koconnor.net
Thu Jan 21 23:44:15 CET 2016


On Fri, Jan 15, 2016 at 02:44:36PM -0500, Stefan Berger wrote:
> From: Stefan Berger <stefanb at linux.vnet.ibm.com>
> 
> Implement tpm2_preboot.
> 
> Here we set the platform password to a random password that prevents
> higher layers (OS) to get this password. This avoids bad things like users
> clearing the TPM, erasing EK (primary key) certificates, changing the
> primary key etc.
> 
> The clearing of the TPM will still be possible through the TPM 2 menu.
> 
> Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
> ---
>  src/std/tcg.h |  44 +++++++++++++++++++++++
>  src/tcgbios.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 152 insertions(+), 2 deletions(-)
> 
> diff --git a/src/std/tcg.h b/src/std/tcg.h
> index db1155d..e0d6f30 100644
> --- a/src/std/tcg.h
> +++ b/src/std/tcg.h
> @@ -372,14 +372,58 @@ struct tpm_res_sha1complete {
>  #define TPM2_SU_CLEAR               0x0000
>  #define TPM2_SU_STATE               0x0001
>  
> +#define TPM2_RS_PW                  0x40000009
> +#define TPM2_RH_PLATFORM            0x4000000c
> +
>  /* TPM 2 command tags */
>  #define TPM2_ST_NO_SESSIONS         0x8001
> +#define TPM2_ST_SESSIONS            0x8002
>  
>  /* TPM 2 commands */
> +#define TPM2_CC_HierarchyChangeAuth 0x129
>  #define TPM2_CC_SelfTest            0x143
>  #define TPM2_CC_Startup             0x144
> +#define TPM2_CC_StirRandom          0x146
> +#define TPM2_CC_GetRandom           0x17b
>  
>  /* TPM 2 error codes */
>  #define TPM2_RC_INITIALIZE          0x100
>  
> +/* TPM 2 data structures */
> +
> +struct tpm2b_stir {
> +    u16 size;
> +    u64 stir;
> +} PACKED;
> +
> +struct tpm2_req_getrandom {
> +    struct tpm_req_header hdr;
> +    u16 bytesRequested;
> +} PACKED;
> +
> +struct tpm2b_20 {
> +    u16 size;
> +    u8 buffer[20];
> +} PACKED;
> +
> +struct tpm2_res_getrandom {
> +    struct tpm_rsp_header hdr;
> +    struct tpm2b_20 rnd;
> +} PACKED;
> +
> +struct tpm2_authblock {
> +    u32 handle;
> +    u16 noncesize;  /* always 0 */
> +    u8 contsession; /* always TPM2_YES */
> +    u16 pwdsize;    /* always 0 */
> +} PACKED;
> +
> +struct tpm2_req_hierarchychangeauth {
> +    struct tpm_req_header hdr;
> +    u32 authhandle;
> +    u32 authblocksize;
> +    struct tpm2_authblock authblock;
> +    struct tpm2b_20 newAuth;
> +} PACKED;
> +
>  #endif // tcg.h
> diff --git a/src/tcgbios.c b/src/tcgbios.c
> index 7b6409c..4f5c5bb 100644
> --- a/src/tcgbios.c
> +++ b/src/tcgbios.c
> @@ -204,7 +204,7 @@ tpm_build_and_send_cmd(u8 locty, u32 ordinal, const u8 *append,
>  {
>      struct {
>          struct tpm_req_header trqh;
> -        u8 cmd[6];
> +        u8 cmd[10];
>      } PACKED req = {
>          .trqh.tag = cpu_to_be16(TPM_TAG_RQU_CMD),
>          .trqh.totlen = cpu_to_be32(sizeof(req.trqh) + append_size),
> @@ -654,6 +654,112 @@ tpm_setup(void)
>      tpm_add_action(2, "Start Option ROM Scan");
>  }
>  
> +static int
> +tpm2_stirrandom(void)
> +{
> +    struct tpm2b_stir stir = {
> +        .size = cpu_to_be16(sizeof(stir.stir)),
> +        .stir = rdtscll(),
> +    };
> +    /* set more bits to stir with */
> +    stir.stir += swab64(rdtscll());
> +
> +    return tpm_build_and_send_cmd(0, TPM2_CC_StirRandom,
> +                                  (u8 *)&stir, sizeof(stir),
> +                                  TPM_DURATION_TYPE_SHORT);
> +}
> +
> +static int
> +tpm2_getrandom(u8 *buf, u16 buf_len)
> +{
> +    struct tpm2_res_getrandom rsp;
> +
> +    if (buf_len > sizeof(rsp.rnd.buffer))
> +        return -1;
> +
> +    struct tpm2_req_getrandom trgr = {
> +        .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
> +        .hdr.totlen = cpu_to_be32(sizeof(trgr)),
> +        .hdr.ordinal = cpu_to_be32(TPM2_CC_GetRandom),
> +        .bytesRequested = cpu_to_be16(buf_len),
> +    };
> +    u32 resp_length = sizeof(rsp);
> +
> +    int ret = tpmhw_transmit(0, &trgr.hdr, &rsp, &resp_length,
> +                             TPM_DURATION_TYPE_MEDIUM);
> +    if (ret || resp_length != sizeof(rsp) || rsp.hdr.errcode)
> +        return -1;
> +
> +    memcpy(buf, rsp.rnd.buffer, buf_len);
> +
> +    return 0;
> +}
> +
> +static int
> +tpm2_hierarchychangeauth(u8 auth[20])
> +{
> +    struct tpm2_req_hierarchychangeauth trhca = {
> +        .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
> +        .hdr.totlen = cpu_to_be32(sizeof(trhca)),
> +        .hdr.ordinal = cpu_to_be32(TPM2_CC_HierarchyChangeAuth),
> +        .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
> +        .authblocksize = cpu_to_be32(sizeof(trhca.authblock)),
> +        .authblock = {
> +            .handle = cpu_to_be32(TPM2_RS_PW),
> +            .noncesize = cpu_to_be16(0),
> +            .contsession = TPM2_YES,
> +            .pwdsize = cpu_to_be16(0),
> +        },
> +        .newAuth = {
> +            .size = cpu_to_be16(sizeof(trhca.newAuth.buffer)),
> +        },
> +    };
> +    memcpy(trhca.newAuth.buffer, auth, sizeof(trhca.newAuth.buffer));
> +
> +    struct tpm_rsp_header rsp;
> +    u32 resp_length = sizeof(rsp);
> +    int ret = tpmhw_transmit(0, &trhca.hdr, &rsp, &resp_length,
> +                             TPM_DURATION_TYPE_MEDIUM);
> +    if (ret || resp_length != sizeof(rsp) || rsp.errcode)
> +        return -1;
> +
> +    return 0;
> +}
> +
> +static void
> +tpm2_prepboot(void)
> +{
> +    int ret = tpm2_stirrandom();
> +
> +    dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_StirRandom = 0x%08x\n",
> +            ret);
> +    if (ret)
> +         goto err_exit;
> +
> +    u8 auth[20];
> +    ret = tpm2_getrandom(&auth[0], sizeof(auth));
> +
> +    dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_GetRandom = 0x%08x\n",
> +            ret);
> +
> +    if (ret)
> +        goto err_exit;
> +
> +    ret = tpm2_hierarchychangeauth(auth);
> +    dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_HierarchyChangeAuth = 0x%08x\n",
> +            ret);

Minor nit - I think it would be better for an error dprintf to be done
in the function that raised the error instead of the callers of that
function.

-Kevin



More information about the SeaBIOS mailing list