[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