From: Lennart Poettering Date: Mon, 25 Jul 2022 15:35:16 +0000 (+0200) Subject: efi: optionally report when measuring to TPM whether we actually did X-Git-Tag: v252-rc1~542^2~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8d5e4d59f2d1c648e3cd249b55d0825c814f7ad0;p=thirdparty%2Fsystemd.git efi: optionally report when measuring to TPM whether we actually did 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. --- diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index ece1c11cd5e..193eebde0c2 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -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); diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 6905e07c851..693b3816a49 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -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); } diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c index 71085546818..9041896f5b3 100644 --- a/src/boot/efi/measure.c +++ b/src/boot/efi/measure.c @@ -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; } diff --git a/src/boot/efi/measure.h b/src/boot/efi/measure.h index af1cc62cdd0..5da160f8c87 100644 --- a/src/boot/efi/measure.h +++ b/src/boot/efi/measure.h @@ -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; } diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 83badd96cda..7f43678cb14 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -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);