diff mbox series

[RFC] ima: add crypto agility support for template-hash algorithm

Message ID 20231214145152.36985-1-enrico.bravi@polito.it (mailing list archive)
State New
Headers show
Series [RFC] ima: add crypto agility support for template-hash algorithm | expand

Commit Message

Enrico Bravi Dec. 14, 2023, 2:51 p.m. UTC
The purpose of this patch is to add the possibility to configure the hash
algorithm to use when calculating the template-hash.
The ima_template_hash command line parameter has been introduced to enable
this configuration.
The entry will contain the hash_algo_name before the actual template-hash,
separated by a colon (:).
An example of the resulting ima log is the following:

10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache

This patch has been created starting from the master branch of the main tree:
<git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>

Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
---
 security/integrity/ima/Kconfig      | 30 +++++++++++++++++++++++++++
 security/integrity/ima/ima.h        |  2 ++
 security/integrity/ima/ima_crypto.c | 26 ++++++++++++++++++++++-
 security/integrity/ima/ima_fs.c     | 25 ++++++++++++++--------
 security/integrity/ima/ima_main.c   | 32 +++++++++++++++++++++++++++++
 5 files changed, 105 insertions(+), 10 deletions(-)

base-commit: 88035e5694a86a7167d490bb95e9df97a9bb162b

Comments

Mimi Zohar Dec. 19, 2023, 8:54 p.m. UTC | #1
Hi Enrico,

On Thu, 2023-12-14 at 15:51 +0100, Enrico Bravi wrote:
> The purpose of this patch is to add the possibility to configure the hash
> algorithm to use when calculating the template-hash.

The patch description should be written in the imperative mood.  For an
explanation, please refer to "Describe your changes" in
Documentation/process/submitting-patches.rst.

For example:

The second field of the IMA measurement list, the template data hash,
contains a fixed sized SHA1 digest.  Add support to replace the SHA1
digest with other hash algorithms.  For backwards compatability, only
the new larger digests will be prefixed with ...

> The ima_template_hash command line parameter has been introduced to enable
> this configuration.

The term "ima_template_hash" could be misconstrued to refer to the hash
algorithm used to calculate the file digest.  To differentiate between
the hash algorithm used to calculate the file digest, the term
'ima_template_data_hash' is longer, but I think clearer.

> The entry will contain the hash_algo_name before the actual template-hash,
> separated by a colon (:).

This chnage will break existing userspace applications, unless the SHA1
digest isn't prefixed.

> An example of the resulting ima log is the following:
> 
> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache
> 
> This patch has been created starting from the master branch of the main tree:
> <git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>

With the base-commit included at the end of the cover letter, this
comment is unnessary.  Please remove.

thanks,

Mimi

> 
> Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
> Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
Enrico Bravi Dec. 21, 2023, 2:38 p.m. UTC | #2
Hi Mimi,

thank you for your feedback.

On 19/12/23 21:54, Mimi Zohar wrote:
> Hi Enrico,
> 
> On Thu, 2023-12-14 at 15:51 +0100, Enrico Bravi wrote:
>> The purpose of this patch is to add the possibility to configure the hash
>> algorithm to use when calculating the template-hash.
> 
> The patch description should be written in the imperative mood.  For an
> explanation, please refer to "Describe your changes" in
> Documentation/process/submitting-patches.rst.>
> For example:
> 
> The second field of the IMA measurement list, the template data hash,
> contains a fixed sized SHA1 digest.  Add support to replace the SHA1
> digest with other hash algorithms.  For backwards compatability, only
> the new larger digests will be prefixed with ...
> 
>> The ima_template_hash command line parameter has been introduced to enable
>> this configuration.
> 
> The term "ima_template_hash" could be misconstrued to refer to the hash
> algorithm used to calculate the file digest.  To differentiate between
> the hash algorithm used to calculate the file digest, the term
> 'ima_template_data_hash' is longer, but I think clearer.

Yes you're right, this name is ambiguous.

>> The entry will contain the hash_algo_name before the actual template-hash,
>> separated by a colon (:).
> 
> This chnage will break existing userspace applications, unless the SHA1
> digest isn't prefixed.

Yes, in the current patch, this value is present even in the case of SHA1. We
can modifying the patch by omitting it in the case of SHA1; as an alternative,
the addition of the hash algorithm information can be made configurable in the
ima log to maintain backward compatibility with existing applications.

Best regards,

Enrico

>> An example of the resulting ima log is the following:
>>
>> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
>> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
>> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
>> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache
>>
>> This patch has been created starting from the master branch of the main tree:
>> <git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>
> 
> With the base-commit included at the end of the cover letter, this
> comment is unnessary.  Please remove.
> 
> thanks,
> 
> Mimi
> 
>>
>> Signed-off-by: Silvia Sisinni <silvia.sisinni@polito.it>
>> Signed-off-by: Enrico Bravi <enrico.bravi@polito.it>
Mimi Zohar Dec. 21, 2023, 10:05 p.m. UTC | #3
On Thu, 2023-12-21 at 15:38 +0100, Enrico Bravi wrote:
> Hi Mimi,
> 
> thank you for your feedback.
> 
> On 19/12/23 21:54, Mimi Zohar wrote:
> > Hi Enrico,
> > 
> > On Thu, 2023-12-14 at 15:51 +0100, Enrico Bravi wrote:
> >> The purpose of this patch is to add the possibility to configure the hash
> >> algorithm to use when calculating the template-hash.
> > 
> > The patch description should be written in the imperative mood.  For an
> > explanation, please refer to "Describe your changes" in
> > Documentation/process/submitting-patches.rst.>
> > For example:
> > 
> > The second field of the IMA measurement list, the template data hash,
> > contains a fixed sized SHA1 digest.  Add support to replace the SHA1
> > digest with other hash algorithms.  For backwards compatability, only
> > the new larger digests will be prefixed with ...
> > 
> >> The ima_template_hash command line parameter has been introduced to enable
> >> this configuration.
> > 
> > The term "ima_template_hash" could be misconstrued to refer to the hash
> > algorithm used to calculate the file digest.  To differentiate between
> > the hash algorithm used to calculate the file digest, the term
> > 'ima_template_data_hash' is longer, but I think clearer.
> 
> Yes you're right, this name is ambiguous.
> 
> >> The entry will contain the hash_algo_name before the actual template-hash,
> >> separated by a colon (:).
> > 
> > This chnage will break existing userspace applications, unless the SHA1
> > digest isn't prefixed.
> 
> Yes, in the current patch, this value is present even in the case of SHA1. We
> can modifying the patch by omitting it in the case of SHA1; as an alternative,
> the addition of the hash algorithm information can be made configurable in the
> ima log to maintain backward compatibility with existing applications.

After thinking about this some more, I realized that we didn't discuss
carrying the measurement list across kexec.   How will the kexec'ed
kernel be able to differentiate between the original and new
measurement list?   Neither the Kconfig nor making SHA1 backwards
compatible address this.   How will attestation servers be able to
differentiate between the two logs?

Obviously the new measurement list with larger digests won't be
backwards compatible. Can we support carrying the original measurement
list across kexec to a new kernel?

As long we're making changes to the IMA measurement list, we should
mention that we could include multiple digests, but I don't think it is
necessary.

> >> An example of the resulting ima log is the following:
> >>
> >> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
> >> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
> >> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
> >> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache

The template DATA_FMT_DIGEST_WITH_ALGO field is a composite field
defined as <hash algo> + ':' + '\0' + digest.   The above ascii display
looks like the template composite field, but isn't.  It is two separate
fields.  Perhaps it should look differently as well.   Consider instead
of a string use the hash_algo value (include/uapi/linux/hash_info.h).

binary measurement log:  <pcr> <hash_algo> <digest_len> <digest>
GUO Zihua Dec. 25, 2023, 1 p.m. UTC | #4
On 2023/12/22 6:05, Mimi Zohar wrote:
> On Thu, 2023-12-21 at 15:38 +0100, Enrico Bravi wrote:
>> Hi Mimi,
>>
>> thank you for your feedback.
>>
>> On 19/12/23 21:54, Mimi Zohar wrote:
>>> Hi Enrico,
>>>
>>> On Thu, 2023-12-14 at 15:51 +0100, Enrico Bravi wrote:
>>>> The purpose of this patch is to add the possibility to configure the hash
>>>> algorithm to use when calculating the template-hash.
>>>
>>> The patch description should be written in the imperative mood.  For an
>>> explanation, please refer to "Describe your changes" in
>>> Documentation/process/submitting-patches.rst.>
>>> For example:
>>>
>>> The second field of the IMA measurement list, the template data hash,
>>> contains a fixed sized SHA1 digest.  Add support to replace the SHA1
>>> digest with other hash algorithms.  For backwards compatability, only
>>> the new larger digests will be prefixed with ...
>>>
>>>> The ima_template_hash command line parameter has been introduced to enable
>>>> this configuration.
>>>
>>> The term "ima_template_hash" could be misconstrued to refer to the hash
>>> algorithm used to calculate the file digest.  To differentiate between
>>> the hash algorithm used to calculate the file digest, the term
>>> 'ima_template_data_hash' is longer, but I think clearer.
>>
>> Yes you're right, this name is ambiguous.
>>
>>>> The entry will contain the hash_algo_name before the actual template-hash,
>>>> separated by a colon (:).
>>>
>>> This chnage will break existing userspace applications, unless the SHA1
>>> digest isn't prefixed.
>>
>> Yes, in the current patch, this value is present even in the case of SHA1. We
>> can modifying the patch by omitting it in the case of SHA1; as an alternative,
>> the addition of the hash algorithm information can be made configurable in the
>> ima log to maintain backward compatibility with existing applications.
> 
> After thinking about this some more, I realized that we didn't discuss
> carrying the measurement list across kexec.   How will the kexec'ed
> kernel be able to differentiate between the original and new
> measurement list?   Neither the Kconfig nor making SHA1 backwards
> compatible address this.   How will attestation servers be able to
> differentiate between the two logs?
> 
> Obviously the new measurement list with larger digests won't be
> backwards compatible. Can we support carrying the original measurement
> list across kexec to a new kernel?
> 
> As long we're making changes to the IMA measurement list, we should
> mention that we could include multiple digests, but I don't think it is
> necessary.
> 
>>>> An example of the resulting ima log is the following:
>>>>
>>>> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
>>>> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
>>>> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
>>>> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache
> 
> The template DATA_FMT_DIGEST_WITH_ALGO field is a composite field
> defined as <hash algo> + ':' + '\0' + digest.   The above ascii display
> looks like the template composite field, but isn't.  It is two separate
> fields.  Perhaps it should look differently as well.   Consider instead
> of a string use the hash_algo value (include/uapi/linux/hash_info.h).
> 
> binary measurement log:  <pcr> <hash_algo> <digest_len> <digest>
> 
Hi Mimi and Enrico,

As we are extending all supported algorithms of a PCR bank, does
algorithm of template-hash still matters?
Ken Goldman Dec. 26, 2023, 3:36 p.m. UTC | #5
On 12/25/2023 8:00 AM, Guozihua (Scott) wrote:
>> After thinking about this some more, I realized that we didn't discuss
>> carrying the measurement list across kexec.   How will the kexec'ed
>> kernel be able to differentiate between the original and new
>> measurement list?   Neither the Kconfig nor making SHA1 backwards
>> compatible address this.   How will attestation servers be able to
>> differentiate between the two logs?
>>
>> Obviously the new measurement list with larger digests won't be
>> backwards compatible. Can we support carrying the original measurement
>> list across kexec to a new kernel?
>>
>> As long we're making changes to the IMA measurement list, we should
>> mention that we could include multiple digests, but I don't think it is
>> necessary.
>>
>>>>> An example of the resulting ima log is the following:
>>>>>
>>>>> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
>>>>> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
>>>>> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
>>>>> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache
>> The template DATA_FMT_DIGEST_WITH_ALGO field is a composite field
>> defined as <hash algo> + ':' + '\0' + digest.   The above ascii display
>> looks like the template composite field, but isn't.  It is two separate
>> fields.  Perhaps it should look differently as well.   Consider instead
>> of a string use the hash_algo value (include/uapi/linux/hash_info.h).
>>
>> binary measurement log:  <pcr> <hash_algo> <digest_len> <digest>
>>
> Hi Mimi and Enrico,
> 
> As we are extending all supported algorithms of a PCR bank, does
> algorithm of template-hash still matters?
> 

 From a security and verification viewpoint, I think you are correct. 
The template hash is redundant, and can always be calculated from the 
template data. In that sense, the template hash can be removed.

On the other hand there is one benefit to the template hash. If there is 
a bug in the software that creates the event log or the software that 
consumes the event log, the template hash may help to determine which 
event has a bug.

If the new event log has a template hash, I do believe that it also 
needs a hash algorithm.
Mimi Zohar Dec. 27, 2023, 2:03 p.m. UTC | #6
On Tue, 2023-12-26 at 10:36 -0500, Ken Goldman wrote:
> 
> On 12/25/2023 8:00 AM, Guozihua (Scott) wrote:
> >> After thinking about this some more, I realized that we didn't discuss
> >> carrying the measurement list across kexec.   How will the kexec'ed
> >> kernel be able to differentiate between the original and new
> >> measurement list?   Neither the Kconfig nor making SHA1 backwards
> >> compatible address this.   How will attestation servers be able to
> >> differentiate between the two logs?
> >>
> >> Obviously the new measurement list with larger digests won't be
> >> backwards compatible. Can we support carrying the original measurement
> >> list across kexec to a new kernel?
> >>
> >> As long we're making changes to the IMA measurement list, we should
> >> mention that we could include multiple digests, but I don't think it is
> >> necessary.
> >>
> >>>>> An example of the resulting ima log is the following:
> >>>>>
> >>>>> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
> >>>>> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
> >>>>> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
> >>>>> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache
> >> The template DATA_FMT_DIGEST_WITH_ALGO field is a composite field
> >> defined as <hash algo> + ':' + '\0' + digest.   The above ascii display
> >> looks like the template composite field, but isn't.  It is two separate
> >> fields.  Perhaps it should look differently as well.   Consider instead
> >> of a string use the hash_algo value (include/uapi/linux/hash_info.h).
> >>
> >> binary measurement log:  <pcr> <hash_algo> <digest_len> <digest>
> >>
> > Hi Mimi and Enrico,
> > 
> > As we are extending all supported algorithms of a PCR bank, does
> > algorithm of template-hash still matters?
> > 
> 
>  From a security and verification viewpoint, I think you are correct. 
> The template hash is redundant, and can always be calculated from the 
> template data. In that sense, the template hash can be removed.
> 
> On the other hand there is one benefit to the template hash. If there is 
> a bug in the software that creates the event log or the software that 
> consumes the event log, the template hash may help to determine which 
> event has a bug.
> 
> If the new event log has a template hash, I do believe that it also 
> needs a hash algorithm.

Scott are you asking, since the template data hash is redudant, why
bother changing the measurement list format to support other digest
algorithms?   After removing the SHA1 digest, perhaps SHA1 would not
need to be configured in the kernel.
Silvia Sisinni Jan. 9, 2024, 5:05 p.m. UTC | #7
Il 12/21/2023 11:05 PM, Mimi Zohar ha scritto:
> On Thu, 2023-12-21 at 15:38 +0100, Enrico Bravi wrote:
>> Hi Mimi,
>>
>> thank you for your feedback.
>>
>> On 19/12/23 21:54, Mimi Zohar wrote:
>>> Hi Enrico,
>>>
>>> On Thu, 2023-12-14 at 15:51 +0100, Enrico Bravi wrote:
>>>> The purpose of this patch is to add the possibility to configure the hash
>>>> algorithm to use when calculating the template-hash.
>>>
>>> The patch description should be written in the imperative mood.  For an
>>> explanation, please refer to "Describe your changes" in
>>> Documentation/process/submitting-patches.rst.>
>>> For example:
>>>
>>> The second field of the IMA measurement list, the template data hash,
>>> contains a fixed sized SHA1 digest.  Add support to replace the SHA1
>>> digest with other hash algorithms.  For backwards compatability, only
>>> the new larger digests will be prefixed with ...
>>>
>>>> The ima_template_hash command line parameter has been introduced to enable
>>>> this configuration.
>>>
>>> The term "ima_template_hash" could be misconstrued to refer to the hash
>>> algorithm used to calculate the file digest.  To differentiate between
>>> the hash algorithm used to calculate the file digest, the term
>>> 'ima_template_data_hash' is longer, but I think clearer.
>>
>> Yes you're right, this name is ambiguous.
>>
>>>> The entry will contain the hash_algo_name before the actual template-hash,
>>>> separated by a colon (:).
>>>
>>> This chnage will break existing userspace applications, unless the SHA1
>>> digest isn't prefixed.
>>
>> Yes, in the current patch, this value is present even in the case of SHA1. We
>> can modifying the patch by omitting it in the case of SHA1; as an alternative,
>> the addition of the hash algorithm information can be made configurable in the
>> ima log to maintain backward compatibility with existing applications.
> 
> After thinking about this some more, I realized that we didn't discuss
> carrying the measurement list across kexec.   How will the kexec'ed
> kernel be able to differentiate between the original and new
> measurement list?   Neither the Kconfig nor making SHA1 backwards
> compatible address this.   How will attestation servers be able to
> differentiate between the two logs?
> 
> Obviously the new measurement list with larger digests won't be
> backwards compatible. Can we support carrying the original measurement
> list across kexec to a new kernel?
> 
> As long we're making changes to the IMA measurement list, we should
> mention that we could include multiple digests, but I don't think it is
> necessary.
> 
>>>> An example of the resulting ima log is the following:
>>>>
>>>> 10 sha256:64326[...]25313 ima-ng sha1:5fc9b[...]974e6 boot_aggregate
>>>> 10 sha256:afd64[...]e3123 ima-ng sha1:5a493[...]f9566 /init
>>>> 10 sha256:99329[...]a6353 ima-ng sha1:8c87d[...]3d8c7 /usr/bin/sh
>>>> 10 sha256:a16ad[...]2ac0e ima-ng sha1:59d4b[...]330b0 /etc/ld.so.cache
> 
> The template DATA_FMT_DIGEST_WITH_ALGO field is a composite field
> defined as <hash algo> + ':' + '\0' + digest.   The above ascii display
> looks like the template composite field, but isn't.  It is two separate
> fields.  Perhaps it should look differently as well.   Consider instead
> of a string use the hash_algo value (include/uapi/linux/hash_info.h).
> 
> binary measurement log:  <pcr> <hash_algo> <digest_len> <digest>
> 

Hi Mimi,

sorry for the delay, thank you for your comments.
What you are highlighting about the difference with the 
DATA_FMT_DIGEST_WITH_ALGO field is correct. To avoid this problem we 
could add the normalization of the measurement list, dumping it with 
SHA1 without prefix. This would resolve the problem because the 
restoring of the measurement list implies the re-computing of all the 
digests corresponding to all the hash algorithms configured for PCR 
banks in the TPM. So, by adding this modification, kexec could execute 
both a kernel compatible with this feature and a kernel that is not.

BR,

Silvia
diff mbox series

Patch

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index a6bd817efc1a..9cdeedb2be53 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -121,6 +121,36 @@  config IMA_DEFAULT_HASH
 	default "wp512" if IMA_DEFAULT_HASH_WP512
 	default "sm3" if IMA_DEFAULT_HASH_SM3
 
+choice
+	prompt "Default template-hash algorithm"
+	default IMA_DEFAULT_TEMPLATE_HASH_SHA1
+	depends on IMA
+	help
+	   Select the default template-hash algorithm written in Measurement
+	   Log entries. The compiled default template-hash algorithm can
+	   be overwritten using the kernel command line 'ima_template_hash='
+	   option.
+
+	config IMA_DEFAULT_TEMPLATE_HASH_SHA1
+		bool "SHA1 (default)"
+		depends on CRYPTO_SHA1=y
+
+	config IMA_DEFAULT_TEMPLATE_HASH_SHA256
+		bool "SHA256"
+		depends on CRYPTO_SHA256=y
+
+	config IMA_DEFAULT_TEMPLATE_HASH_SHA512
+		bool "SHA512"
+		depends on CRYPTO_SHA512=y
+endchoice
+
+config IMA_DEFAULT_TEMPLATE_HASH
+	string
+	depends on IMA
+	default "sha1" if IMA_DEFAULT_TEMPLATE_HASH_SHA1
+	default "sha256" if IMA_DEFAULT_TEMPLATE_HASH_SHA256
+	default "sha512" if IMA_DEFAULT_TEMPLATE_HASH_SHA512
+
 config IMA_WRITE_POLICY
 	bool "Enable multiple writes to the IMA policy"
 	default n
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c29db699c996..a19375b9a6e4 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -55,6 +55,8 @@  extern int ima_sha1_idx __ro_after_init;
 extern int ima_hash_algo_idx __ro_after_init;
 extern int ima_extra_slots __ro_after_init;
 extern int ima_appraise;
+extern int ima_template_hash_algo __ro_after_init;
+extern int ima_template_hash_algo_idx __ro_after_init;
 extern struct tpm_chip *ima_tpm_chip;
 extern const char boot_aggregate_name[];
 
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 51ad29940f05..448b55ed5033 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -64,6 +64,7 @@  struct ima_algo_desc {
 
 int ima_sha1_idx __ro_after_init;
 int ima_hash_algo_idx __ro_after_init;
+int ima_template_hash_algo_idx __ro_after_init;
 /*
  * Additional number of slots reserved, as needed, for SHA1
  * and IMA default algo.
@@ -124,6 +125,7 @@  int __init ima_init_crypto(void)
 
 	ima_sha1_idx = -1;
 	ima_hash_algo_idx = -1;
+	ima_template_hash_algo_idx = -1;
 
 	for (i = 0; i < NR_BANKS(ima_tpm_chip); i++) {
 		algo = ima_tpm_chip->allocated_banks[i].crypto_id;
@@ -132,16 +134,28 @@  int __init ima_init_crypto(void)
 
 		if (algo == ima_hash_algo)
 			ima_hash_algo_idx = i;
+
+		if (algo == ima_template_hash_algo)
+			ima_template_hash_algo_idx = i;
 	}
 
 	if (ima_sha1_idx < 0) {
 		ima_sha1_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
 		if (ima_hash_algo == HASH_ALGO_SHA1)
 			ima_hash_algo_idx = ima_sha1_idx;
+
+		if (ima_template_hash_algo == HASH_ALGO_SHA1)
+			ima_template_hash_algo_idx = ima_sha1_idx;
 	}
 
-	if (ima_hash_algo_idx < 0)
+	if (ima_hash_algo_idx < 0) {
 		ima_hash_algo_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
+		if (ima_template_hash_algo == ima_hash_algo)
+			ima_template_hash_algo_idx = ima_hash_algo_idx;
+	}
+
+	if (ima_template_hash_algo_idx < 0)
+		ima_template_hash_algo_idx = NR_BANKS(ima_tpm_chip) + ima_extra_slots++;
 
 	ima_algo_array = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
 				 sizeof(*ima_algo_array), GFP_KERNEL);
@@ -196,6 +210,16 @@  int __init ima_init_crypto(void)
 		ima_algo_array[ima_hash_algo_idx].algo = ima_hash_algo;
 	}
 
+	if (ima_template_hash_algo_idx >= NR_BANKS(ima_tpm_chip) &&
+		ima_template_hash_algo_idx != ima_sha1_idx &&
+		ima_template_hash_algo_idx != ima_hash_algo_idx) {
+		ima_algo_array[ima_template_hash_algo_idx].tfm = ima_alloc_tfm(ima_template_hash_algo);
+		if (IS_ERR(ima_algo_array[ima_template_hash_algo_idx].tfm)) {
+			rc = PTR_ERR(ima_algo_array[ima_template_hash_algo_idx].tfm);
+			goto out_array;
+		}
+	}
+
 	return 0;
 out_array:
 	for (i = 0; i < NR_BANKS(ima_tpm_chip) + ima_extra_slots; i++) {
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index cd1683dad3bf..5545602a6144 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -21,6 +21,7 @@ 
 #include <linux/rcupdate.h>
 #include <linux/parser.h>
 #include <linux/vmalloc.h>
+#include <crypto/hash_info.h>
 
 #include "ima.h"
 
@@ -130,7 +131,7 @@  int ima_measurements_show(struct seq_file *m, void *v)
 	struct ima_queue_entry *qe = v;
 	struct ima_template_entry *e;
 	char *template_name;
-	u32 pcr, namelen, template_data_len; /* temporary fields */
+	u32 pcr, namelen, template_hash_len, template_data_len; /* temporary fields */
 	bool is_ima_template = false;
 	int i;
 
@@ -150,18 +151,23 @@  int ima_measurements_show(struct seq_file *m, void *v)
 	pcr = !ima_canonical_fmt ? e->pcr : (__force u32)cpu_to_le32(e->pcr);
 	ima_putc(m, &pcr, sizeof(e->pcr));
 
-	/* 2nd: template digest */
-	ima_putc(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+	/* 2nd: template digest size */
+	template_hash_len = !ima_canonical_fmt ? hash_digest_size[ima_template_hash_algo] :
+		(__force u32)cpu_to_le32(hash_digest_size[ima_template_hash_algo]);
+	ima_putc(m, &template_hash_len, sizeof(template_hash_len));
 
-	/* 3rd: template name size */
+	/* 3rd: template digest */
+	ima_putc(m, e->digests[ima_template_hash_algo_idx].digest, hash_digest_size[ima_template_hash_algo]);
+
+	/* 4th: template name size */
 	namelen = !ima_canonical_fmt ? strlen(template_name) :
 		(__force u32)cpu_to_le32(strlen(template_name));
 	ima_putc(m, &namelen, sizeof(namelen));
 
-	/* 4th:  template name */
+	/* 5th:  template name */
 	ima_putc(m, template_name, strlen(template_name));
 
-	/* 5th:  template length (except for 'ima' template) */
+	/* 6th:  template length (except for 'ima' template) */
 	if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0)
 		is_ima_template = true;
 
@@ -171,7 +177,7 @@  int ima_measurements_show(struct seq_file *m, void *v)
 		ima_putc(m, &template_data_len, sizeof(e->template_data_len));
 	}
 
-	/* 6th:  template specific data */
+	/* 7th:  template specific data */
 	for (i = 0; i < e->template_desc->num_fields; i++) {
 		enum ima_show_type show = IMA_SHOW_BINARY;
 		const struct ima_template_field *field =
@@ -233,8 +239,9 @@  static int ima_ascii_measurements_show(struct seq_file *m, void *v)
 	/* 1st: PCR used (config option) */
 	seq_printf(m, "%2d ", e->pcr);
 
-	/* 2nd: SHA1 template hash */
-	ima_print_digest(m, e->digests[ima_sha1_idx].digest, TPM_DIGEST_SIZE);
+	/* 2nd: template hash (hash_algo_name:digest)*/
+	seq_printf(m, "%s:", hash_algo_name[ima_template_hash_algo]);
+	ima_print_digest(m, e->digests[ima_template_hash_algo_idx].digest, hash_digest_size[ima_template_hash_algo]);
 
 	/* 3th:  template name */
 	seq_printf(m, " %s", template_name);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index cc1217ac2c6f..fa31ecb66606 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -36,7 +36,9 @@  int ima_appraise;
 #endif
 
 int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1;
+int __ro_after_init ima_template_hash_algo = HASH_ALGO_SHA1;
 static int hash_setup_done;
+static int template_hash_setup_done;
 
 static struct notifier_block ima_lsm_policy_notifier = {
 	.notifier_call = ima_lsm_policy_change,
@@ -76,6 +78,26 @@  static int __init hash_setup(char *str)
 }
 __setup("ima_hash=", hash_setup);
 
+static int __init template_hash_setup(char *str)
+{
+	int i;
+
+	if (template_hash_setup_done)
+		return 1;
+
+	i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
+	if (i < 0) {
+		pr_err("invalid template-hash algorithm \"%s\"", str);
+		return 1;
+	}
+
+	ima_template_hash_algo = i;
+
+	template_hash_setup_done = 1;
+	return 1;
+}
+__setup("ima_template_hash=", template_hash_setup);
+
 enum hash_algo ima_get_current_hash_algo(void)
 {
 	return ima_hash_algo;
@@ -1096,6 +1118,7 @@  static int __init init_ima(void)
 	ima_appraise_parse_cmdline();
 	ima_init_template_list();
 	hash_setup(CONFIG_IMA_DEFAULT_HASH);
+	template_hash_setup(CONFIG_IMA_DEFAULT_TEMPLATE_HASH);
 	error = ima_init();
 
 	if (error && strcmp(hash_algo_name[ima_hash_algo],
@@ -1107,6 +1130,15 @@  static int __init init_ima(void)
 		error = ima_init();
 	}
 
+	if (error && strcmp(hash_algo_name[ima_template_hash_algo],
+			    CONFIG_IMA_DEFAULT_TEMPLATE_HASH) != 0) {
+		pr_info("Allocating %s failed, going to use default template-hash algorithm %s\n",
+			hash_algo_name[ima_template_hash_algo], CONFIG_IMA_DEFAULT_TEMPLATE_HASH);
+		template_hash_setup_done = 0;
+		template_hash_setup(CONFIG_IMA_DEFAULT_TEMPLATE_HASH);
+		error = ima_init();
+	}
+
 	if (error)
 		return error;