Patch 1 fixes the return of a missing digest in the HashLogExtendEvent command.
Beyond that the patches extend the handling of physical presence to HW physical presence and rework the showing of the TPM menu to depend on whether SW physical presence could be asserted or HW physical presence has been found to be enabled.
Regards, Stefan
v1->v2: Addressed Kevin's comments v2->v3: Addressed Kevin's comments
Stefan Berger (6): tpm: Copy digest into HashLogExentEvent response tpm: Move assert_physical_presence and dependencies tpm: Add support for harware physical presence tpm: Rework the assertion of physical presence tpm: Remove usage of PP_CMD_ENABLE from all but one place tpm: Do not set TPM in failure mode if menu command fails
src/boot.c | 4 +- src/std/tcg.h | 1 + src/tcgbios.c | 243 +++++++++++++++++++++------------------------------------- src/tcgbios.h | 2 +- 4 files changed, 90 insertions(+), 160 deletions(-)
From: Stefan Berger stefanb@linux.vnet.ibm.com
Copy the digest into the response of a HashLogExtendEvent API call.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/tcgbios.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 1a247df..8716600 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -660,6 +660,7 @@ hash_log_extend_event_int(const struct hleei_short *hleei_s, hleeo->opblength = sizeof(struct hleeo); hleeo->reserved = 0; hleeo->eventnumber = hleo.eventnumber; + memcpy(hleeo->digest, pcpes->digest, sizeof(hleeo->digest));
err_exit: if (rc != 0) {
From: Stefan Berger stefanb@linux.vnet.ibm.com
Move assert_physical_presence and dependencies in front of tpm_startup so that the next patches can assert physical presence after TPM_ORD_Startup ran.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/tcgbios.c | 150 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 75 insertions(+), 75 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 8716600..aa93e5e 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -396,6 +396,81 @@ tpm_smbios_measure(void) }
static int +read_stclear_flags(char *buf, int buf_len) +{ + memset(buf, 0, buf_len); + + struct tpm_res_getcap_stclear_flags stcf; + int ret = tpm_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_VOLATILE + , &stcf.hdr, sizeof(stcf)); + if (ret) { + dprintf(DEBUG_tcg, "Error reading STClear flags: 0x%08x\n", ret); + return -1; + } + + memcpy(buf, &stcf.stclear_flags, buf_len); + + return 0; +} + +static int +read_permanent_flags(char *buf, int buf_len) +{ + memset(buf, 0, buf_len); + + struct tpm_res_getcap_perm_flags pf; + int ret = tpm_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_PERMANENT + , &pf.hdr, sizeof(pf)); + if (ret) + return -1; + + memcpy(buf, &pf.perm_flags, buf_len); + + return 0; +} + +static int +assert_physical_presence(int verbose) +{ + struct tpm_stclear_flags stcf; + int ret = read_stclear_flags((char *)&stcf, sizeof(stcf)); + if (ret) + return -1; + + if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE]) + /* physical presence already asserted */ + return 0; + + ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_CMD_ENABLE, + sizeof(PhysicalPresence_CMD_ENABLE), + TPM_DURATION_TYPE_SHORT); + if (ret) { + if (verbose) + printf("Error: Could not enable physical presence.\n\n"); + goto err_exit; + } + + ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_PRESENT, + sizeof(PhysicalPresence_PRESENT), + TPM_DURATION_TYPE_SHORT); + if (ret) { + if (verbose) + printf("Error: Could not set presence flag.\n\n"); + goto err_exit; + } + + return 0; + +err_exit: + dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); + tpm_set_failure(); + dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed: %x\n", ret); + return -1; +} + +static int tpm_startup(void) { dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n"); @@ -881,81 +956,6 @@ tpm_interrupt_handler32(struct bregs *regs) ****************************************************************/
static int -read_stclear_flags(char *buf, int buf_len) -{ - memset(buf, 0, buf_len); - - struct tpm_res_getcap_stclear_flags stcf; - int ret = tpm_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_VOLATILE - , &stcf.hdr, sizeof(stcf)); - if (ret) { - dprintf(DEBUG_tcg, "Error reading STClear flags: 0x%08x\n", ret); - return -1; - } - - memcpy(buf, &stcf.stclear_flags, buf_len); - - return 0; -} - -static int -assert_physical_presence(int verbose) -{ - struct tpm_stclear_flags stcf; - int ret = read_stclear_flags((char *)&stcf, sizeof(stcf)); - if (ret) - return -1; - - if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE]) - /* physical presence already asserted */ - return 0; - - ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_CMD_ENABLE, - sizeof(PhysicalPresence_CMD_ENABLE), - TPM_DURATION_TYPE_SHORT); - if (ret) { - if (verbose) - printf("Error: Could not enable physical presence.\n\n"); - goto err_exit; - } - - ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_PRESENT, - sizeof(PhysicalPresence_PRESENT), - TPM_DURATION_TYPE_SHORT); - if (ret) { - if (verbose) - printf("Error: Could not set presence flag.\n\n"); - goto err_exit; - } - - return 0; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - tpm_set_failure(); - dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed: %x\n", ret); - return -1; -} - -static int -read_permanent_flags(char *buf, int buf_len) -{ - memset(buf, 0, buf_len); - - struct tpm_res_getcap_perm_flags pf; - int ret = tpm_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_PERMANENT - , &pf.hdr, sizeof(pf)); - if (ret) - return -1; - - memcpy(buf, &pf.perm_flags, buf_len); - - return 0; -} - -static int read_has_owner(int *has_owner) { struct tpm_res_getcap_ownerauth oauth;
From: Stefan Berger stefanb@linux.vnet.ibm.com
Extend assert_physical_presence with checks for hardware physical presence support. If hardware physical presence is enabled, we return 0.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/std/tcg.h | 1 + src/tcgbios.c | 79 +++++++++++++++++++++-------------------------------------- 2 files changed, 29 insertions(+), 51 deletions(-)
diff --git a/src/std/tcg.h b/src/std/tcg.h index 9f7f021..91692e9 100644 --- a/src/std/tcg.h +++ b/src/std/tcg.h @@ -285,6 +285,7 @@ enum permFlagsIndex { PERM_FLAG_IDX_ALLOW_MAINTENANCE, PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK, PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE, + PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE, };
diff --git a/src/tcgbios.c b/src/tcgbios.c index aa93e5e..545e9b6 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -396,24 +396,6 @@ tpm_smbios_measure(void) }
static int -read_stclear_flags(char *buf, int buf_len) -{ - memset(buf, 0, buf_len); - - struct tpm_res_getcap_stclear_flags stcf; - int ret = tpm_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_VOLATILE - , &stcf.hdr, sizeof(stcf)); - if (ret) { - dprintf(DEBUG_tcg, "Error reading STClear flags: 0x%08x\n", ret); - return -1; - } - - memcpy(buf, &stcf.stclear_flags, buf_len); - - return 0; -} - -static int read_permanent_flags(char *buf, int buf_len) { memset(buf, 0, buf_len); @@ -430,43 +412,38 @@ read_permanent_flags(char *buf, int buf_len) }
static int -assert_physical_presence(int verbose) +assert_physical_presence(void) { - struct tpm_stclear_flags stcf; - int ret = read_stclear_flags((char *)&stcf, sizeof(stcf)); + int ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_PRESENT, + sizeof(PhysicalPresence_PRESENT), + TPM_DURATION_TYPE_SHORT); + if (!ret) + return 0; + + struct tpm_permanent_flags pf; + ret = read_permanent_flags((char *)&pf, sizeof(pf)); if (ret) return -1;
- if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE]) - /* physical presence already asserted */ + /* check if hardware physical presence is supported */ + if (pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]) { + /* HW phys. presence may not be asserted... */ return 0; - - ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_CMD_ENABLE, - sizeof(PhysicalPresence_CMD_ENABLE), - TPM_DURATION_TYPE_SHORT); - if (ret) { - if (verbose) - printf("Error: Could not enable physical presence.\n\n"); - goto err_exit; }
- ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_PRESENT, - sizeof(PhysicalPresence_PRESENT), - TPM_DURATION_TYPE_SHORT); - if (ret) { - if (verbose) - printf("Error: Could not set presence flag.\n\n"); - goto err_exit; + if (!pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK] + && !pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]) { + build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_CMD_ENABLE, + sizeof(PhysicalPresence_CMD_ENABLE), + TPM_DURATION_TYPE_SHORT); + + return build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_PRESENT, + sizeof(PhysicalPresence_PRESENT), + TPM_DURATION_TYPE_SHORT); } - - return 0; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - tpm_set_failure(); - dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed: %x\n", ret); return -1; }
@@ -980,7 +957,7 @@ enable_tpm(int enable, int verbose) if (pf.flags[PERM_FLAG_IDX_DISABLE] && !enable) return 0;
- ret = assert_physical_presence(verbose); + ret = assert_physical_presence(); if (ret) return -1;
@@ -1018,7 +995,7 @@ activate_tpm(int activate, int allow_reset, int verbose) if (pf.flags[PERM_FLAG_IDX_DISABLE]) return 0;
- ret = assert_physical_presence(verbose); + ret = assert_physical_presence(); if (ret) return -1;
@@ -1081,7 +1058,7 @@ force_clear(int enable_activate_before, int enable_activate_after, int verbose) } }
- ret = assert_physical_presence(verbose); + ret = assert_physical_presence(); if (ret) return -1;
@@ -1130,7 +1107,7 @@ set_owner_install(int allow, int verbose) return 0; }
- ret = assert_physical_presence(verbose); + ret = assert_physical_presence(); if (ret) return -1;
From: Stefan Berger stefanb@linux.vnet.ibm.com
Rework the assertion of physical presence by calling assert_physical_presence in tpm_setup. This call will assert physical presence if SW assertion is possible or by checking whether HW physical presence is enabled. The TPM menu will only be shown if physical presence is asserted or HW physical presence is enabled after this call.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/boot.c | 4 ++-- src/tcgbios.c | 31 ++++++++++++++----------------- src/tcgbios.h | 2 +- 3 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/boot.c b/src/boot.c index a251eb4..a045a8e 100644 --- a/src/boot.c +++ b/src/boot.c @@ -486,7 +486,7 @@ interactive_bootmenu(void) printf("%d. %s\n", maxmenu , strtcpy(desc, pos->description, ARRAY_SIZE(desc))); } - if (tpm_is_working()) { + if (tpm_can_show_menu()) { printf("\nt. TPM Configuration\n"); }
@@ -499,7 +499,7 @@ interactive_bootmenu(void) scan_code = get_keystroke(1000); if (scan_code == 1 && !irqtimer_check(esc_accepted_time)) continue; - if (tpm_is_working() && scan_code == 20 /* t */) { + if (tpm_can_show_menu() && scan_code == 20 /* t */) { printf("\n"); tpm_menu(); } diff --git a/src/tcgbios.c b/src/tcgbios.c index 545e9b6..ceeb5fb 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -60,6 +60,8 @@ struct { u8 * log_area_last_entry; } tpm_state VARLOW;
+static int TPM_has_physical_presence; + static struct tcpa_descriptor_rev2 * find_tcpa_by_rsdp(struct rsdp_descriptor *rsdp) { @@ -158,12 +160,18 @@ tpm_log_event(struct pcpes *pcpes, const void *event)
u8 TPM_working VARLOW;
-int +static int tpm_is_working(void) { return CONFIG_TCGBIOS && TPM_working; }
+int +tpm_can_show_menu(void) +{ + return tpm_is_working() && TPM_has_physical_presence; +} + /* * Send a TPM command with the given ordinal. Append the given buffer * containing all data in network byte order to the command (this is @@ -462,6 +470,11 @@ tpm_startup(void) if (ret) goto err_exit;
+ /* assertion of physical presence is only possible after startup */ + ret = assert_physical_presence(); + if (!ret) + TPM_has_physical_presence = 1; + ret = determine_timeouts(); if (ret) return -1; @@ -957,10 +970,6 @@ enable_tpm(int enable, int verbose) if (pf.flags[PERM_FLAG_IDX_DISABLE] && !enable) return 0;
- ret = assert_physical_presence(); - if (ret) - return -1; - ret = build_and_send_cmd(0, enable ? TPM_ORD_PhysicalEnable : TPM_ORD_PhysicalDisable, NULL, 0, TPM_DURATION_TYPE_SHORT); @@ -995,10 +1004,6 @@ activate_tpm(int activate, int allow_reset, int verbose) if (pf.flags[PERM_FLAG_IDX_DISABLE]) return 0;
- ret = assert_physical_presence(); - if (ret) - return -1; - ret = build_and_send_cmd(0, TPM_ORD_PhysicalSetDeactivated, activate ? CommandFlag_FALSE : CommandFlag_TRUE, @@ -1058,10 +1063,6 @@ force_clear(int enable_activate_before, int enable_activate_after, int verbose) } }
- ret = assert_physical_presence(); - if (ret) - return -1; - ret = build_and_send_cmd(0, TPM_ORD_ForceClear, NULL, 0, TPM_DURATION_TYPE_SHORT); if (ret) @@ -1107,10 +1108,6 @@ set_owner_install(int allow, int verbose) return 0; }
- ret = assert_physical_presence(); - if (ret) - return -1; - ret = build_and_send_cmd(0, TPM_ORD_SetOwnerInstall, (allow) ? CommandFlag_TRUE : CommandFlag_FALSE, diff --git a/src/tcgbios.h b/src/tcgbios.h index 6040b0c..32fb941 100644 --- a/src/tcgbios.h +++ b/src/tcgbios.h @@ -13,7 +13,7 @@ void tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length); void tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length); void tpm_add_cdrom_catalog(const u8 *addr, u32 length); void tpm_option_rom(const void *addr, u32 len); -int tpm_is_working(void); +int tpm_can_show_menu(void); void tpm_menu(void);
#endif /* TCGBIOS_H */
From: Stefan Berger stefanb@linux.vnet.ibm.com
Remove the usage of PhysicalPresence_CMD_ENABLE from all but the assert_physical_presence function.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/tcgbios.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index ceeb5fb..31e1435 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -211,16 +211,10 @@ build_and_send_cmd(u8 locty, u32 ordinal, const u8 *append, u32 append_size, static void tpm_set_failure(void) { - /* we will try to deactivate the TPM now - ignoring all errors */ - build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_CMD_ENABLE, - sizeof(PhysicalPresence_CMD_ENABLE), - TPM_DURATION_TYPE_SHORT); - - build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_PRESENT, - sizeof(PhysicalPresence_PRESENT), - TPM_DURATION_TYPE_SHORT); + /* + * We will try to deactivate the TPM now - ignoring all errors + * Physical presence is asserted. + */
build_and_send_cmd(0, TPM_ORD_SetTempDeactivated, NULL, 0, TPM_DURATION_TYPE_SHORT); @@ -528,32 +522,17 @@ tpm_setup(void) void tpm_prepboot(void) { - if (!tpm_is_working()) + if (!CONFIG_TCGBIOS) return;
- int ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_CMD_ENABLE, - sizeof(PhysicalPresence_CMD_ENABLE), - TPM_DURATION_TYPE_SHORT); - if (ret) - goto err_exit; - - ret = build_and_send_cmd(0, TPM_ORD_PhysicalPresence, - PhysicalPresence_NOT_PRESENT_LOCK, - sizeof(PhysicalPresence_NOT_PRESENT_LOCK), - TPM_DURATION_TYPE_SHORT); - if (ret) - goto err_exit; + if (TPM_has_physical_presence) + build_and_send_cmd(0, TPM_ORD_PhysicalPresence, + PhysicalPresence_NOT_PRESENT_LOCK, + sizeof(PhysicalPresence_NOT_PRESENT_LOCK), + TPM_DURATION_TYPE_SHORT);
tpm_add_action(4, "Calling INT 19h"); tpm_add_event_separators(); - - return; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); }
/*
From: Stefan Berger stefanb@linux.vnet.ibm.com
Since we may detect that HW physical presence is enabled but we do not detect whether it is actually asserted, we may fail on the TPM menu commands that require the assertion of physical presence. We therefore cannot set the TPM into failure mode if we hit this case. Failure should never occur in these cases if SW physical presence has been asserted.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/tcgbios.c | 43 +++++++++---------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 31e1435..7077426 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -952,20 +952,12 @@ enable_tpm(int enable, int verbose) ret = build_and_send_cmd(0, enable ? TPM_ORD_PhysicalEnable : TPM_ORD_PhysicalDisable, NULL, 0, TPM_DURATION_TYPE_SHORT); - if (ret) - goto err_exit; - - return 0; - -err_exit: - if (enable) - dprintf(DEBUG_tcg, "TCGBIOS: Enabling the TPM failed.\n"); - else - dprintf(DEBUG_tcg, "TCGBIOS: Disabling the TPM failed.\n"); - - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); + if (ret) { + if (enable) + dprintf(DEBUG_tcg, "TCGBIOS: Enabling the TPM failed.\n"); + else + dprintf(DEBUG_tcg, "TCGBIOS: Disabling the TPM failed.\n"); + } return ret; }
@@ -990,7 +982,7 @@ activate_tpm(int activate, int allow_reset, int verbose) : sizeof(CommandFlag_TRUE), TPM_DURATION_TYPE_SHORT); if (ret) - goto err_exit; + return ret;
if (activate && allow_reset) { if (verbose) { @@ -1002,12 +994,6 @@ activate_tpm(int activate, int allow_reset, int verbose) }
return 0; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); - return ret; }
static int @@ -1045,7 +1031,7 @@ force_clear(int enable_activate_before, int enable_activate_after, int verbose) ret = build_and_send_cmd(0, TPM_ORD_ForceClear, NULL, 0, TPM_DURATION_TYPE_SHORT); if (ret) - goto err_exit; + return ret;
if (!enable_activate_after) { if (verbose) @@ -1055,12 +1041,6 @@ force_clear(int enable_activate_before, int enable_activate_after, int verbose) }
return enable_activate(1, verbose); - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); - return ret; }
static int @@ -1093,17 +1073,12 @@ set_owner_install(int allow, int verbose) sizeof(CommandFlag_TRUE), TPM_DURATION_TYPE_SHORT); if (ret) - goto err_exit; + return ret;
if (verbose) printf("Installation of owner %s.\n", allow ? "enabled" : "disabled");
return 0; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - tpm_set_failure(); - return ret; }
static int
On Thu, Jan 07, 2016 at 12:02:45PM -0500, Stefan Berger wrote:
Patch 1 fixes the return of a missing digest in the HashLogExtendEvent command.
Beyond that the patches extend the handling of physical presence to HW physical presence and rework the showing of the TPM menu to depend on whether SW physical presence could be asserted or HW physical presence has been found to be enabled.
Thanks - if there are no further comments, I'll commit in a couple of days.
-Kevin
On Thu, Jan 07, 2016 at 12:02:45PM -0500, Stefan Berger wrote:
Patch 1 fixes the return of a missing digest in the HashLogExtendEvent command.
Beyond that the patches extend the handling of physical presence to HW physical presence and rework the showing of the TPM menu to depend on whether SW physical presence could be asserted or HW physical presence has been found to be enabled.
Thanks - I committed this series.
-Kevin