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.
This commit is contained in:
Lennart Poettering
2022-08-02 10:28:49 +02:00
parent c794e280e9
commit 8d5e4d59f2
5 changed files with 69 additions and 21 deletions
+1 -1
View 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);
+2 -1
View 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);
}
+50 -14
View 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_load_options(const char16_t *load_options) {
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, 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;
err = tpm_log_event(pcr,
POINTER_TO_PHYSICAL_ADDRESS(load_options),
strsize16(load_options), load_options);
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, &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;
}
+15 -4
View 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;
}
+1 -1
View 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);