[Skiboot] [PATCH 1/4] secvar: ensure ESL buf size is at least what ESL header expects

Daniel Axtens dja at axtens.net
Mon Jun 28 23:12:12 AEST 2021

Nick Child <nnac123 at gmail.com> writes:

> Currently, `get_esl_cert` receives a data buffer containing an ESL and it's
(nit: its, not "it's")

> length. It is to return a data buffer of the certificate that is contained
> inside the ESL. The ESL has header info that contains the certificates
> `size`  and the size of the header (`sig_data_offset`). We use this
> information to copy `size` bytes starting `sig_data_offset` bytes after the
> given ESL buffer. Currently we are checking that the length of the ESL
> buffer is at least `sig_data_offset` bytes but we are not checking that it
> also has enough bytes to also contain `size` bytes of the certificate. This
> becomes problematic if some data at the end of the ESL gets lost. Since the
> ESL claims it has more than it actually does, this will lead to a buffer
> over-read. What is even worse, is that this buffer over-read can go
> unnoticed since the last 256 bytes of the ESL are usually the x509 2048 bit
> signature so the extra garbage bytes that are copied will appear to be a
> valid rsa signature.
> To resolve this, a conditional is has been added to ensure that the ESL

Another nit: "conditional is has been" -> "conditional is", or even
better, simply "ensure that ..." - see

> buffer length is large enough to hold the data that it claims it contains.
> Lastly, a new test case is added to test the described condition. It
> includes a new test file `trimmedKEK.h` which contains a struct a valid KEK
> auth file minus 5 bytes, therefore making it invalid.
> Signed-off-by: Nick Child <nick.child at ibm.com>
> ---
>  libstb/secvar/backend/edk2-compat-process.c  |   4 +-
>  libstb/secvar/test/data/trimmedKEK.h         | 161 +++++++++++++++++++
>  libstb/secvar/test/secvar-test-edk2-compat.c |  16 ++
>  3 files changed, 180 insertions(+), 1 deletion(-)
>  create mode 100644 libstb/secvar/test/data/trimmedKEK.h
> diff --git a/libstb/secvar/backend/edk2-compat-process.c b/libstb/secvar/backend/edk2-compat-process.c
> index 244f2340..e1101a4c 100644
> --- a/libstb/secvar/backend/edk2-compat-process.c
> +++ b/libstb/secvar/backend/edk2-compat-process.c
> @@ -135,8 +135,10 @@ static int get_esl_cert(const char *buf, const size_t buflen, char **cert)
>  	sig_data_offset = sizeof(EFI_SIGNATURE_LIST)
>  			  + le32_to_cpu(list->SignatureHeaderSize)
>  			  + 16 * sizeof(uint8_t);
> -	if (sig_data_offset > buflen)
> +	if (sig_data_offset + size > buflen) {
> +		prlog(PR_ERR, "Number of bytes of ESL data is less than size specified\n");
>  		return OPAL_PARAMETER;
> +	}
>  	*cert = zalloc(size);
>  	if (!(*cert))
> diff --git a/libstb/secvar/test/data/trimmedKEK.h b/libstb/secvar/test/data/trimmedKEK.h
> new file mode 100644
> index 00000000..6600d254
> --- /dev/null
> +++ b/libstb/secvar/test/data/trimmedKEK.h
> @@ -0,0 +1,161 @@
> +unsigned char trimmedKEK_auth[]  = {
> +0xe4 ,0x07 ,0x09 ,0x0e ,0x0e ,0x22 ,0x2e ,0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
> +,0xd3 ,0x05 ,0x00 ,0x00 ,0x00 ,0x02 ,0xf1 ,0x0e  ,0x9d ,0xd2 ,0xaf ,0x4a ,0xdf ,0x68 ,0xee ,0x49

How are you creating these? I ask because the commas are in weird

FWIW I use 'xxd -i foo > foo.h'.

> +	/* Add trimmed KEK, .process(), should fail. */
> +	printf("Add trimmed KEK\n");
> +	tmp = new_secvar("KEK", 4, trimmedKEK_auth, trimmedKEK_auth_len, 0);
> +	ASSERT(0 == edk2_compat_validate(tmp));

Intuitively it seems edk2_compat_validate() should catch this, but I see
looking at the code that _validate() currently simply validates that the
variable being updated is one of the recognised SB vars and that the
message is PKCS#7, so I guess there must be historical reasons for the

All up, I have nits but none of them rise to a level that should prevent
this code from being merged. As such:

Reviewed-by: Daniel Axtens <dja at axtens.net>

Kind regards,

More information about the Skiboot mailing list