[PATCH v2] efi_loader: Remove authentication header in GetVariable()

Aswin Murugan aswin.murugan at oss.qualcomm.com
Thu May 14 13:01:08 CEST 2026


Hi Ilias,

We are attempting to pre-seed ubootefi.var created using the *efivar.py* 
tool for authenticated EFI variables.
Currently, efivar.py writes variables including the full authentication 
descriptor (timestamp + WIN_CERTIFICATE + payload) into ubootefi.var.

As per the CI tests shared, it stores the authenticated EFI variables 
using setenv
When authenticated variables are set via U‑Boot using setenv -e -at, the 
flow goes through SetVariable(), where the firmware:

  * parses and validates the authentication descriptor
  * removes the authentication header
  * stores only the variable payload


Due to this mismatch, variables created with efivar.py differ from those 
created via U‑Boot:

GetVariable() returns descriptor + payload instead of payload-only, this 
leads to inconsistent and non‑compliant variable behavior

Fix Proposed:

Strip the authentication descriptor within efivar.py during variable 
write, so that only the payload is stored in ubootefi.var, matching 
U‑Boot SetVariable() behavior. Please confirm if there are any concerns 
with this approach.

Regards,
Aswin

On 5/13/2026 11:54 AM, Ilias Apalodimas wrote:
> Hi Aswin,
>
> On Tue, 12 May 2026 at 22:42, Aswin Murugan
> <aswin.murugan at oss.qualcomm.com> wrote:
>> 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.
> What are 'the callers'? The EFI security related variables are usually
> read and consumed by the firmware itself during secure boot. I don't
> remember the code on top of my head, but i think we end up storing the
> auth info because it also contains timestamps etc.
>
>> 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()."
> We can strip the headers during GetVariable, but you need more changes
> apart from the one here. The EFI secure boot tests fail with the
> change above [1].
>
>> 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.
> [1] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/30086
>
> Regards
> /Ilias
>> Signed-off-by: Aswin Murugan <aswin.murugan at oss.qualcomm.com>
>> ---
>> Changes in v2:
>> - Enhanced commit message with explicit UEFI spec reference
>> Link to v1: https://lore.kernel.org/u-boot/20250725123653.513252-1-aswin.murugan@oss.qualcomm.com/
>> ---
>>   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
>>


More information about the U-Boot mailing list