diff mbox series

[7/7] tpm: allow the user to select the compiled algorithms

Message ID 20240622143601.187723-8-ilias.apalodimas@linaro.org
State Superseded
Headers show
Series The great TCG deduplication saga | expand

Commit Message

Ilias Apalodimas June 22, 2024, 2:35 p.m. UTC
Simon reports that after enabling all algorithms on the TPM some boards
fail since they don't have enough storage to accommodate the ~5KB growth.

The choice of hash algorithms are determined by the platform and the TPM
configuration. Failing to cap a PCR in a bank which the platform left
active is a security vulnerability. It might allow  unsealing of secrets
if an attacker can replay a good set of measurements into an unused bank.

If MEASURED_BOOT or EFI_TCG2_PROTOCOL is enabled our Kconfig will enable
all supported hashing algorithms. We still want to allow users to add a
TPM and not enable measured boot via EFI or bootm though and at the same
time, control the compiled algorithms for size reasons.

So let's add a function tpm2_allow_extend() which checks the TPM active
PCRs banks against the one U-Boot was compiled with.
If all the active PCRs banks are not enabled refuse to extend a PCR but
otherwise leave the TPM functional.

It's worth noting that this is only added on TPM2.0, since TPM1.2 is
lacking a lot of code at the moment to read the available PCRs.
We unconditionally enable SHA1 when a TPM is selected, which is the only
hashing algorithm v1.2 supports.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
 boot/Kconfig     |  4 ++++
 include/tpm-v2.h | 59 +++++++++++++++++++++++++++++++++++-------------
 lib/Kconfig      |  6 ++---
 lib/tpm-v2.c     | 40 +++++++++++++++++++++++++++++---
 4 files changed, 87 insertions(+), 22 deletions(-)

Comments

Heinrich Schuchardt June 22, 2024, 4:28 p.m. UTC | #1
On 22.06.24 16:35, Ilias Apalodimas wrote:
> Simon reports that after enabling all algorithms on the TPM some boards
> fail since they don't have enough storage to accommodate the ~5KB growth.
>
> The choice of hash algorithms are determined by the platform and the TPM
> configuration. Failing to cap a PCR in a bank which the platform left
> active is a security vulnerability. It might allow  unsealing of secrets
> if an attacker can replay a good set of measurements into an unused bank.
>
> If MEASURED_BOOT or EFI_TCG2_PROTOCOL is enabled our Kconfig will enable
> all supported hashing algorithms. We still want to allow users to add a
> TPM and not enable measured boot via EFI or bootm though and at the same
> time, control the compiled algorithms for size reasons.
>
> So let's add a function tpm2_allow_extend() which checks the TPM active
> PCRs banks against the one U-Boot was compiled with.
> If all the active PCRs banks are not enabled refuse to extend a PCR but
> otherwise leave the TPM functional.

The paragraph above is bit hard to read. I guess you mean:

We only allow extending PCRs using one of the algorithms selected in the
configuration.

>
> It's worth noting that this is only added on TPM2.0, since TPM1.2 is
> lacking a lot of code at the moment to read the available PCRs.
> We unconditionally enable SHA1 when a TPM is selected, which is the only
> hashing algorithm v1.2 supports.

Why do we need SHA1 if we cannot access PCRs on a TPM1.2?

Best regards

Heinrich

>
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> ---
>   boot/Kconfig     |  4 ++++
>   include/tpm-v2.h | 59 +++++++++++++++++++++++++++++++++++-------------
>   lib/Kconfig      |  6 ++---
>   lib/tpm-v2.c     | 40 +++++++++++++++++++++++++++++---
>   4 files changed, 87 insertions(+), 22 deletions(-)
>
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 6f3096c15a6f..b061891e109c 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -734,6 +734,10 @@ config LEGACY_IMAGE_FORMAT
>   config MEASURED_BOOT
>   	bool "Measure boot images and configuration when booting without EFI"
>   	depends on HASH && TPM_V2
> +	select SHA1
> +	select SHA256
> +	select SHA384
> +	select SHA512
>   	help
>   	  This option enables measurement of the boot process when booting
>   	  without UEFI . Measurement involves creating cryptographic hashes
> diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> index eac04d1c6831..fccb07fa4695 100644
> --- a/include/tpm-v2.h
> +++ b/include/tpm-v2.h
> @@ -277,48 +277,40 @@ struct digest_info {
>   #define TCG2_BOOT_HASH_ALG_SM3_256 0x00000010
>
>   static const struct digest_info hash_algo_list[] = {
> +#if IS_ENABLED(CONFIG_SHA1)
>   	{
>   		"sha1",
>   		TPM2_ALG_SHA1,
>   		TCG2_BOOT_HASH_ALG_SHA1,
>   		TPM2_SHA1_DIGEST_SIZE,
>   	},
> +#endif
> +#if IS_ENABLED(CONFIG_SHA256)
>   	{
>   		"sha256",
>   		TPM2_ALG_SHA256,
>   		TCG2_BOOT_HASH_ALG_SHA256,
>   		TPM2_SHA256_DIGEST_SIZE,
>   	},
> +#endif
> +#if IS_ENABLED(CONFIG_SHA384)
>   	{
>   		"sha384",
>   		TPM2_ALG_SHA384,
>   		TCG2_BOOT_HASH_ALG_SHA384,
>   		TPM2_SHA384_DIGEST_SIZE,
>   	},
> +#endif
> +#if IS_ENABLED(CONFIG_SHA512)
>   	{
>   		"sha512",
>   		TPM2_ALG_SHA512,
>   		TCG2_BOOT_HASH_ALG_SHA512,
>   		TPM2_SHA512_DIGEST_SIZE,
>   	},
> +#endif
>   };
>
> -static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
> -{
> -	switch (a) {
> -	case TPM2_ALG_SHA1:
> -		return TPM2_SHA1_DIGEST_SIZE;
> -	case TPM2_ALG_SHA256:
> -		return TPM2_SHA256_DIGEST_SIZE;
> -	case TPM2_ALG_SHA384:
> -		return TPM2_SHA384_DIGEST_SIZE;
> -	case TPM2_ALG_SHA512:
> -		return TPM2_SHA512_DIGEST_SIZE;
> -	default:
> -		return 0;
> -	}
> -}
> -
>   /* NV index attributes */
>   enum tpm_index_attrs {
>   	TPMA_NV_PPWRITE		= 1UL << 0,
> @@ -711,6 +703,41 @@ enum tpm2_algorithms tpm2_name_to_algorithm(const char *name);
>    */
>   const char *tpm2_algorithm_name(enum tpm2_algorithms);
>
> +/**
> + * tpm2_algorithm_to_len() - Return an algorithm length for supported algorithm id
> + *
> + * @algorithm_id: algorithm defined in enum tpm2_algorithms
> + * Return: len or 0 if not supported
> + */
> +u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo);
> +
> +/*
> + * When measured boot is enabled via EFI or bootX commands all the algorithms
> + * above are selected by our Kconfigs. Due to U-Boots nature of being small there
> + * are cases where we need some functionality from the TPM -- e.g storage or RNG
> + * but we don't want to support measurements.
> + *
> + * The choice of hash algorithms are determined by the platform and the TPM
> + * configuration. Failing to cap a PCR in a bank which the platform left
> + * active is a security vulnerability. It permits the unsealing of secrets
> + * if an attacker can replay a good set of measurements into an unused bank.
> + *
> + * On top of that a previous stage bootloader (e.g TF-A), migh pass an eventlog
> + * since it doesn't have a TPM driver, which U-Boot needs to replace. The algorit h
> + * choice is a compile time option in that case and we need to make sure we conform.
> + *
> + * Add a variable here that sums the supported algorithms U-Boot was compiled
> + * with so we can refuse to do measurements if we don't support all of them
> + */
> +
> +/**
> + * tpm2_allow_extend() - Check if extending PCRs is allowed and safe
> + *
> + * @dev: TPM device
> + * Return: true if allowed
> + */
> +bool tpm2_allow_extend(struct udevice *dev);
> +
>   /**
>    * tpm2_is_active_pcr() - check the pcr_select. If at least one of the PCRs
>    *			  supports the algorithm add it on the active ones
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 189e6eb31aa1..b3baa4b85b07 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -439,9 +439,6 @@ config TPM
>   	depends on DM
>   	imply DM_RNG
>   	select SHA1
> -	select SHA256
> -	select SHA384
> -	select SHA512
>   	help
>   	  This enables support for TPMs which can be used to provide security
>   	  features for your board. The TPM can be connected via LPC or I2C
> @@ -449,6 +446,9 @@ config TPM
>   	  command to interactive the TPM. Driver model support is provided
>   	  for the low-level TPM interface, but only one TPM is supported at
>   	  a time by the TPM library.
> +	  For size reasons only SHA1 is selected which is supported on TPM1.2.
> +	  If you want a fully functional TPM enable all hashing algorithms.
> +	  If you enabled measured boot all hashing algorithms are selected.
>
>   config SPL_TPM
>   	bool "Trusted Platform Module (TPM) Support in SPL"
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 36aace03cf4e..59e6cbafafaa 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -196,6 +196,11 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
>
>   	if (!digest)
>   		return -EINVAL;
> +
> +	if (!tpm2_allow_extend(dev)) {
> +		log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
> +		return -EINVAL;
> +	}
>   	/*
>   	 * Fill the command structure starting from the first buffer:
>   	 *     - the digest
> @@ -409,11 +414,10 @@ int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
>
>   	pcrs->count = get_unaligned_be32(response);
>   	/*
> -	 * We only support 5 algorithms for now so check against that
> +	 * We only support 4 algorithms for now so check against that
>   	 * instead of TPM2_NUM_PCR_BANKS
>   	 */
> -	if (pcrs->count > ARRAY_SIZE(hash_algo_list) ||
> -	    pcrs->count < 1) {
> +	if (pcrs->count > 4 || pcrs->count < 1) {
>   		printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
>   		return -EMSGSIZE;
>   	}
> @@ -880,3 +884,33 @@ const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
>   	return "";
>   }
>
> +u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
> +		if (hash_algo_list[i].hash_alg == algo)
> +			return hash_algo_list[i].hash_len;
> +	}
> +
> +	return 0;
> +}
> +
> +bool tpm2_allow_extend(struct udevice *dev)
> +{
> +	struct tpml_pcr_selection pcrs;
> +	size_t i;
> +	int rc;
> +
> +	rc = tpm2_get_pcr_info(dev, &pcrs);
> +	if (rc)
> +		return false;
> +
> +	for (i = 0; i < pcrs.count; i++) {
> +		if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
> +		    !tpm2_algorithm_to_len(pcrs.selection[i].hash))
> +			return false;
> +	}
> +
> +	return true;
> +}
Ilias Apalodimas June 22, 2024, 4:40 p.m. UTC | #2
On Sat, 22 Jun 2024 at 19:34, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 22.06.24 16:35, Ilias Apalodimas wrote:
> > Simon reports that after enabling all algorithms on the TPM some boards
> > fail since they don't have enough storage to accommodate the ~5KB growth.
> >
> > The choice of hash algorithms are determined by the platform and the TPM
> > configuration. Failing to cap a PCR in a bank which the platform left
> > active is a security vulnerability. It might allow  unsealing of secrets
> > if an attacker can replay a good set of measurements into an unused bank.
> >
> > If MEASURED_BOOT or EFI_TCG2_PROTOCOL is enabled our Kconfig will enable
> > all supported hashing algorithms. We still want to allow users to add a
> > TPM and not enable measured boot via EFI or bootm though and at the same
> > time, control the compiled algorithms for size reasons.
> >
> > So let's add a function tpm2_allow_extend() which checks the TPM active
> > PCRs banks against the one U-Boot was compiled with.
> > If all the active PCRs banks are not enabled refuse to extend a PCR but
> > otherwise leave the TPM functional.
>
> The paragraph above is bit hard to read. I guess you mean:
>
> We only allow extending PCRs using one of the algorithms selected in the
> configuration.

Yes

>
> >
> > It's worth noting that this is only added on TPM2.0, since TPM1.2 is
> > lacking a lot of code at the moment to read the available PCRs.
> > We unconditionally enable SHA1 when a TPM is selected, which is the only
> > hashing algorithm v1.2 supports.
>
> Why do we need SHA1 if we cannot access PCRs on a TPM1.2?

You can. On TPM1.2 we don't have the functions to check for the active
PCR banks. So I am unconditionally enabling SHA1, which is the only
hashing algo TPM1.2 supports.

Thanks
/Ilias
>
> Best regards
>
> Heinrich
>
> >
> > Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > ---
> >   boot/Kconfig     |  4 ++++
> >   include/tpm-v2.h | 59 +++++++++++++++++++++++++++++++++++-------------
> >   lib/Kconfig      |  6 ++---
> >   lib/tpm-v2.c     | 40 +++++++++++++++++++++++++++++---
> >   4 files changed, 87 insertions(+), 22 deletions(-)
> >
> > diff --git a/boot/Kconfig b/boot/Kconfig
> > index 6f3096c15a6f..b061891e109c 100644
> > --- a/boot/Kconfig
> > +++ b/boot/Kconfig
> > @@ -734,6 +734,10 @@ config LEGACY_IMAGE_FORMAT
> >   config MEASURED_BOOT
> >       bool "Measure boot images and configuration when booting without EFI"
> >       depends on HASH && TPM_V2
> > +     select SHA1
> > +     select SHA256
> > +     select SHA384
> > +     select SHA512
> >       help
> >         This option enables measurement of the boot process when booting
> >         without UEFI . Measurement involves creating cryptographic hashes
> > diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> > index eac04d1c6831..fccb07fa4695 100644
> > --- a/include/tpm-v2.h
> > +++ b/include/tpm-v2.h
> > @@ -277,48 +277,40 @@ struct digest_info {
> >   #define TCG2_BOOT_HASH_ALG_SM3_256 0x00000010
> >
> >   static const struct digest_info hash_algo_list[] = {
> > +#if IS_ENABLED(CONFIG_SHA1)
> >       {
> >               "sha1",
> >               TPM2_ALG_SHA1,
> >               TCG2_BOOT_HASH_ALG_SHA1,
> >               TPM2_SHA1_DIGEST_SIZE,
> >       },
> > +#endif
> > +#if IS_ENABLED(CONFIG_SHA256)
> >       {
> >               "sha256",
> >               TPM2_ALG_SHA256,
> >               TCG2_BOOT_HASH_ALG_SHA256,
> >               TPM2_SHA256_DIGEST_SIZE,
> >       },
> > +#endif
> > +#if IS_ENABLED(CONFIG_SHA384)
> >       {
> >               "sha384",
> >               TPM2_ALG_SHA384,
> >               TCG2_BOOT_HASH_ALG_SHA384,
> >               TPM2_SHA384_DIGEST_SIZE,
> >       },
> > +#endif
> > +#if IS_ENABLED(CONFIG_SHA512)
> >       {
> >               "sha512",
> >               TPM2_ALG_SHA512,
> >               TCG2_BOOT_HASH_ALG_SHA512,
> >               TPM2_SHA512_DIGEST_SIZE,
> >       },
> > +#endif
> >   };
> >
> > -static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
> > -{
> > -     switch (a) {
> > -     case TPM2_ALG_SHA1:
> > -             return TPM2_SHA1_DIGEST_SIZE;
> > -     case TPM2_ALG_SHA256:
> > -             return TPM2_SHA256_DIGEST_SIZE;
> > -     case TPM2_ALG_SHA384:
> > -             return TPM2_SHA384_DIGEST_SIZE;
> > -     case TPM2_ALG_SHA512:
> > -             return TPM2_SHA512_DIGEST_SIZE;
> > -     default:
> > -             return 0;
> > -     }
> > -}
> > -
> >   /* NV index attributes */
> >   enum tpm_index_attrs {
> >       TPMA_NV_PPWRITE         = 1UL << 0,
> > @@ -711,6 +703,41 @@ enum tpm2_algorithms tpm2_name_to_algorithm(const char *name);
> >    */
> >   const char *tpm2_algorithm_name(enum tpm2_algorithms);
> >
> > +/**
> > + * tpm2_algorithm_to_len() - Return an algorithm length for supported algorithm id
> > + *
> > + * @algorithm_id: algorithm defined in enum tpm2_algorithms
> > + * Return: len or 0 if not supported
> > + */
> > +u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo);
> > +
> > +/*
> > + * When measured boot is enabled via EFI or bootX commands all the algorithms
> > + * above are selected by our Kconfigs. Due to U-Boots nature of being small there
> > + * are cases where we need some functionality from the TPM -- e.g storage or RNG
> > + * but we don't want to support measurements.
> > + *
> > + * The choice of hash algorithms are determined by the platform and the TPM
> > + * configuration. Failing to cap a PCR in a bank which the platform left
> > + * active is a security vulnerability. It permits the unsealing of secrets
> > + * if an attacker can replay a good set of measurements into an unused bank.
> > + *
> > + * On top of that a previous stage bootloader (e.g TF-A), migh pass an eventlog
> > + * since it doesn't have a TPM driver, which U-Boot needs to replace. The algorit h
> > + * choice is a compile time option in that case and we need to make sure we conform.
> > + *
> > + * Add a variable here that sums the supported algorithms U-Boot was compiled
> > + * with so we can refuse to do measurements if we don't support all of them
> > + */
> > +
> > +/**
> > + * tpm2_allow_extend() - Check if extending PCRs is allowed and safe
> > + *
> > + * @dev: TPM device
> > + * Return: true if allowed
> > + */
> > +bool tpm2_allow_extend(struct udevice *dev);
> > +
> >   /**
> >    * tpm2_is_active_pcr() - check the pcr_select. If at least one of the PCRs
> >    *                    supports the algorithm add it on the active ones
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 189e6eb31aa1..b3baa4b85b07 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -439,9 +439,6 @@ config TPM
> >       depends on DM
> >       imply DM_RNG
> >       select SHA1
> > -     select SHA256
> > -     select SHA384
> > -     select SHA512
> >       help
> >         This enables support for TPMs which can be used to provide security
> >         features for your board. The TPM can be connected via LPC or I2C
> > @@ -449,6 +446,9 @@ config TPM
> >         command to interactive the TPM. Driver model support is provided
> >         for the low-level TPM interface, but only one TPM is supported at
> >         a time by the TPM library.
> > +       For size reasons only SHA1 is selected which is supported on TPM1.2.
> > +       If you want a fully functional TPM enable all hashing algorithms.
> > +       If you enabled measured boot all hashing algorithms are selected.
> >
> >   config SPL_TPM
> >       bool "Trusted Platform Module (TPM) Support in SPL"
> > diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> > index 36aace03cf4e..59e6cbafafaa 100644
> > --- a/lib/tpm-v2.c
> > +++ b/lib/tpm-v2.c
> > @@ -196,6 +196,11 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> >
> >       if (!digest)
> >               return -EINVAL;
> > +
> > +     if (!tpm2_allow_extend(dev)) {
> > +             log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
> > +             return -EINVAL;
> > +     }
> >       /*
> >        * Fill the command structure starting from the first buffer:
> >        *     - the digest
> > @@ -409,11 +414,10 @@ int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
> >
> >       pcrs->count = get_unaligned_be32(response);
> >       /*
> > -      * We only support 5 algorithms for now so check against that
> > +      * We only support 4 algorithms for now so check against that
> >        * instead of TPM2_NUM_PCR_BANKS
> >        */
> > -     if (pcrs->count > ARRAY_SIZE(hash_algo_list) ||
> > -         pcrs->count < 1) {
> > +     if (pcrs->count > 4 || pcrs->count < 1) {
> >               printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
> >               return -EMSGSIZE;
> >       }
> > @@ -880,3 +884,33 @@ const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
> >       return "";
> >   }
> >
> > +u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
> > +{
> > +     size_t i;
> > +
> > +     for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
> > +             if (hash_algo_list[i].hash_alg == algo)
> > +                     return hash_algo_list[i].hash_len;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +bool tpm2_allow_extend(struct udevice *dev)
> > +{
> > +     struct tpml_pcr_selection pcrs;
> > +     size_t i;
> > +     int rc;
> > +
> > +     rc = tpm2_get_pcr_info(dev, &pcrs);
> > +     if (rc)
> > +             return false;
> > +
> > +     for (i = 0; i < pcrs.count; i++) {
> > +             if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
> > +                 !tpm2_algorithm_to_len(pcrs.selection[i].hash))
> > +                     return false;
> > +     }
> > +
> > +     return true;
> > +}
>
diff mbox series

Patch

diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a6f..b061891e109c 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -734,6 +734,10 @@  config LEGACY_IMAGE_FORMAT
 config MEASURED_BOOT
 	bool "Measure boot images and configuration when booting without EFI"
 	depends on HASH && TPM_V2
+	select SHA1
+	select SHA256
+	select SHA384
+	select SHA512
 	help
 	  This option enables measurement of the boot process when booting
 	  without UEFI . Measurement involves creating cryptographic hashes
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index eac04d1c6831..fccb07fa4695 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -277,48 +277,40 @@  struct digest_info {
 #define TCG2_BOOT_HASH_ALG_SM3_256 0x00000010
 
 static const struct digest_info hash_algo_list[] = {
+#if IS_ENABLED(CONFIG_SHA1)
 	{
 		"sha1",
 		TPM2_ALG_SHA1,
 		TCG2_BOOT_HASH_ALG_SHA1,
 		TPM2_SHA1_DIGEST_SIZE,
 	},
+#endif
+#if IS_ENABLED(CONFIG_SHA256)
 	{
 		"sha256",
 		TPM2_ALG_SHA256,
 		TCG2_BOOT_HASH_ALG_SHA256,
 		TPM2_SHA256_DIGEST_SIZE,
 	},
+#endif
+#if IS_ENABLED(CONFIG_SHA384)
 	{
 		"sha384",
 		TPM2_ALG_SHA384,
 		TCG2_BOOT_HASH_ALG_SHA384,
 		TPM2_SHA384_DIGEST_SIZE,
 	},
+#endif
+#if IS_ENABLED(CONFIG_SHA512)
 	{
 		"sha512",
 		TPM2_ALG_SHA512,
 		TCG2_BOOT_HASH_ALG_SHA512,
 		TPM2_SHA512_DIGEST_SIZE,
 	},
+#endif
 };
 
-static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
-{
-	switch (a) {
-	case TPM2_ALG_SHA1:
-		return TPM2_SHA1_DIGEST_SIZE;
-	case TPM2_ALG_SHA256:
-		return TPM2_SHA256_DIGEST_SIZE;
-	case TPM2_ALG_SHA384:
-		return TPM2_SHA384_DIGEST_SIZE;
-	case TPM2_ALG_SHA512:
-		return TPM2_SHA512_DIGEST_SIZE;
-	default:
-		return 0;
-	}
-}
-
 /* NV index attributes */
 enum tpm_index_attrs {
 	TPMA_NV_PPWRITE		= 1UL << 0,
@@ -711,6 +703,41 @@  enum tpm2_algorithms tpm2_name_to_algorithm(const char *name);
  */
 const char *tpm2_algorithm_name(enum tpm2_algorithms);
 
+/**
+ * tpm2_algorithm_to_len() - Return an algorithm length for supported algorithm id
+ *
+ * @algorithm_id: algorithm defined in enum tpm2_algorithms
+ * Return: len or 0 if not supported
+ */
+u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo);
+
+/*
+ * When measured boot is enabled via EFI or bootX commands all the algorithms
+ * above are selected by our Kconfigs. Due to U-Boots nature of being small there
+ * are cases where we need some functionality from the TPM -- e.g storage or RNG
+ * but we don't want to support measurements.
+ *
+ * The choice of hash algorithms are determined by the platform and the TPM
+ * configuration. Failing to cap a PCR in a bank which the platform left
+ * active is a security vulnerability. It permits the unsealing of secrets
+ * if an attacker can replay a good set of measurements into an unused bank.
+ *
+ * On top of that a previous stage bootloader (e.g TF-A), migh pass an eventlog
+ * since it doesn't have a TPM driver, which U-Boot needs to replace. The algorit h
+ * choice is a compile time option in that case and we need to make sure we conform.
+ *
+ * Add a variable here that sums the supported algorithms U-Boot was compiled
+ * with so we can refuse to do measurements if we don't support all of them
+ */
+
+/**
+ * tpm2_allow_extend() - Check if extending PCRs is allowed and safe
+ *
+ * @dev: TPM device
+ * Return: true if allowed
+ */
+bool tpm2_allow_extend(struct udevice *dev);
+
 /**
  * tpm2_is_active_pcr() - check the pcr_select. If at least one of the PCRs
  *			  supports the algorithm add it on the active ones
diff --git a/lib/Kconfig b/lib/Kconfig
index 189e6eb31aa1..b3baa4b85b07 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -439,9 +439,6 @@  config TPM
 	depends on DM
 	imply DM_RNG
 	select SHA1
-	select SHA256
-	select SHA384
-	select SHA512
 	help
 	  This enables support for TPMs which can be used to provide security
 	  features for your board. The TPM can be connected via LPC or I2C
@@ -449,6 +446,9 @@  config TPM
 	  command to interactive the TPM. Driver model support is provided
 	  for the low-level TPM interface, but only one TPM is supported at
 	  a time by the TPM library.
+	  For size reasons only SHA1 is selected which is supported on TPM1.2.
+	  If you want a fully functional TPM enable all hashing algorithms.
+	  If you enabled measured boot all hashing algorithms are selected.
 
 config SPL_TPM
 	bool "Trusted Platform Module (TPM) Support in SPL"
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 36aace03cf4e..59e6cbafafaa 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -196,6 +196,11 @@  u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
 
 	if (!digest)
 		return -EINVAL;
+
+	if (!tpm2_allow_extend(dev)) {
+		log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
+		return -EINVAL;
+	}
 	/*
 	 * Fill the command structure starting from the first buffer:
 	 *     - the digest
@@ -409,11 +414,10 @@  int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
 
 	pcrs->count = get_unaligned_be32(response);
 	/*
-	 * We only support 5 algorithms for now so check against that
+	 * We only support 4 algorithms for now so check against that
 	 * instead of TPM2_NUM_PCR_BANKS
 	 */
-	if (pcrs->count > ARRAY_SIZE(hash_algo_list) ||
-	    pcrs->count < 1) {
+	if (pcrs->count > 4 || pcrs->count < 1) {
 		printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
 		return -EMSGSIZE;
 	}
@@ -880,3 +884,33 @@  const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
 	return "";
 }
 
+u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
+		if (hash_algo_list[i].hash_alg == algo)
+			return hash_algo_list[i].hash_len;
+	}
+
+	return 0;
+}
+
+bool tpm2_allow_extend(struct udevice *dev)
+{
+	struct tpml_pcr_selection pcrs;
+	size_t i;
+	int rc;
+
+	rc = tpm2_get_pcr_info(dev, &pcrs);
+	if (rc)
+		return false;
+
+	for (i = 0; i < pcrs.count; i++) {
+		if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
+		    !tpm2_algorithm_to_len(pcrs.selection[i].hash))
+			return false;
+	}
+
+	return true;
+}