Currently, efi_get_variable_mem() returns the raw stored format for authenticated variables, which includes the EFI_VARIABLE_AUTHENTICATION_2 descriptor . This causes image authentication failures when reading secure boot variables as callers receive wrong data containing authentication headers instead of the actual variable payload.
The UEFI Specification Section 8.2.6(EFI_VARIABLE_AUTHENTICATION_2 descriptor) explicitly states: "The authentication descriptor is not part of the variable data and is not returned by subsequent calls to GetVariable()." This patch implements spec-compliant behavior by detecting variables with the EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute and stripping the authentication descriptor before returning data to callers. Signed-off-by: Aswin Murugan <[email protected]> --- Changes in v2: - Enhanced commit message with explicit UEFI spec reference Link to v1: https://lore.kernel.org/u-boot/[email protected]/ --- lib/efi_loader/efi_var_mem.c | 44 +++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index 8d5f99f4870..edf4522e51f 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -336,9 +336,10 @@ efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, efi_uintn_t *data_size, void *data, u64 *timep, u32 mask) { - efi_uintn_t old_size; + efi_uintn_t old_size, var_data_size; struct efi_var_entry *var; u16 *pdata; + void *var_data; if (!variable_name || !vendor || !data_size) return EFI_INVALID_PARAMETER; @@ -362,19 +363,46 @@ efi_get_variable_mem(const u16 *variable_name, const efi_guid_t *vendor, if (!u16_strcmp(variable_name, vtf)) return efi_var_collect_mem(data, data_size, EFI_VARIABLE_NON_VOLATILE); + for (pdata = var->name; *pdata; ++pdata) + ; + ++pdata; + + var_data = (void *)pdata; + var_data_size = var->length; + + /* Handle EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS */ + if (var->attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) { + if (var_data_size > sizeof(struct efi_time)) { + struct efi_time *timestamp; + struct win_certificate_uefi_guid *cert; + efi_uintn_t auth_size; + + timestamp = (struct efi_time *)var_data; + cert = (struct win_certificate_uefi_guid *)(timestamp + 1); + auth_size = sizeof(struct efi_time) + cert->hdr.dwLength; + if (var_data_size > auth_size) { + var_data = (u8 *)var_data + auth_size; + var_data_size -= auth_size; + } + } + } + /* + * EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS type is old & not + * expected for auth variables + */ + else if (var->attr & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + return EFI_INVALID_PARAMETER; + old_size = *data_size; - *data_size = var->length; - if (old_size < var->length) + *data_size = var_data_size; + + if (old_size < var_data_size) return EFI_BUFFER_TOO_SMALL; if (!data) return EFI_INVALID_PARAMETER; - for (pdata = var->name; *pdata; ++pdata) - ; - ++pdata; - - efi_memcpy_runtime(data, pdata, var->length); + efi_memcpy_runtime(data, var_data, var_data_size); return EFI_SUCCESS; } -- 2.34.1

