[PATCH v1] efi_loader: Remove authentication header in efi variable data

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Jul 25 15:26:28 CEST 2025


On 25.07.25 14:36, Aswin Murugan wrote:
> efi_get_variable_mem() returned auth header along with ESL data for
> authenticated variables like PK, KEK, and DB. This caused issues in
> later stages where the auth header was misinterpreted as ESL data,

Which later stages are you relating to?
How can the error be reproduced?

> leading to parsing failures, the efi_get_variable_mem() is expected
> to return esl data alone.
> Added a check to remove the auth header if the variable has the
> EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute. Now,
> only the ESL data is returned from the function.

Please, have a look at chapter 8.2.1 GetVariable in the UEFI spec.

When the attribute EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS is set, 
the Data buffer shall be interpreted as follows:
// NOTE: “||” indicates concatenation.
// Example: EFI_VARIABLE_AUTHENTICATION_3_TIMESTAMP_TYPE
EFI_VARIABLE_AUTHENTICATION_3 || EFI_TIME || 
EFI_VARIABLE_AUTHENTICATION_3_CERT_ID || Data
// Example: EFI_VARIABLE_AUTHENTICATION_3_NONCE_TYPE
EFI_VARIABLE_AUTHENTICATION_3 || EFI_VARIABLE_AUTHENTICATION_3_NONCE || 
EFI_VARIABLE_AUTHENTICATION_3_CERT_ID || Data

Isn't removing the authentication header violating the EFI specification?

Is tests/test_efi_secboot/test_authvar.py still passing with your patch?

> 
> Signed-off-by: Aswin Murugan <aswin.murugan at oss.qualcomm.com>
> ---
>   lib/efi_loader/efi_var_mem.c | 42 +++++++++++++++++++++++++++++-------
>   1 file changed, 34 insertions(+), 8 deletions(-)
> 
> diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
> index 31180df9e3a..f73daf8bdc9 100644
> --- a/lib/efi_loader/efi_var_mem.c
> +++ b/lib/efi_loader/efi_var_mem.c
> @@ -309,9 +309,12 @@ 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, auth_size;
>   	struct efi_var_entry *var;
>   	u16 *pdata;
> +	void *var_data;
> +	struct efi_time *timestamp;
> +	struct win_certificate_uefi_guid *cert;

Please, move variable definitions to the innermost code block where they 
are used.

Best regards

Heinrich

>   
>   	if (!variable_name || !vendor || !data_size)
>   		return EFI_INVALID_PARAMETER;
> @@ -335,19 +338,42 @@ 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)) {
> +			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;
>   }



More information about the U-Boot mailing list