[SLOF] [PATCH v4 30/33] tpm2: implement tpm20_prepboot

Stefan Berger stefanb at linux.vnet.ibm.com
Thu Dec 12 07:27:25 AEDT 2019


Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 lib/libtpm/tcgbios.c     | 108 +++++++++++++++++++++++++++++++++++++++
 lib/libtpm/tcgbios_int.h |  32 ++++++++++++
 2 files changed, 140 insertions(+)

diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index c28385e..db1e4f0 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -19,6 +19,7 @@
  */
 
 #include <stddef.h>
+#include <stdlib.h>
 
 #include "types.h"
 #include "byteorder.h"
@@ -511,6 +512,88 @@ static int tpm_extend(struct tpm_log_entry *le, int digest_len)
 	return -1;
 }
 
+static int tpm20_stirrandom(void)
+{
+	struct tpm2_req_stirrandom stir = {
+		.hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
+		.hdr.totlen = cpu_to_be32(sizeof(stir)),
+		.hdr.ordinal = cpu_to_be32(TPM2_CC_StirRandom),
+		.size = cpu_to_be16(sizeof(stir.stir)),
+		.stir = rand(),
+	};
+	struct tpm_rsp_header rsp;
+	uint32_t resp_length = sizeof(rsp);
+	int ret = tpmhw_transmit(0, &stir.hdr, &rsp, &resp_length,
+				 TPM_DURATION_TYPE_SHORT);
+	if (ret || resp_length != sizeof(rsp) || rsp.errcode)
+		ret = -1;
+
+	dprintf("TCGBIOS: Return value from sending TPM2_CC_StirRandom = 0x%08x\n",
+		ret);
+
+	return ret;
+}
+
+static int tpm20_getrandom(uint8_t *buf, uint16_t buf_len)
+{
+	struct tpm2_res_getrandom rsp;
+	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),
+	};
+	uint32_t resp_length = sizeof(rsp);
+
+	if (buf_len > sizeof(rsp.rnd.buffer))
+		return -1;
+
+	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("TCGBIOS: Return value from sending TPM2_CC_GetRandom = 0x%08x\n",
+		ret);
+
+	return ret;
+}
+
+static int tpm20_hierarchychangeauth(uint8_t 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;
+	uint32_t 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("TCGBIOS: Return value from sending TPM2_CC_HierarchyChangeAuth = 0x%08x\n",
+		ret);
+
+	return ret;
+}
+
 static int tpm20_hierarchycontrol(uint32_t hierarchy, uint8_t state)
 {
 	/* we will try to deactivate the TPM now - ignoring all errors */
@@ -841,6 +924,29 @@ void tpm_finalize(void)
 	spapr_vtpm_finalize();
 }
 
+static void tpm20_prepboot(void)
+{
+	uint8_t auth[20];
+	int ret = tpm20_stirrandom();
+	if (ret)
+		 goto err_exit;
+
+	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("TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+	tpm_set_failure();
+}
+
 /*
  * Give up physical presence; this function has to be called before
  * the firmware transitions to the boot loader.
@@ -854,6 +960,8 @@ uint32_t tpm_unassert_physical_presence(void)
 				       2, TPM_PP_NOT_PRESENT_LOCK,
 				       TPM_DURATION_TYPE_SHORT);
 	break;
+	case TPM_VERSION_2:
+		tpm20_prepboot();
 	}
 
 	return 0;
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index 3dc7199..ce4d9c2 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -278,9 +278,12 @@ struct tpm_rsp_getcap_buffersize {
 #define TPM2_CC_HierarchyControl    0x121
 #define TPM2_CC_Clear               0x126
 #define TPM2_CC_ClearControl        0x127
+#define TPM2_CC_HierarchyChangeAuth 0x129
 #define TPM2_CC_SelfTest            0x143
 #define TPM2_CC_Startup             0x144
+#define TPM2_CC_StirRandom          0x146
 #define TPM2_CC_GetCapability       0x17a
+#define TPM2_CC_GetRandom           0x17b
 #define TPM2_CC_PCR_Extend          0x182
 
 /* TPM 2 Capabilities */
@@ -288,6 +291,27 @@ struct tpm_rsp_getcap_buffersize {
 
 /* TPM 2 data structures */
 
+struct tpm2_req_stirrandom {
+	struct tpm_req_header hdr;
+	uint16_t size;
+	uint64_t stir;
+} __attribute__((packed));
+
+struct tpm2_req_getrandom {
+	struct tpm_req_header hdr;
+	uint16_t bytesRequested;
+} __attribute__((packed));
+
+struct tpm2b_20 {
+	uint16_t size;
+	uint8_t buffer[20];
+} __attribute__((packed));
+
+struct tpm2_res_getrandom {
+	struct tpm_rsp_header hdr;
+	struct tpm2b_20 rnd;
+} __attribute__((packed));
+
 struct tpm2_authblock {
 	uint32_t handle;
 	uint16_t noncesize;  /* always 0 */
@@ -295,6 +319,14 @@ struct tpm2_authblock {
 	uint16_t pwdsize;    /* always 0 */
 } __attribute__((packed));
 
+struct tpm2_req_hierarchychangeauth {
+	struct tpm_req_header hdr;
+	uint32_t authhandle;
+	uint32_t authblocksize;
+	struct tpm2_authblock authblock;
+	struct tpm2b_20 newAuth;
+} __attribute__((packed));
+
 struct tpm2_req_extend {
 	struct tpm_req_header hdr;
 	uint32_t pcrindex;
-- 
2.17.1



More information about the SLOF mailing list