The parameters for extending the PCRs of a TPM 2 are written in big endian format when sent to the TPM. However, the log needs to be written in little endian format, so we cannot just copy the structure into the log as-is. To support the little endian format in the log, we extend the function writing the TPM 2 digest structure with a parameter that allows us to choose the endianess of a few parameters. We then rewrite the digest structure in little endian format for the log.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/tcgbios.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index 4cff4ce..fea88a6 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -311,11 +311,13 @@ tpm20_write_EfiSpecIdEventStruct(void) * * le: the log entry to build the digest in * sha1: the sha1 hash value to use + * bigEndian: whether to build in big endian format for the TPM or + * little endian for the log * * Returns the digest size; -1 on fatal error */ static int -tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1) +tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) { if (!tpm20_pcr_selection) return -1; @@ -346,7 +348,11 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1) return -1; }
- v->hashAlg = sel->hashAlg; + if (bigEndian) + v->hashAlg = sel->hashAlg; + else + v->hashAlg = be16_to_cpu(sel->hashAlg); + memset(v->hash, 0, hsize); memcpy(v->hash, sha1, hsize > SHA1_BUFSIZE ? SHA1_BUFSIZE : hsize);
@@ -360,7 +366,10 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1) }
struct tpm2_digest_values *v = (void*)le->hdr.digest; - v->count = cpu_to_be32(count); + if (bigEndian) + v->count = cpu_to_be32(count); + else + v->count = count;
return dest - (void*)le->hdr.digest; } @@ -374,13 +383,13 @@ tpm12_build_digest(struct tpm_log_entry *le, const u8 *sha1) }
static int -tpm_build_digest(struct tpm_log_entry *le, const u8 *sha1) +tpm_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) { switch (TPM_version) { case TPM_VERSION_1_2: return tpm12_build_digest(le, sha1); case TPM_VERSION_2: - return tpm20_build_digest(le, sha1); + return tpm20_build_digest(le, sha1, bigEndian); } return -1; } @@ -709,7 +718,7 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, .hdr.pcrindex = pcrindex, .hdr.eventtype = event_type, }; - int digest_len = tpm_build_digest(&le, hash); + int digest_len = tpm_build_digest(&le, hash, 1); if (digest_len < 0) return; int ret = tpm_extend(&le, digest_len); @@ -717,6 +726,7 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, tpm_set_failure(); return; } + tpm_build_digest(&le, hash, 0); tpm_log_event(&le.hdr, digest_len, event, event_length); }
@@ -1249,7 +1259,7 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length .hdr.pcrindex = pcpes->pcrindex, .hdr.eventtype = pcpes->eventtype, }; - int digest_len = tpm_build_digest(&le, pcpes->digest); + int digest_len = tpm_build_digest(&le, pcpes->digest, 1); if (digest_len < 0) return TCG_GENERAL_ERROR; if (extend) { @@ -1257,6 +1267,7 @@ hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length if (ret) return TCG_TCG_COMMAND_ERROR; } + tpm_build_digest(&le, pcpes->digest, 0); int ret = tpm_log_event(&le.hdr, digest_len , pcpes->event, pcpes->eventdatasize); if (ret)
On Wed, Nov 23, 2016 at 11:19:43AM -0500, Stefan Berger wrote:
The parameters for extending the PCRs of a TPM 2 are written in big endian format when sent to the TPM. However, the log needs to be written in little endian format, so we cannot just copy the structure into the log as-is. To support the little endian format in the log, we extend the function writing the TPM 2 digest structure with a parameter that allows us to choose the endianess of a few parameters. We then rewrite the digest structure in little endian format for the log.
Thanks. I committed this patch.
-Kevin