]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
commands/bli: Set LoaderTpm2ActivePcrBanks runtime variable
authorLuca Boccassi <luca.boccassi@gmail.com>
Fri, 25 Jul 2025 13:47:05 +0000 (14:47 +0100)
committerDaniel Kiper <daniel.kiper@oracle.com>
Thu, 14 Aug 2025 19:20:01 +0000 (21:20 +0200)
It turns out checking from userspace is not 100% reliable to figure out
whether the firmware had TPM2 support enabled or not. For example with
EDK2 arm64, the default upstream build config bundles TPM2 support with
SecureBoot support, so if the latter is disabled, TPM2 is also unavailable.
But still, the ACPI TPM2 table is created just as if it was enabled. So,
/sys/firmware/acpi/tables/TPM2 exists and looks correct but there are no
measurements, neither the firmware nor the loader/stub can do them, and
/sys/kernel/security/tpm0/binary_bios_measurements does not exist.
So, userspace cannot really tell what was going on in UEFI mode.

The loader can use the apposite UEFI protocol to check, which is a more
definitive answer. Export the bitmask with the list of active banks as-is.
If it's not 0, then in userspace we can be sure a working TPM2 was available
in UEFI mode.

systemd-boot and systemd-stub v258 (current main) set this variable and
userspace portion consumes it to be able to tell what was available in
the firmware context.

Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/commands/bli.c
grub-core/commands/efi/tpm.c
include/grub/tpm.h

index 298c5f70a8762b02f2105dc13988fd3601f772c6..38f52f87a477ca65865763848c7a9f0f316879f0 100644 (file)
@@ -28,6 +28,7 @@
 #include <grub/misc.h>
 #include <grub/mm.h>
 #include <grub/partition.h>
+#include <grub/tpm.h>
 #include <grub/types.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -127,12 +128,34 @@ set_loader_device_part_uuid (void)
   return status;
 }
 
+static grub_err_t
+set_loader_active_pcr_banks (void)
+{
+  grub_efi_uint32_t active_pcr_banks;
+  char *active_pcr_banks_str;
+  grub_err_t status;
+
+  active_pcr_banks = grub_tpm2_active_pcr_banks();
+  active_pcr_banks_str = grub_xasprintf ("0x%08x", active_pcr_banks);
+  if (active_pcr_banks_str == NULL)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate active PCR banks string"));
+
+  status = grub_efi_set_variable_to_string ("LoaderTpm2ActivePcrBanks",
+                                            &bli_vendor_guid,
+                                            active_pcr_banks_str,
+                                            GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                            GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
+  grub_free (active_pcr_banks_str);
+  return status;
+}
+
 GRUB_MOD_INIT (bli)
 {
   grub_efi_set_variable_to_string ("LoaderInfo", &bli_vendor_guid, PACKAGE_STRING,
                                   GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
                                   GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
   set_loader_device_part_uuid ();
+  set_loader_active_pcr_banks ();
   /* No error here is critical, other than being logged */
   grub_print_error ();
 }
index cbac6986691645711eec5e69dd3f64cab86bdf7f..59d0b67085a1f536c84b26dcf54202f72bf86404 100644 (file)
@@ -332,3 +332,36 @@ grub_tpm_present (void)
       return grub_tpm2_present (tpm);
     }
 }
+
+grub_uint32_t
+grub_tpm2_active_pcr_banks (void)
+{
+  grub_efi_handle_t tpm_handle;
+  grub_efi_uint8_t protocol_version;
+  grub_efi_tpm2_protocol_t *tpm;
+  grub_efi_uint32_t active_pcr_banks = 0;
+
+  if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
+    return 0;
+
+  if (protocol_version == 1)
+    return 0; /* We report TPM2 status */
+
+  tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
+                               GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+  if (tpm == NULL)
+    {
+      grub_dprintf ("tpm", "Cannot open TPM2 protocol\n");
+      return 0;
+    }
+
+  if (grub_tpm2_present (tpm))
+    {
+      grub_efi_status_t status = tpm->get_active_pcr_banks (tpm, &active_pcr_banks);
+
+      if (status != GRUB_EFI_SUCCESS)
+       return 0; /* Assume none available if the call fails. */
+    }
+
+  return active_pcr_banks;
+}
index d09783dacc0a5a03d60d6baa1b9fe1368ad9ada5..fd0956b39d794ed8aa1c9e0692febb1db0e30417 100644 (file)
@@ -39,6 +39,7 @@
 grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size,
                             grub_uint8_t pcr, const char *description);
 int grub_tpm_present (void);
+grub_uint32_t grub_tpm2_active_pcr_banks (void);
 
 static inline bool
 grub_is_tpm_fail_fatal (void)