Georg Wicherski (gw@oxff.net) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14009
-gerrit
commit 80eb817fb874d521d382e03370b179c4156bc054 Author: Georg Wicherski gw@oxff.net Date: Wed Mar 9 17:21:31 2016 +0100
TPM: Add option to read PCRs after TPM initialization
Coreboot may be used on platforms using "Measured Boot". This change adds an option to read and print all PCRs right after initialization for identifying "Measured Boot" on a mainboard and determining the resulting initial PCR stage (depending on the bootblock).
This works as expected on my Auron Paine, which apparently does not have "Measured Boot" and reports PCR contents as defined in the TPM TIS 1.2 (0s and -1s).
Add new Kconfig TPM_READ_INIT_PCRS and tlcl_pcr_read depending on the former (which is then invoked in init_tpm).
Change-Id: I79e7fdc97d500228aa574fe344ad7ac1cb0dfe64 Signed-off-by: Georg Wicherski gw@oxff.net --- src/drivers/tpm/lpc/Kconfig | 11 +++++++++++ src/include/tpm/tss.h | 5 +++++ src/lib/tpm/tspi.c | 35 +++++++++++++++++++++++++++++++++++ src/lib/tpm/tss.c | 23 ++++++++++++++++++++--- 4 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/src/drivers/tpm/lpc/Kconfig b/src/drivers/tpm/lpc/Kconfig index e377e99..ec17782 100644 --- a/src/drivers/tpm/lpc/Kconfig +++ b/src/drivers/tpm/lpc/Kconfig @@ -13,6 +13,17 @@ config LPC_TPM
If unsure, say N.
+config TPM_READ_INIT_PCRS + bool "Read PCR values after initialization" + depends on LPC_TPM + default n + help + Read (and print) initial PCR values at end of TPM initialization. + This is useful for identifying "Measured Boot" and verifying that + the TPM is adhering to TPM TIS 1.2 PCR initial values. + + If unsure, say N. + config TPM_TIS_BASE_ADDRESS hex default 0xfed40000 diff --git a/src/include/tpm/tss.h b/src/include/tpm/tss.h index 04ad9b3..b940e9c 100644 --- a/src/include/tpm/tss.h +++ b/src/include/tpm/tss.h @@ -129,6 +129,11 @@ uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest);
/** + * Read current PCR digest + */ +uint32_t tlcl_pcr_read(int pcr_num, uint8_t *out_digest); + +/** * Get the entire set of permanent flags. */ uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags); diff --git a/src/lib/tpm/tspi.c b/src/lib/tpm/tspi.c index 0114af8..0d9c6aa 100644 --- a/src/lib/tpm/tspi.c +++ b/src/lib/tpm/tspi.c @@ -19,8 +19,40 @@ #include <reset.h>
#include <tpm/tss.h> +#define TPM_PCR_DIGEST_LENGTH 20 #include <tpm/tspi.h>
+static inline void _debug_init_pcrs(void) +{ + uint32_t result; + int pcr_index; + uint8_t digest[TPM_PCR_DIGEST_LENGTH]; + + for (pcr_index = 0; pcr_index < 24; ++pcr_index) { + int digest_offset; + + result = tlcl_pcr_read(pcr_index, digest); + + if (result != TPM_SUCCESS) { + printk(BIOS_DEBUG, + "TPM: reading PCR %i failed\n", + pcr_index); + continue; + } + + printk(BIOS_SPEW, "TPM: PCR %i value is ", + pcr_index); + for (digest_offset = 0; + digest_offset < TPM_PCR_DIGEST_LENGTH; + ++digest_offset) { + printk(BIOS_SPEW, "%02x%c", + digest[digest_offset], + digest_offset < TPM_PCR_DIGEST_LENGTH - 1 ? + ':' : '\n'); + } + } +} + void init_tpm(int s3resume) { u32 result = 0; @@ -76,6 +108,9 @@ void init_tpm(int s3resume) }
if (result == TPM_SUCCESS) { + if (IS_ENABLED(CONFIG_TPM_READ_INIT_PCRS)) + _debug_init_pcrs(); + printk(BIOS_SPEW, "TPM: OK.\n"); return; } diff --git a/src/lib/tpm/tss.c b/src/lib/tpm/tss.c index a22aa15..8f38504 100644 --- a/src/lib/tpm/tss.c +++ b/src/lib/tpm/tss.c @@ -116,7 +116,7 @@ return result; uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response, int max_length) { uint32_t result = tlcl_send_receive_no_retry(request, response, - max_length); + max_length); /* If the command fails because the self test has not completed, try it * again after attempting to ensure that the self test has completed. */ if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) { @@ -303,7 +303,7 @@ uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags) from_tpm_uint32(response + kTpmResponseHeaderLength, &size); assert(size == sizeof(TPM_PERMANENT_FLAGS)); memcpy(pflags, response + kTpmResponseHeaderLength + sizeof(size), - sizeof(TPM_PERMANENT_FLAGS)); + sizeof(TPM_PERMANENT_FLAGS)); return result; }
@@ -351,6 +351,23 @@ uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest,
if (out_digest) memcpy(out_digest, response + kTpmResponseHeaderLength, - kPcrDigestLength); + kPcrDigestLength); + return result; +} + +uint32_t tlcl_pcr_read(int pcr_num, uint8_t *out_digest) +{ + struct s_tpm_pcr_read_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result; + + memcpy(&cmd, &tpm_pcr_read_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_pcr_read_cmd.pcrNum, pcr_num); + + result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); + if (result == TPM_SUCCESS) + memcpy(out_digest, response + kTpmResponseHeaderLength, + kPcrDigestLength); + return result; }