[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