From: Stefan Berger stefanb@linux.vnet.ibm.com
In the TPM 2 menu we currently only allow to run the TPM2_Clear operation. For this we follow the TCG Physical Presence Interface Specification to be found here:
http://www.trustedcomputinggroup.org/resources/tcg_physical_presence_interfa...
Table 3 shows the 'Clear' operation and the sequence of commands to send.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/std/tcg.h | 17 +++++++++ src/tcgbios.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-)
diff --git a/src/std/tcg.h b/src/std/tcg.h index d45c7f6..dd860e6 100644 --- a/src/std/tcg.h +++ b/src/std/tcg.h @@ -382,6 +382,8 @@ struct tpm_res_sha1complete { #define TPM2_ST_SESSIONS 0x8002
/* TPM 2 commands */ +#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 @@ -443,4 +445,19 @@ struct tpm2_req_extend { struct tpm2_digest_value digest; } PACKED;
+struct tpm2_req_clearcontrol { + struct tpm_req_header hdr; + u32 authhandle; + u32 authblocksize; + struct tpm2_authblock authblock; + u8 disable; +} PACKED; + +struct tpm2_req_clear { + struct tpm_req_header hdr; + u32 authhandle; + u32 authblocksize; + struct tpm2_authblock authblock; +} PACKED; + #endif // tcg.h diff --git a/src/tcgbios.c b/src/tcgbios.c index 627a374..356cef9 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -1429,6 +1429,89 @@ tpm12_process_cfg(tpm_ppi_code msgCode, int verbose) }
static int +tpm2_clearcontrol(u8 disable, int verbose) +{ + struct tpm2_req_clearcontrol trc = { + .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), + .hdr.totlen = cpu_to_be32(sizeof(trc)), + .hdr.ordinal = cpu_to_be32(TPM2_CC_ClearControl), + .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), + .authblocksize = cpu_to_be32(sizeof(trc.authblock)), + .authblock = { + .handle = cpu_to_be32(TPM2_RS_PW), + .noncesize = cpu_to_be16(0), + .contsession = TPM2_YES, + .pwdsize = cpu_to_be16(0), + }, + .disable = disable, + }; + struct tpm_rsp_header rsp; + u32 resp_length = sizeof(rsp); + int ret = tpmhw_transmit(0, &trc.hdr, &rsp, &resp_length, + TPM_DURATION_TYPE_SHORT); + if (ret || resp_length != sizeof(rsp) || rsp.errcode) + return -1; + + return 0; +} + +static int +tpm2_clear(void) +{ + struct tpm2_req_clear trq = { + .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), + .hdr.totlen = cpu_to_be32(sizeof(trq)), + .hdr.ordinal = cpu_to_be32(TPM2_CC_Clear), + .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), + .authblocksize = cpu_to_be32(sizeof(trq.authblock)), + .authblock = { + .handle = cpu_to_be32(TPM2_RS_PW), + .noncesize = cpu_to_be16(0), + .contsession = TPM2_YES, + .pwdsize = cpu_to_be16(0), + }, + }; + struct tpm_rsp_header rsp; + u32 resp_length = sizeof(rsp); + int ret = tpmhw_transmit(0, &trq.hdr, &rsp, &resp_length, + TPM_DURATION_TYPE_MEDIUM); + if (ret || resp_length != sizeof(rsp) || rsp.errcode) + return -1; + + return 0; +} + +static int +tpm2_process_cfg(tpm_ppi_code msgCode, int verbose) +{ + int ret = 0; + + switch (msgCode) { + case TPM_PPI_OP_NOOP: /* no-op */ + break; + + case TPM_PPI_OP_CLEAR: + ret = tpm2_clearcontrol(0, verbose); + if (ret) + dprintf(DEBUG_tcg, + "TCGBIOS: tpm2_clearcontrol failed\n"); + if (!ret) { + ret = tpm2_clear(); + if (ret) { + dprintf(DEBUG_tcg, + "TCGBIOS: tpm2_clear failed\n"); + } + } + break; + } + + if (ret) + printf("Op %d: An error occurred: 0x%x\n", msgCode, ret); + + return ret; +} + +static int tpm12_get_tpm_state(void) { int state = 0; @@ -1602,6 +1685,40 @@ tpm12_menu(void) } }
+static void +tpm2_menu(void) +{ + int scan_code; + tpm_ppi_code msgCode; + + for (;;) { + printf("1. Clear TPM\n"); + + printf("\nIf no change is desired or if this menu was reached by " + "mistake, press ESC to\n" + "reboot the machine.\n"); + + msgCode = TPM_PPI_OP_NOOP; + + while ((scan_code = get_keystroke(1000)) == ~0) + ; + + switch (scan_code) { + case 1: + // ESC + reset(); + break; + case 2: + msgCode = TPM_PPI_OP_CLEAR; + break; + default: + continue; + } + + tpm2_process_cfg(msgCode, 0); + } +} + void tpm_menu(void) { @@ -1617,7 +1734,7 @@ tpm_menu(void) tpm12_menu(); break; case TPM_VERSION_2: - // FIXME: missing code + tpm2_menu(); break; } }