aboutsummaryrefslogtreecommitdiff
path: root/src/tcgbios.c
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.ibm.com>2019-01-30 14:06:07 -0500
committerKevin O'Connor <kevin@koconnor.net>2019-02-04 21:23:37 -0500
commit171fc8979dc712eab7544a81ab381786ced9242c (patch)
tree47b743c1684dea95535dbdb8c803b67271d723de /src/tcgbios.c
parentb7dbd200cfe938698ed09b339ac3209ecb893648 (diff)
downloadseabios-hppa-171fc8979dc712eab7544a81ab381786ced9242c.zip
seabios-hppa-171fc8979dc712eab7544a81ab381786ced9242c.tar.gz
seabios-hppa-171fc8979dc712eab7544a81ab381786ced9242c.tar.bz2
tcgbios: Implement TPM 2.0 menu item to activate and deactivate PCR banks
Implement a TPM 2.0 menu item that allows a user to toggle the activation of PCR banks of the TPM 2.0. After successful activation we shut down the TPM 2.0 and reset the machine. Background: A TPM 2.0 may have multiple PCR banks, such as for SHA1, SHA256, SHA384, SHA512, and SM3-256. One or multiple of those banks may be active (by factory for example) and modifying the set of active PCR banks is only possible while in the firmware since it requires platform authorization. Platform authorization is not possible for a user when in the OS since the firmware generates a random password for the platform authorization before booting the system and it throws that password away. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Diffstat (limited to 'src/tcgbios.c')
-rw-r--r--src/tcgbios.c223
1 files changed, 223 insertions, 0 deletions
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;
}