tcgbios: Use The proper sha function for each PCR bank

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>
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 @@
     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 @@
     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 @@
  * 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 @@
         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 @@
 }
 
 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 @@
 }
 
 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 @@
     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_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 @@
         .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 @@
         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)