From: Stefan Berger stefanb@linux.vnet.ibm.com
Extend assert_physical_presence with checks for hardware physical presence support. If no hardware physical presence is asserted and the SW assertion is disable, -1 is returned.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/std/tcg.h | 2 ++ src/tcgbios.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/src/std/tcg.h b/src/std/tcg.h index 9f7f021..00be533 100644 --- a/src/std/tcg.h +++ b/src/std/tcg.h @@ -70,6 +70,7 @@
/* TPM command error codes */ #define TPM_INVALID_POSTINIT 0x26 +#define TPM_BAD_PRESENCE 0x2d #define TPM_BAD_LOCALITY 0x3d
/* TPM command tags */ @@ -285,6 +286,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 d6a8495..6a6b6b0 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -446,7 +446,7 @@ err_exit: return -1; }
-static u32 +static int read_stclear_flags(char *buf, int buf_len) { memset(buf, 0, buf_len); @@ -480,7 +480,32 @@ read_permanent_flags(char *buf, int buf_len) return 0; }
-static u32 +static int +has_hw_physical_presence(struct tpm_permanent_flags *pf, int *has_hw_pp) +{ + u32 ordinal; + + /* We cannot read hardware physical presence from a flag; + * it has to be inferred from the error code to a command that + * needs physical presence + */ + if (pf->flags[PERM_FLAG_IDX_DISABLE]) + ordinal = TPM_ORD_PhysicalDisable; + else + ordinal = TPM_ORD_PhysicalEnable; + + int ret = tpm_send_cmd(0, ordinal, NULL, 0, TPM_DURATION_TYPE_SHORT); + if (ret == TPM_BAD_PRESENCE) { + ret = 0; + *has_hw_pp = 0; + } else { + *has_hw_pp = 1; + } + + return ret; +} + +static int assert_physical_presence(int verbose) { struct tpm_stclear_flags stcf; @@ -492,6 +517,38 @@ assert_physical_presence(int verbose) /* physical presence already asserted */ return 0;
+ struct tpm_permanent_flags pf; + ret = read_permanent_flags((char *)&pf, sizeof(pf)); + if (ret) + return -1; + + /* check if hardware physical presence is supported and asserted */ + if (pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]) { + int has_hw_pp; + ret = has_hw_physical_presence(&pf, &has_hw_pp); + if (verbose && !has_hw_pp) + printf("Hardware physical presence is not asserted.\n\n"); + if (ret) + return ret; + + if (has_hw_pp) + return 0; + + if (!pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]) { + /* cannot enable phys. presence using command */ + if (verbose) + printf("Error: Physical presence SW assertion is disabled.\n\n"); + return -1; + } + } + + if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE_LOCK]) { + /* physical presence cannot be changed anymore */ + if (verbose) + printf("Error: Physical presence assertion is locked.\n\n"); + return -1; + } + ret = tpm_send_check_cmd(0, TPM_ORD_PhysicalPresence, PhysicalPresence_CMD_ENABLE, sizeof(PhysicalPresence_CMD_ENABLE),