[PATCH v3] tools: efivar: strip auth descriptor for authenticated variables

Ilias Apalodimas ilias.apalodimas at linaro.org
Fri May 15 12:32:49 CEST 2026


Hi Ashwin,

On Thu, 14 May 2026 at 20:17, Aswin Murugan
<aswin.murugan at oss.qualcomm.com> wrote:
>
> efivar.py currently stores authenticated variables including the
> EFI_VARIABLE_AUTHENTICATION_2 descriptor (timestamp + WIN_CERTIFICATE)
> along with the payload.
>
> When variables are set via U-Boot, SetVariable() validates and strips
> this authentication descriptor before persisting the variable data,
> resulting in only the payload being stored and returned by GetVariable().
>
> This mismatch causes efivar.py-generated stores to differ from U-Boot
> runtime behavior and leads to incorrect GetVariable() results.
>
> Update efivar.py to strip the authentication descriptor and store only
> the payload for authenticated variables, ensuring consistency with
> U-Boot behavior and compliance with UEFI expectations.

The approach is fine, but when I use the tool now to create signatures
and enable secure boot I am getting
=> bootefi bootmgr
Getting signature database(db) failed"

Have you tried a built that worked locally?

Thanks
/Ilias
>
> Signed-off-by: Aswin Murugan <aswin.murugan at oss.qualcomm.com>
> ---
> Changes in v3:
> - Previously stripped the authentication descriptor at GetVariable(),
>   now moved to strip it in efivar.py during variable pre-seeding/set.
> Link to v2: https://lore.kernel.org/u-boot/20260512194205.1905069-1-aswin.murugan@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/
> ---
>  tools/efivar.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/tools/efivar.py b/tools/efivar.py
> index 67729fa8505..d248cd868ba 100755
> --- a/tools/efivar.py
> +++ b/tools/efivar.py
> @@ -79,6 +79,50 @@ class EfiVariable:
>  def calc_crc32(buf):
>      return zlib.crc32(buf) & 0xffffffff
>
> +def strip_auth_descriptor(data, attrs):
> +    """
> +    Strip the EFI auth descriptor from authenticated variable data.
> +
> +    This is used during efivar.py-based pre-seeding of ubootefi.var to
> +    match U-Boot SetVariable() behavior, where the authentication header
> +    is consumed during validation and only the payload is stored.
> +
> +    For variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS:
> +    - Input format: [EFI_VARIABLE_AUTHENTICATION_2 | payload]
> +    - Stored format: [payload only]
> +
> +    Auth header size calculation (aligned with U-Boot efi_variable_authenticate()):
> +        auth_size = sizeof(EFI_TIME) + WIN_CERTIFICATE.dwLength
> +
> +    Only the payload portion is retained after stripping the header.
> +    """
> +    if not (attrs & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS):
> +        return data
> +    if not data:
> +        return data
> +
> +    efi = EfiStruct()
> +    if len(data) < efi.var_time_size:
> +        return data
> +
> +    offset = efi.var_time_size
> +    if len(data) < offset + efi.var_win_cert_size:
> +        return data
> +
> +    try:
> +        cert_hdr = struct.unpack_from(efi.var_win_cert_fmt, data, offset)
> +        dwLength = cert_hdr[0]
> +    except struct.error:
> +        return data
> +
> +    auth_size = efi.var_time_size + dwLength
> +    if auth_size <= 0 or auth_size > len(data):
> +        return data
> +
> +    if len(data) <= auth_size:
> +        return b''
> +    return data[auth_size:]
> +
>  class EfiVariableStore:
>      def __init__(self, infile):
>          self.infile = infile
> @@ -172,8 +216,12 @@ class EfiVariableStore:
>                  break
>              offs = loffs
>
> +        if data and (attrs & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS):
> +            data = strip_auth_descriptor(data, attrs)
> +            size = len(data) if data else 0
> +
>          tsec = int(time.time()) if attrs & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS else 0
> -        nd = name.encode('utf_16_le') + b"\x00\x00" + data
> +        nd = name.encode('utf_16_le') + b"\x00\x00" + (data if data else b'')
>          # U-Boot variable format requires the name + data blob to be 8-byte aligned
>          pad = ((len(nd) + 7) & ~7) - len(nd)
>          nd += bytes([0] * pad)
> --
> 2.34.1
>


More information about the U-Boot mailing list