boot: report missing GetActivePcrBanks() call in formware as UINT32_MAX PCR bank mask

Fixes: #39150
This commit is contained in:
Lennart Poettering
2025-11-13 09:30:43 +01:00
parent 7643e4a89c
commit b2b8fb8105
3 changed files with 36 additions and 20 deletions

View File

@@ -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;

View File

@@ -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 },
};
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);
uint32_t tcg_bits = 0;
FOREACH_ELEMENT(t, table)
SET_FLAG(tcg_bits, t->tcg, efi_bits & t->efi);
cache = tcg_bits;
cache = tcg_bits;
}
cache_valid = true;
}
if (ret)

View File

@@ -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;