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

Ilias Apalodimas ilias.apalodimas at linaro.org
Fri May 15 09:54:41 CEST 2026


Hi Ashwin

On Thu, 14 May 2026 at 14:01, Aswin Murugan
<aswin.murugan at oss.qualcomm.com> wrote:
>
> 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.

Yes, that's what I was trying to figure out on your setup

Cheers
/Ilias
>
> 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