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

Aswin Murugan aswin.murugan at oss.qualcomm.com
Fri May 15 15:17:34 CEST 2026


Hi Ilias,

This change has been verified locally with our setups on qcs615 & 
QCS9100 SOCs

Regards,
Aswin

On 5/15/2026 4:02 PM, Ilias Apalodimas wrote:
> 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