On Fri, 17 May 2019 at 23:39, Matthew Garrett <matthewgarrett@xxxxxxxxxx> wrote: > > From: Matthew Garrett <mjg59@xxxxxxxxxx> > > Right now we only attempt to obtain the SHA1-only event log. The > protocol also supports a crypto agile log format, which contains digests > for all algorithms in use. Attempt to obtain this first, and fall back > to obtaining the older format if the system doesn't support it. This is > lightly complicated by the event sizes being variable (as we don't know > in advance which algorithms are in use), and the interface giving us > back a pointer to the start of the final entry rather than a pointer to > the end of the log - as a result, we need to parse the final entry to > figure out its length in order to know how much data to copy up to the > OS. > > Signed-off-by: Matthew Garrett <mjg59@xxxxxxxxxx> > Tested-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> > Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> This signoff doesn't belong here I think? > --- > drivers/firmware/efi/libstub/tpm.c | 57 ++++++++++++++++++++---------- > 1 file changed, 39 insertions(+), 18 deletions(-) > > diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c > index 5bd04f75d8d6..b3f30448e454 100644 > --- a/drivers/firmware/efi/libstub/tpm.c > +++ b/drivers/firmware/efi/libstub/tpm.c > @@ -8,8 +8,13 @@ > * Thiebaud Weksteen <tweek@xxxxxxxxxx> > */ > #include <linux/efi.h> > -#include <linux/tpm_eventlog.h> > #include <asm/efi.h> > +/* > + * KASAN redefines memcpy() in a way that isn't available in the EFI stub. > + * We need to include asm/efi.h before linux/tpm_eventlog.h in order to avoid > + * the wrong memcpy() being referenced. > + */ > +#include <linux/tpm_eventlog.h> > Please drop this hunk. I just sent out a patch to fix this properly. > #include "efistub.h" > > @@ -57,7 +62,7 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) > > #endif > > -static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) > +void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg) > { > efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; > efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID; > @@ -67,6 +72,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) > unsigned long first_entry_addr, last_entry_addr; > size_t log_size, last_entry_size; > efi_bool_t truncated; > + int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; > void *tcg2_protocol = NULL; > > status = efi_call_early(locate_protocol, &tcg2_guid, NULL, > @@ -74,14 +80,20 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) > if (status != EFI_SUCCESS) > return; > > - status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol, > - EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2, > - &log_location, &log_last_entry, &truncated); > - if (status != EFI_SUCCESS) > - return; > + status = efi_call_proto(efi_tcg2_protocol, get_event_log, > + tcg2_protocol, version, &log_location, > + &log_last_entry, &truncated); > + > + if (status != EFI_SUCCESS || !log_location) { > + version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; > + status = efi_call_proto(efi_tcg2_protocol, get_event_log, > + tcg2_protocol, version, &log_location, > + &log_last_entry, &truncated); > + if (status != EFI_SUCCESS || !log_location) > + return; > + > + } > > - if (!log_location) > - return; > first_entry_addr = (unsigned long) log_location; > > /* > @@ -96,8 +108,23 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) > * We need to calculate its size to deduce the full size of > * the logs. > */ > - last_entry_size = sizeof(struct tcpa_event) + > - ((struct tcpa_event *) last_entry_addr)->event_size; > + if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) { > + /* > + * The TCG2 log format has variable length entries, > + * and the information to decode the hash algorithms > + * back into a size is contained in the first entry - > + * pass a pointer to the final entry (to calculate its > + * size) and the first entry (so we know how long each > + * digest is) > + */ > + last_entry_size = > + __calc_tpm2_event_size((void *)last_entry_addr, > + (void *)(long)log_location, > + false); > + } else { > + last_entry_size = sizeof(struct tcpa_event) + > + ((struct tcpa_event *) last_entry_addr)->event_size; > + } > log_size = log_last_entry - log_location + last_entry_size; > } > > @@ -114,7 +141,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) > > memset(log_tbl, 0, sizeof(*log_tbl) + log_size); > log_tbl->size = log_size; > - log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; > + log_tbl->version = version; > memcpy(log_tbl->log, (void *) first_entry_addr, log_size); > > status = efi_call_early(install_configuration_table, > @@ -126,9 +153,3 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) > err_free: > efi_call_early(free_pool, log_tbl); > } > - > -void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg) > -{ > - /* Only try to retrieve the logs in 1.2 format. */ > - efi_retrieve_tpm2_eventlog_1_2(sys_table_arg); > -} > -- > 2.21.0.1020.gf2820cf01a-goog >