[PATCH v3] tools: efivar: strip auth descriptor for authenticated variables
Ilias Apalodimas
ilias.apalodimas at linaro.org
Mon May 18 10:37:24 CEST 2026
On Fri, 15 May 2026 at 16:17, Aswin Murugan
<aswin.murugan at oss.qualcomm.com> wrote:
>
> Hi Ilias,
>
> This change has been verified locally with our setups on qcs615 &
> QCS9100 SOCs
Ok I am getting the same error here. How did you produce the final binary?
The only test I am doing here is enable secure boot and variable
preseed. The generate the preseed with
./tools/efivar.py set -i ubootefi.var -n pk -d PK.esl -t file
./tools/efivar.py set -i ubootefi.var -n kek -d KEK.esl -t file
./tools/efivar.py set -i ubootefi.var -n db -d db.esl -t file
./tools/efivar.py set -i ubootefi.var -n dbx -d dbx.esl -t file
Thanks
/Ilias
>
> 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