[PATCH v1] efi_loader: Remove authentication header in efi variable data
Aswin Murugan
aswin.murugan at oss.qualcomm.com
Fri Jul 25 19:11:57 CEST 2025
On 7/25/2025 6:56 PM, Heinrich Schuchardt wrote:
> On 25.07.25 14:36, Aswin Murugan wrote:
>> efi_get_variable_mem() returned auth header along with ESL data for
>> authenticated variables like PK, KEK, and DB. This caused issues in
>> later stages where the auth header was misinterpreted as ESL data,
>
> Which later stages are you relating to?
> In the current implementation of efi_signature_store()
> https://source.denx.de/u-boot/u-boot/-/blob/master/lib/efi_loader/efi_signature.c#L809,
> the db variable is retrieved using efi_get_var() and passed directly to
> efi_build_signature_store(). However, for authenticated variables, the
> data
> returned by efi_get_var() includes the authentication header.
> efi_build_signature_store() expects the data pointer to begin at the start
> of the EFI Signature List, not the authentication header. This
> mismatch leads
> to a parsing error, as the header is misinterpreted as part of the
> signature
> list, resulting in an invalid signature list format.
>
> How can the error be reproduced?
> Created the ubootefi.var through tools/efivar.py and enabled
> EFI_VARIABLES_PRESEED for secure boot,
> during image authentication, wrong siglist format error was observed.
>
>> leading to parsing failures, the efi_get_variable_mem() is expected
>> to return esl data alone.
>> Added a check to remove the auth header if the variable has the
>> EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute. Now,
>> only the ESL data is returned from the function.
>
> Please, have a look at chapter 8.2.1 GetVariable in the UEFI spec.
>
> When the attribute EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS is set,
> the Data buffer shall be interpreted as follows:
> // NOTE: “||” indicates concatenation.
> // Example: EFI_VARIABLE_AUTHENTICATION_3_TIMESTAMP_TYPE
> EFI_VARIABLE_AUTHENTICATION_3 || EFI_TIME ||
> EFI_VARIABLE_AUTHENTICATION_3_CERT_ID || Data
> // Example: EFI_VARIABLE_AUTHENTICATION_3_NONCE_TYPE
> EFI_VARIABLE_AUTHENTICATION_3 || EFI_VARIABLE_AUTHENTICATION_3_NONCE
> || EFI_VARIABLE_AUTHENTICATION_3_CERT_ID || Data
>
> Isn't removing the authentication header violating the EFI specification?
> I belive that stripping the auth header during variable read might not
> violate the spec.
>
> Is tests/test_efi_secboot/test_authvar.py still passing with your patch?
> Yes, it passed
>>
>> Signed-off-by: Aswin Murugan <aswin.murugan at oss.qualcomm.com>
>> ---
>> lib/efi_loader/efi_var_mem.c | 42 +++++++++++++++++++++++++++++-------
>> 1 file changed, 34 insertions(+), 8 deletions(-)
>>
>> diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
>> index 31180df9e3a..f73daf8bdc9 100644
>> --- a/lib/efi_loader/efi_var_mem.c
>> +++ b/lib/efi_loader/efi_var_mem.c
>> @@ -309,9 +309,12 @@ 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, auth_size;
>> struct efi_var_entry *var;
>> u16 *pdata;
>> + void *var_data;
>> + struct efi_time *timestamp;
>> + struct win_certificate_uefi_guid *cert;
>
> Please, move variable definitions to the innermost code block where
> they are used.
>
> Best regards
>
> Heinrich
>
>> if (!variable_name || !vendor || !data_size)
>> return EFI_INVALID_PARAMETER;
>> @@ -335,19 +338,42 @@ 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)) {
>> + 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;
>> }
>
More information about the U-Boot
mailing list