]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi: optionally report when measuring to TPM whether we actually did
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Jul 2022 15:35:16 +0000 (17:35 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 2 Aug 2022 08:28:49 +0000 (10:28 +0200)
the measurement calls can succeed either when they actually measured
something, or when they skipped measurement because the local system
didn't support TPMs.

Let's optionally return a boolean saying which case it is. This is later
useful to tell userspace how and if we measured something.

src/boot/efi/boot.c
src/boot/efi/cpio.c
src/boot/efi/measure.c
src/boot/efi/measure.h
src/boot/efi/stub.c

index ece1c11cd5ed078590f02512d0cec8903cf0e7a2..193eebde0c21652a436b3c529031103a15051b9e 100644 (file)
@@ -2339,7 +2339,7 @@ static EFI_STATUS image_start(
                 loaded_image->LoadOptionsSize = strsize16(options);
 
                 /* Try to log any options to the TPM, especially to catch manually edited options */
-                (void) tpm_log_load_options(options);
+                (void) tpm_log_load_options(options, NULL);
         }
 
         efivar_set_time_usec(LOADER_GUID, L"LoaderTimeExecUSec", 0);
index 6905e07c851c6d841a5e25799cb6fc8464190236..693b3816a49330f11892ddb6da5ba4978d15c108 100644 (file)
@@ -436,7 +436,8 @@ EFI_STATUS pack_cpio(
                                 tpm_pcr[i],
                                 POINTER_TO_PHYSICAL_ADDRESS(buffer),
                                 buffer_size,
-                                tpm_description);
+                                tpm_description,
+                                NULL);
                 if (err != EFI_SUCCESS)
                         log_error_stall(L"Unable to add initrd TPM measurement for PCR %u (%s), ignoring: %r", tpm_pcr[i], tpm_description, err);
         }
index 7108554681814820a116f7871f0acfb522d94808..9041896f5b373c21659a961089e2e4a7a7d1e921 100644 (file)
@@ -141,43 +141,79 @@ bool tpm_present(void) {
         return tcg2_interface_check() || tcg1_interface_check();
 }
 
-EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description) {
-        EFI_TCG *tpm1;
+EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description, bool *ret_measured) {
         EFI_TCG2 *tpm2;
+        EFI_STATUS err;
 
         assert(description);
 
-        /* PCR disabled */
-        if (pcrindex == UINT32_MAX)
+        /* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
+         * something, or false if measurement was turned off. */
+
+        if (pcrindex == UINT32_MAX) { /* PCR disabled? */
+                if (ret_measured)
+                        *ret_measured = false;
+
                 return EFI_SUCCESS;
+        }
 
         tpm2 = tcg2_interface_check();
         if (tpm2)
-                return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
+                err = tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
+        else {
+                EFI_TCG *tpm1;
 
-        tpm1 = tcg1_interface_check();
-        if (tpm1)
-                return tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description);
+                tpm1 = tcg1_interface_check();
+                if (tpm1)
+                        err = tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description);
+                else {
+                        /* No active TPM found, so don't return an error */
 
-        /* No active TPM found, so don't return an error */
-        return EFI_SUCCESS;
+                        if (ret_measured)
+                                *ret_measured = false;
+
+                        return EFI_SUCCESS;
+                }
+        }
+
+        if (err == EFI_SUCCESS && ret_measured)
+                *ret_measured = true;
+
+        return err;
+}
+
+EFI_STATUS tpm_log_event_ascii(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char *description, bool *ret_measured) {
+        _cleanup_free_ char16_t *c = NULL;
+
+        if (description)
+                c = xstra_to_str(description);
+
+        return tpm_log_event(pcrindex, buffer, buffer_size, c, ret_measured);
 }
 
-EFI_STATUS tpm_log_load_options(const char16_t *load_options) {
+EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured) {
+        int measured = -1;
         EFI_STATUS err;
 
         /* Measures a load options string into the TPM2, i.e. the kernel command line */
 
         for (UINTN i = 0; i < 2; i++) {
                 uint32_t pcr = i == 0 ? TPM_PCR_INDEX_KERNEL_PARAMETERS : TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT;
+                bool m;
+
+                if (pcr == UINT32_MAX) /* Skip this one, if it's invalid, so that our 'measured' return value is not corrupted by it */
+                        continue;
 
-                err = tpm_log_event(pcr,
-                                    POINTER_TO_PHYSICAL_ADDRESS(load_options),
-                                    strsize16(load_options), load_options);
+                err = tpm_log_event(pcr, POINTER_TO_PHYSICAL_ADDRESS(load_options), strsize16(load_options), load_options, &m);
                 if (err != EFI_SUCCESS)
                         return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", pcr, err);
+
+                measured = measured < 0 ? m : (measured && m);
         }
 
+        if (ret_measured)
+                *ret_measured = measured < 0 ? false : measured;
+
         return EFI_SUCCESS;
 }
 
index af1cc62cdd0a35f7de62059da3d5f642c0a70a2e..5da160f8c87b3da13b3d7da2ebf8fed7a42426cc 100644 (file)
@@ -22,8 +22,9 @@
 #if ENABLE_TPM
 
 bool tpm_present(void);
-EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description);
-EFI_STATUS tpm_log_load_options(const char16_t *cmdline);
+EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description, bool *ret_measured);
+EFI_STATUS tpm_log_event_ascii(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char *description, bool *ret_measured);
+EFI_STATUS tpm_log_load_options(const char16_t *cmdline, bool *ret_measured);
 
 #else
 
@@ -31,11 +32,21 @@ static inline bool tpm_present(void) {
         return false;
 }
 
-static inline EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description) {
+static inline EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description, bool *ret_measured) {
+        if (ret_measured)
+                *ret_measured = false;
         return EFI_SUCCESS;
 }
 
-static inline EFI_STATUS tpm_log_load_options(const char16_t *cmdline) {
+static inline EFI_STATUS tpm_log_event_ascii(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char *description, bool *ret_measured) {
+        if (ret_measured)
+                *ret_measured = false;
+        return EFI_SUCCESS;
+}
+
+static inline EFI_STATUS tpm_log_load_options(const char16_t *cmdline, bool *ret_measured) {
+        if (ret_measured)
+                *ret_measured = false;
         return EFI_SUCCESS;
 }
 
index 83badd96cda10a484725326174700e8d92df5d4d..7f43678cb14001985716bc1abffedbc1939eeaf8 100644 (file)
@@ -223,7 +223,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
                  * duplicates what we already did in the boot menu, if that was already used. However, since
                  * we want the boot menu to support an EFI binary, and want to this stub to be usable from
                  * any boot menu, let's measure things anyway. */
-                (void) tpm_log_load_options(loaded_image->LoadOptions);
+                (void) tpm_log_load_options(loaded_image->LoadOptions, NULL);
         }
 
         export_variables(loaded_image);