[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