aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/std/tcg.h17
-rw-r--r--src/tcgbios.c223
2 files changed, 240 insertions, 0 deletions
diff --git a/src/std/tcg.h b/src/std/tcg.h
index 09a92d8..1cc1c92 100644
--- a/src/std/tcg.h
+++ b/src/std/tcg.h
@@ -336,6 +336,12 @@ struct tpm_res_sha1complete {
#define TPM2_ALG_SHA512 0x000d
#define TPM2_ALG_SM3_256 0x0012
+#define TPM2_ALG_SHA1_FLAG (1 << 0)
+#define TPM2_ALG_SHA256_FLAG (1 << 1)
+#define TPM2_ALG_SHA384_FLAG (1 << 2)
+#define TPM2_ALG_SHA512_FLAG (1 << 3)
+#define TPM2_ALG_SM3_256_FLAG (1 << 4)
+
/* TPM 2 command tags */
#define TPM2_ST_NO_SESSIONS 0x8001
#define TPM2_ST_SESSIONS 0x8002
@@ -345,8 +351,10 @@ struct tpm_res_sha1complete {
#define TPM2_CC_Clear 0x126
#define TPM2_CC_ClearControl 0x127
#define TPM2_CC_HierarchyChangeAuth 0x129
+#define TPM2_CC_PCR_Allocate 0x12b
#define TPM2_CC_SelfTest 0x143
#define TPM2_CC_Startup 0x144
+#define TPM2_CC_Shutdown 0x145
#define TPM2_CC_StirRandom 0x146
#define TPM2_CC_GetCapability 0x17a
#define TPM2_CC_GetRandom 0x17b
@@ -442,6 +450,15 @@ struct tpm2_res_getcapability {
u8 data[0]; /* capability dependent data */
} PACKED;
+struct tpm2_req_pcr_allocate {
+ struct tpm_req_header hdr;
+ u32 authhandle;
+ u32 authblocksize;
+ struct tpm2_authblock authblock;
+ u32 count;
+ u8 tpms_pcr_selections[4];
+} PACKED;
+
struct tpms_pcr_selection {
u16 hashAlg;
u8 sizeOfSelect;
diff --git a/src/tcgbios.c b/src/tcgbios.c
index 0eabc60..2e503f9 100644
--- a/src/tcgbios.c
+++ b/src/tcgbios.c
@@ -163,23 +163,35 @@ struct tpm_log_entry {
static const struct hash_parameters {
u16 hashalg;
+ u8 hashalg_flag;
u8 hash_buffersize;
+ const char *name;
} hash_parameters[] = {
{
.hashalg = TPM2_ALG_SHA1,
+ .hashalg_flag = TPM2_ALG_SHA1_FLAG,
.hash_buffersize = SHA1_BUFSIZE,
+ .name = "SHA1",
}, {
.hashalg = TPM2_ALG_SHA256,
+ .hashalg_flag = TPM2_ALG_SHA256_FLAG,
.hash_buffersize = SHA256_BUFSIZE,
+ .name = "SHA256",
}, {
.hashalg = TPM2_ALG_SHA384,
+ .hashalg_flag = TPM2_ALG_SHA384_FLAG,
.hash_buffersize = SHA384_BUFSIZE,
+ .name = "SHA384",
}, {
.hashalg = TPM2_ALG_SHA512,
+ .hashalg_flag = TPM2_ALG_SHA512_FLAG,
.hash_buffersize = SHA512_BUFSIZE,
+ .name = "SHA512",
}, {
.hashalg = TPM2_ALG_SM3_256,
+ .hashalg_flag = TPM2_ALG_SM3_256_FLAG,
.hash_buffersize = SM3_256_BUFSIZE,
+ .name = "SM3-256",
}
};
@@ -195,6 +207,42 @@ tpm20_get_hash_buffersize(u16 hashAlg)
return -1;
}
+static u8
+tpm20_hashalg_to_flag(u16 hashAlg)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
+ if (hash_parameters[i].hashalg == hashAlg)
+ return hash_parameters[i].hashalg_flag;
+ }
+ return 0;
+}
+
+static u16
+tpm20_hashalg_flag_to_hashalg(u8 hashalg_flag)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
+ if (hash_parameters[i].hashalg_flag == hashalg_flag)
+ return hash_parameters[i].hashalg;
+ }
+ return 0;
+}
+
+static const char *
+tpm20_hashalg_flag_to_name(u8 hashalg_flag)
+{
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) {
+ if (hash_parameters[i].hashalg_flag == hashalg_flag)
+ return hash_parameters[i].name;
+ }
+ return NULL;
+}
+
// Add an entry at the start of the log describing digest formats
static int
tpm20_write_EfiSpecIdEventStruct(void)
@@ -448,6 +496,115 @@ tpm20_get_pcrbanks(void)
}
static int
+tpm20_get_suppt_pcrbanks(u8 *suppt_pcrbanks, u8 *active_pcrbanks)
+{
+ *suppt_pcrbanks = 0;
+ *active_pcrbanks = 0;
+
+ if (!tpm20_pcr_selection)
+ return -1;
+
+ struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections;
+ void *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size;
+
+ while (1) {
+ u8 sizeOfSelect = sel->sizeOfSelect;
+ void *nsel = (void*)sel + sizeof(*sel) + sizeOfSelect;
+ if (nsel > end)
+ return 0;
+
+ u16 hashalg = be16_to_cpu(sel->hashAlg);
+ u8 hashalg_flag = tpm20_hashalg_to_flag(hashalg);
+
+ *suppt_pcrbanks |= hashalg_flag;
+
+ unsigned i;
+ for (i = 0; i < sizeOfSelect; i++) {
+ if (sel->pcrSelect[i]) {
+ *active_pcrbanks |= hashalg_flag;
+ break;
+ }
+ }
+
+ sel = nsel;
+ }
+}
+
+static int
+tpm20_set_pcrbanks(u32 active_banks)
+{
+ struct tpm2_req_pcr_allocate trpa = {
+ .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS),
+ .hdr.ordinal = cpu_to_be32(TPM2_CC_PCR_Allocate),
+ .authhandle = cpu_to_be32(TPM2_RH_PLATFORM),
+ .authblocksize = cpu_to_be32(sizeof(trpa.authblock)),
+ .authblock = {
+ .handle = cpu_to_be32(TPM2_RS_PW),
+ .noncesize = cpu_to_be16(0),
+ .contsession = TPM2_YES,
+ .pwdsize = cpu_to_be16(0),
+ },
+ };
+ struct tpms_pcr_selection3 {
+ u16 hashAlg;
+ u8 sizeOfSelect;
+ u8 pcrSelect[3];
+ } tps[ARRAY_SIZE(trpa.tpms_pcr_selections)];
+ int i = 0;
+ u8 hashalg_flag = TPM2_ALG_SHA1_FLAG;
+ u8 dontcare, suppt_banks;
+
+ tpm20_get_suppt_pcrbanks(&suppt_banks, &dontcare);
+
+ while (hashalg_flag) {
+ if ((hashalg_flag & suppt_banks)) {
+ u16 hashalg = tpm20_hashalg_flag_to_hashalg(hashalg_flag);
+
+ if (hashalg) {
+ u8 mask = 0;
+ tps[i].hashAlg = cpu_to_be16(hashalg);
+ tps[i].sizeOfSelect = 3;
+
+ if (active_banks & hashalg_flag)
+ mask = 0xff;
+
+ tps[i].pcrSelect[0] = mask;
+ tps[i].pcrSelect[1] = mask;
+ tps[i].pcrSelect[2] = mask;
+ i++;
+ }
+ }
+ hashalg_flag <<= 1;
+ }
+
+ trpa.count = cpu_to_be32(i);
+ memcpy(trpa.tpms_pcr_selections, tps, i * sizeof(tps[0]));
+ trpa.hdr.totlen = cpu_to_be32(offsetof(struct tpm2_req_pcr_allocate,
+ tpms_pcr_selections) +
+ i * sizeof(tps[0]));
+
+ struct tpm_rsp_header rsp;
+ u32 resp_length = sizeof(rsp);
+
+ int ret = tpmhw_transmit(0, &trpa.hdr, &rsp, &resp_length,
+ TPM_DURATION_TYPE_SHORT);
+ ret = ret ? -1 : be32_to_cpu(rsp.errcode);
+
+ return ret;
+}
+
+static int tpm20_activate_pcrbanks(u32 active_banks)
+{
+ int ret = tpm20_set_pcrbanks(active_banks);
+ if (!ret)
+ ret = tpm_simple_cmd(0, TPM2_CC_Shutdown,
+ 2, TPM2_SU_CLEAR, TPM_DURATION_TYPE_SHORT);
+ if (!ret)
+ reset();
+ return ret;
+}
+
+static int
tpm12_get_capability(u32 cap, u32 subcap, struct tpm_rsp_header *rsp, u32 rsize)
{
struct tpm_req_getcap trgc = {
@@ -1962,6 +2119,68 @@ tpm12_menu(void)
}
}
+static int
+tpm20_menu_change_active_pcrbanks(void)
+{
+ u8 active_banks, suppt_banks;
+
+ tpm20_get_suppt_pcrbanks(&suppt_banks, &active_banks);
+
+ u8 activate_banks = active_banks;
+
+ while (1) {
+ u8 hashalg_flag = TPM2_ALG_SHA1_FLAG;
+ u8 i = 0;
+
+ printf("\nToggle active PCR banks by pressing number key\n\n");
+
+ while (hashalg_flag) {
+ u8 flag = hashalg_flag & suppt_banks;
+ const char *hashname = tpm20_hashalg_flag_to_name(flag);
+
+ i++;
+ if (hashname) {
+ printf(" %d: %s", i, hashname);
+ if (activate_banks & hashalg_flag)
+ printf(" (enabled)");
+ printf("\n");
+ }
+
+ hashalg_flag <<= 1;
+ }
+ printf("\n"
+ "ESC: return to previous menu without changes\n");
+ if (activate_banks)
+ printf("A : activate selection\n");
+
+ u8 flagnum;
+ int show = 0;
+ while (!show) {
+ int scancode = get_keystroke(1000);
+
+ switch (scancode) {
+ case ~0:
+ continue;
+ case 1: /* ESC */
+ printf("\n");
+ return -1;
+ case 2 ... 6: /* keys 1 .. 5 */
+ flagnum = scancode - 1;
+ if (flagnum > i)
+ continue;
+ if (suppt_banks & (1 << (flagnum - 1))) {
+ activate_banks ^= 1 << (flagnum - 1);
+ show = 1;
+ }
+ break;
+ case 30: /* a */
+ if (activate_banks)
+ tpm20_activate_pcrbanks(activate_banks);
+ }
+ }
+ }
+}
+
static void
tpm20_menu(void)
{
@@ -1970,6 +2189,7 @@ tpm20_menu(void)
for (;;) {
printf("1. Clear TPM\n");
+ printf("2. Change active PCR banks\n");
printf("\nIf no change is desired or if this menu was reached by "
"mistake, press ESC to\n"
@@ -1988,6 +2208,9 @@ tpm20_menu(void)
case 2:
msgCode = TPM_PPI_OP_CLEAR;
break;
+ case 3:
+ tpm20_menu_change_active_pcrbanks();
+ continue;
default:
continue;
}