Message ID | 20240622143601.187723-8-ilias.apalodimas@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | The great TCG deduplication saga | expand |
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; > +}
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 --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; +}
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(-)