#define IMA_TEMPLATE_IMA_NAME "ima"
 #define IMA_TEMPLATE_IMA_FMT "d|n"
 
+#define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
+
 /* current content of the policy */
 extern int ima_policy_flag;
 
 /* set during initialization */
 extern int ima_hash_algo;
+extern int ima_sha1_idx __ro_after_init;
+extern int ima_extra_slots __ro_after_init;
 extern int ima_appraise;
 extern struct tpm_chip *ima_tpm_chip;
 
 
 struct ima_template_entry {
        int pcr;
-       u8 digest[TPM_DIGEST_SIZE];     /* sha1 or md5 measurement hash */
+       struct tpm_digest *digests;
        struct ima_template_desc *template_desc; /* template descriptor */
        u32 template_data_len;
        struct ima_field_data template_data[0]; /* template related data */
 
        for (i = 0; i < entry->template_desc->num_fields; i++)
                kfree(entry->template_data[i].data);
 
+       kfree(entry->digests);
        kfree(entry);
 }
 
                            struct ima_template_desc *desc)
 {
        struct ima_template_desc *template_desc;
+       struct tpm_digest *digests;
        int i, result = 0;
 
        if (desc)
        if (!*entry)
                return -ENOMEM;
 
+       digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
+                         sizeof(*digests), GFP_NOFS);
+       if (!digests) {
+               result = -ENOMEM;
+               goto out;
+       }
+
+       (*entry)->digests = digests;
        (*entry)->template_desc = template_desc;
        for (i = 0; i < template_desc->num_fields; i++) {
                const struct ima_template_field *field =
 
 static struct crypto_shash *ima_shash_tfm;
 static struct crypto_ahash *ima_ahash_tfm;
 
+int ima_sha1_idx __ro_after_init;
+/*
+ * Additional number of slots reserved, as needed, for SHA1
+ * and IMA default algo.
+ */
+int ima_extra_slots __ro_after_init = 1;
+
 int __init ima_init_crypto(void)
 {
        long rc;
        }
 
        if (!rc)
-               rc = crypto_shash_final(shash, entry->digest);
+               rc = crypto_shash_final(shash,
+                                       entry->digests[ima_sha1_idx].digest);
 
        return rc;
 }
 
        ima_putc(m, &pcr, sizeof(e->pcr));
 
        /* 2nd: template digest */
-       ima_putc(m, e->digest, TPM_DIGEST_SIZE);
+       ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
 
        /* 3rd: template name size */
        namelen = !ima_canonical_fmt ? strlen(template_name) :
        seq_printf(m, "%2d ", e->pcr);
 
        /* 2nd: SHA1 template hash */
-       ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
+       ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
 
        /* 3th:  template name */
        seq_printf(m, " %s", template_name);
 
        key = ima_hash_key(digest_value);
        rcu_read_lock();
        hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) {
-               rc = memcmp(qe->entry->digest, digest_value, TPM_DIGEST_SIZE);
+               rc = memcmp(qe->entry->digests[ima_sha1_idx].digest,
+                           digest_value, TPM_DIGEST_SIZE);
                if ((rc == 0) && (qe->entry->pcr == pcr)) {
                        ret = qe;
                        break;
        int size = 0;
 
        size += sizeof(u32);    /* pcr */
-       size += sizeof(entry->digest);
+       size += TPM_DIGEST_SIZE;
        size += sizeof(int);    /* template name size field */
        size += strlen(entry->template_desc->name);
        size += sizeof(entry->template_data_len);
 
        atomic_long_inc(&ima_htable.len);
        if (update_htable) {
-               key = ima_hash_key(entry->digest);
+               key = ima_hash_key(entry->digests[ima_sha1_idx].digest);
                hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
        }
 
 
        mutex_lock(&ima_extend_list_mutex);
        if (!violation) {
-               memcpy(digest, entry->digest, sizeof(digest));
+               memcpy(digest, entry->digests[ima_sha1_idx].digest,
+                      sizeof(digest));
                if (ima_lookup_digest_entry(digest, entry->pcr)) {
                        audit_cause = "hash_exists";
                        result = -EEXIST;
 
                                     int template_data_size,
                                     struct ima_template_entry **entry)
 {
+       struct tpm_digest *digests;
        int ret = 0;
        int i;
 
        if (!*entry)
                return -ENOMEM;
 
+       digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
+                         sizeof(*digests), GFP_NOFS);
+       if (!digests) {
+               kfree(*entry);
+               return -ENOMEM;
+       }
+
+       (*entry)->digests = digests;
+
        ret = ima_parse_buf(template_data, template_data + template_data_size,
                            NULL, template_desc->num_fields,
                            (*entry)->template_data, NULL, NULL,
                            ENFORCE_FIELDS | ENFORCE_BUFEND, "template data");
        if (ret < 0) {
+               kfree((*entry)->digests);
                kfree(*entry);
                return ret;
        }
                if (ret < 0)
                        break;
 
-               memcpy(entry->digest, hdr[HDR_DIGEST].data,
-                      hdr[HDR_DIGEST].len);
+               memcpy(entry->digests[ima_sha1_idx].digest,
+                      hdr[HDR_DIGEST].data, hdr[HDR_DIGEST].len);
                entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) :
                             le32_to_cpu(*(hdr[HDR_PCR].data));
                ret = ima_restore_measurement_entry(entry);