Instead of just using sha1 for all PCR banks (and truncating the value or zero-padding it) use the proper hash function for each one of the banks. For unimplemented hashes, fill the buffer with 0xff.
Signed-off-by: Stefan Berger stefanb@linux.ibm.com --- src/tcgbios.c | 58 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 15 deletions(-)
diff --git a/src/tcgbios.c b/src/tcgbios.c index a9d62c8..02921d8 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -167,27 +167,32 @@ static const struct hash_parameters { u8 hashalg_flag; u8 hash_buffersize; const char *name; + void (*hashfunc)(const u8 *data, u32 length, u8 *hash); } hash_parameters[] = { { .hashalg = TPM2_ALG_SHA1, .hashalg_flag = TPM2_ALG_SHA1_FLAG, .hash_buffersize = SHA1_BUFSIZE, .name = "SHA1", + .hashfunc = sha1, }, { .hashalg = TPM2_ALG_SHA256, .hashalg_flag = TPM2_ALG_SHA256_FLAG, .hash_buffersize = SHA256_BUFSIZE, .name = "SHA256", + .hashfunc = sha256, }, { .hashalg = TPM2_ALG_SHA384, .hashalg_flag = TPM2_ALG_SHA384_FLAG, .hash_buffersize = SHA384_BUFSIZE, .name = "SHA384", + .hashfunc = sha384, }, { .hashalg = TPM2_ALG_SHA512, .hashalg_flag = TPM2_ALG_SHA512_FLAG, .hash_buffersize = SHA512_BUFSIZE, .name = "SHA512", + .hashfunc = sha512, }, { .hashalg = TPM2_ALG_SM3_256, .hashalg_flag = TPM2_ALG_SM3_256_FLAG, @@ -259,6 +264,21 @@ tpm20_hashalg_flag_to_name(u8 hashalg_flag) return NULL; }
+static void tpm2_hash_data(u16 hashAlg, const u8 *data, u32 data_len, u8 *hash) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { + if (hash_parameters[i].hashalg == hashAlg) { + if (hash_parameters[i].hashfunc) { + hash_parameters[i].hashfunc(data, data_len, hash); + } else { + memset(hash, 0xff, hash_parameters[i].hash_buffersize); + } + } + } +} + // Add an entry at the start of the log describing digest formats static int tpm20_write_EfiSpecIdEventStruct(void) @@ -342,14 +362,16 @@ tpm20_write_EfiSpecIdEventStruct(void) * hash when writing it in the area of the sha1 hash. * * le: the log entry to build the digest in - * sha1: the sha1 hash value to use + * hashdata: the data to hash + * hashdata_len: the length of the hashdata * 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, int bigEndian) +tpm20_build_digest(struct tpm_log_entry *le, + const u8 *hashdata, u32 hashdata_len, int bigEndian) { if (!tpm20_pcr_selection) return -1; @@ -391,8 +413,8 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) else v->hashAlg = be16_to_cpu(sel->hashAlg);
- memset(v->hash, 0, hsize); - memcpy(v->hash, sha1, hsize > SHA1_BUFSIZE ? SHA1_BUFSIZE : hsize); + tpm2_hash_data(be16_to_cpu(sel->hashAlg), hashdata, hashdata_len, + v->hash);
dest += sizeof(*v) + hsize; sel = nsel; @@ -415,7 +437,15 @@ tpm20_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) }
static int -tpm12_build_digest(struct tpm_log_entry *le, const u8 *sha1) +tpm12_build_digest(struct tpm_log_entry *le, + const u8 *hashdata, u32 hashdata_len) +{ + sha1(hashdata, hashdata_len, le->hdr.digest); + return SHA1_BUFSIZE; +} + +static int +tpm12_build_digest_direct(struct tpm_log_entry *le, const u8 *sha1) { // On TPM 1.2 the digest contains just the SHA1 hash memcpy(le->hdr.digest, sha1, SHA1_BUFSIZE); @@ -423,13 +453,14 @@ tpm12_build_digest(struct tpm_log_entry *le, const u8 *sha1) }
static int -tpm_build_digest(struct tpm_log_entry *le, const u8 *sha1, int bigEndian) +tpm_build_digest(struct tpm_log_entry *le, const u8 *hashdata, u32 hashdata_len + , int bigEndian) { switch (TPM_version) { case TPM_VERSION_1_2: - return tpm12_build_digest(le, sha1); + return tpm12_build_digest(le, hashdata, hashdata_len); case TPM_VERSION_2: - return tpm20_build_digest(le, sha1, bigEndian); + return tpm20_build_digest(le, hashdata, hashdata_len, bigEndian); } return -1; } @@ -978,14 +1009,11 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, if (!tpm_is_working()) return;
- u8 hash[SHA1_BUFSIZE]; - sha1(hashdata, hashdata_length, hash); - struct tpm_log_entry le = { .hdr.pcrindex = pcrindex, .hdr.eventtype = event_type, }; - int digest_len = tpm_build_digest(&le, hash, 1); + int digest_len = tpm_build_digest(&le, hashdata, hashdata_length, 1); if (digest_len < 0) return; int ret = tpm_extend(&le, digest_len); @@ -993,7 +1021,7 @@ tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, tpm_set_failure(); return; } - tpm_build_digest(&le, hash, 0); + tpm_build_digest(&le, hashdata, hashdata_length, 0); tpm_log_event(&le.hdr, digest_len, event, event_length); }
@@ -1407,7 +1435,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, 1); + int digest_len = tpm12_build_digest_direct(&le, pcpes->digest); if (digest_len < 0) return TCG_GENERAL_ERROR; if (extend) { @@ -1415,7 +1443,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); + tpm12_build_digest_direct(&le, pcpes->digest); int ret = tpm_log_event(&le.hdr, digest_len , pcpes->event, pcpes->eventdatasize); if (ret)