#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
{
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),
tpm_add_action(2, "Start Option ROM Scan");
}
+static int
+tpm20_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());
+
+ int ret = tpm_build_and_send_cmd(0, TPM2_CC_StirRandom,
+ (u8 *)&stir, sizeof(stir),
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_StirRandom = 0x%08x\n",
+ ret);
+
+ return ret;
+}
+
+static int
+tpm20_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)
+ ret = -1;
+ else
+ memcpy(buf, rsp.rnd.buffer, buf_len);
+
+ dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_GetRandom = 0x%08x\n",
+ ret);
+
+ return ret;
+}
+
+static int
+tpm20_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)
+ ret = -1;
+
+ dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_HierarchyChangeAuth = 0x%08x\n",
+ ret);
+
+ return ret;
+}
+
+static void
+tpm20_prepboot(void)
+{
+ int ret = tpm20_stirrandom();
+ if (ret)
+ goto err_exit;
+
+ u8 auth[20];
+ ret = tpm20_getrandom(&auth[0], sizeof(auth));
+ if (ret)
+ goto err_exit;
+
+ ret = tpm20_hierarchychangeauth(auth);
+ if (ret)
+ goto err_exit;
+
+ return;
+
+err_exit:
+ dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_set_failure();
+}
+
void
tpm_prepboot(void)
{
TPM_DURATION_TYPE_SHORT);
break;
case TPM_VERSION_2:
- // FIXME: missing code
+ tpm20_prepboot();
break;
}