From: Lennart Poettering Date: Thu, 13 Nov 2025 08:30:43 +0000 (+0100) Subject: boot: report missing GetActivePcrBanks() call in formware as UINT32_MAX PCR bank... X-Git-Tag: v259-rc1~48^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b2b8fb810509442ceca33555d47a04ff527b3da7;p=thirdparty%2Fsystemd.git boot: report missing GetActivePcrBanks() call in formware as UINT32_MAX PCR bank mask Fixes: #39150 --- diff --git a/src/boot/measure.c b/src/boot/measure.c index b1433ff1b50..22129cb87d6 100644 --- a/src/boot/measure.c +++ b/src/boot/measure.c @@ -198,8 +198,8 @@ uint32_t tpm_get_active_pcr_banks(void) { /* GetActivePcrBanks() was added only in version 1.1 of the spec */ if (version.Major < 1 || (version.Major == 1 && version.Minor < 1)) { - log_debug("TCG protocol too old for GetActivePcrBanks(), claiming no active banks."); - return 0; + log_debug("TCG protocol too old for GetActivePcrBanks(), returning wildcard bank information."); + return UINT32_MAX; } uint32_t active_pcr_banks = 0; diff --git a/src/shared/efi-api.c b/src/shared/efi-api.c index 608001b6e2d..ad9cbab74e1 100644 --- a/src/shared/efi-api.c +++ b/src/shared/efi-api.c @@ -525,10 +525,15 @@ int efi_get_boot_options(uint16_t **ret_options) { int efi_get_active_pcr_banks(uint32_t *ret) { #if ENABLE_EFI - static uint32_t cache = UINT32_MAX; + static uint32_t cache = 0; + static bool cache_valid = false; int r; - if (cache == UINT32_MAX) { + /* Returns the enabled PCR banks as bitmask, as reported by firmware. If the bitmask is returned as + * UINT32_MAX, the firmware supports the TCG protocol, but in a version too old to report this + * information. */ + + if (!cache_valid) { _cleanup_free_ char *active_pcr_banks = NULL; r = efi_get_variable_string(EFI_LOADER_VARIABLE_STR("LoaderTpm2ActivePcrBanks"), &active_pcr_banks); if (r < 0) @@ -539,22 +544,29 @@ int efi_get_active_pcr_banks(uint32_t *ret) { if (r < 0) return log_debug_errno(r, "Failed to parse LoaderTpm2ActivePcrBanks variable: %m"); - /* EFI TPM protocol uses different bit values for the hash algorithms, let's convert */ - static const struct { - uint32_t efi; - uint32_t tcg; - } table[] = { - { EFI_TCG2_BOOT_HASH_ALG_SHA1, 1U << TPM2_ALG_SHA1 }, - { EFI_TCG2_BOOT_HASH_ALG_SHA256, 1U << TPM2_ALG_SHA256 }, - { EFI_TCG2_BOOT_HASH_ALG_SHA384, 1U << TPM2_ALG_SHA384 }, - { EFI_TCG2_BOOT_HASH_ALG_SHA512, 1U << TPM2_ALG_SHA512 }, - }; - - uint32_t tcg_bits = 0; - FOREACH_ELEMENT(t, table) - SET_FLAG(tcg_bits, t->tcg, efi_bits & t->efi); - - cache = tcg_bits; + if (efi_bits == UINT32_MAX) + /* UINT32_MAX means that the firmware API doesn't implement GetActivePcrBanks() and caller must guess */ + cache = UINT32_MAX; + else { + /* EFI TPM protocol uses different bit values for the hash algorithms, let's convert */ + static const struct { + uint32_t efi; + uint32_t tcg; + } table[] = { + { EFI_TCG2_BOOT_HASH_ALG_SHA1, 1U << TPM2_ALG_SHA1 }, + { EFI_TCG2_BOOT_HASH_ALG_SHA256, 1U << TPM2_ALG_SHA256 }, + { EFI_TCG2_BOOT_HASH_ALG_SHA384, 1U << TPM2_ALG_SHA384 }, + { EFI_TCG2_BOOT_HASH_ALG_SHA512, 1U << TPM2_ALG_SHA512 }, + }; + + uint32_t tcg_bits = 0; + FOREACH_ELEMENT(t, table) + SET_FLAG(tcg_bits, t->tcg, efi_bits & t->efi); + + cache = tcg_bits; + } + + cache_valid = true; } if (ret) diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index de7e3d9728c..c74162302ca 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -2705,7 +2705,9 @@ int tpm2_get_best_pcr_bank( /* If variable is not set use guesswork below */ log_debug("Boot loader didn't set the LoaderTpm2ActivePcrBanks EFI variable, we have to guess the used PCR banks."); - } else { + } else if (efi_banks == UINT32_MAX) + log_debug("Boot loader set the LoaderTpm2ActivePcrBanks EFI variable to indicate that the GetActivePcrBanks() API is not available in the firmware. We have to guess the used PCR banks."); + else { if (BIT_SET(efi_banks, TPM2_ALG_SHA256)) *ret = TPM2_ALG_SHA256; else if (BIT_SET(efi_banks, TPM2_ALG_SHA1)) @@ -2812,7 +2814,9 @@ int tpm2_get_good_pcr_banks( /* If the variable is not set we have to guess via the code below */ log_debug("Boot loader didn't set the LoaderTpm2ActivePcrBanks EFI variable, we have to guess the used PCR banks."); - } else { + } else if (efi_banks == UINT32_MAX) + log_debug("Boot loader set the LoaderTpm2ActivePcrBanks EFI variable to indicate that the GetActivePcrBanks() API is not available in the firmware. We have to guess the used PCR banks."); + else { FOREACH_ARRAY(hash, tpm2_hash_algorithms, TPM2_N_HASH_ALGORITHMS) { if (!BIT_SET(efi_banks, *hash)) continue;