Message ID | 20190520205501.177637-5-matthewgarrett@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add support for crypto agile logs | expand |
On Mon, 20 May 2019 at 21:55, Matthew Garrett <matthewgarrett@google.com> wrote: > > From: Matthew Garrett <mjg59@google.com> > > 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@google.com> Provided that this gets a tested-by from Bartosz, Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > --- > drivers/firmware/efi/libstub/tpm.c | 50 ++++++++++++++++++++---------- > 1 file changed, 33 insertions(+), 17 deletions(-) > > diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c > index 5bd04f75d8d6..6b3b507a54eb 100644 > --- a/drivers/firmware/efi/libstub/tpm.c > +++ b/drivers/firmware/efi/libstub/tpm.c > @@ -57,7 +57,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 +67,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 +75,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 +103,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 +136,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 +148,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 >
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c index 5bd04f75d8d6..6b3b507a54eb 100644 --- a/drivers/firmware/efi/libstub/tpm.c +++ b/drivers/firmware/efi/libstub/tpm.c @@ -57,7 +57,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 +67,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 +75,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 +103,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 +136,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 +148,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); -}