mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-25 06:00:43 +00:00
efi_loader: variable: keep temporary buffer during the authentication
This is a bug fix; Setting an authenticated variable may fail due to a memory corruption in the authentication. A temporary buffer will, if needed, be allocated to parse a variable's authentication data, and some portion of buffer, specifically signer's certificates, will be referenced by efi_signature_verify(). So the buffer should be kept valid until the authentication process is finished. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
bc78d22d0f
commit
0658bb29b0
1 changed files with 20 additions and 7 deletions
|
@ -37,16 +37,21 @@ static u8 pkcs7_hdr[] = {
|
||||||
* efi_variable_parse_signature - parse a signature in variable
|
* efi_variable_parse_signature - parse a signature in variable
|
||||||
* @buf: Pointer to variable's value
|
* @buf: Pointer to variable's value
|
||||||
* @buflen: Length of @buf
|
* @buflen: Length of @buf
|
||||||
|
* @tmpbuf: Pointer to temporary buffer
|
||||||
*
|
*
|
||||||
* Parse a signature embedded in variable's value and instantiate
|
* Parse a signature embedded in variable's value and instantiate
|
||||||
* a pkcs7_message structure. Since pkcs7_parse_message() accepts only
|
* a pkcs7_message structure. Since pkcs7_parse_message() accepts only
|
||||||
* pkcs7's signedData, some header needed be prepended for correctly
|
* pkcs7's signedData, some header needed be prepended for correctly
|
||||||
* parsing authentication data, particularly for variable's.
|
* parsing authentication data, particularly for variable's.
|
||||||
|
* A temporary buffer will be allocated if needed, and it should be
|
||||||
|
* kept valid during the authentication because some data in the buffer
|
||||||
|
* will be referenced by efi_signature_verify().
|
||||||
*
|
*
|
||||||
* Return: Pointer to pkcs7_message structure on success, NULL on error
|
* Return: Pointer to pkcs7_message structure on success, NULL on error
|
||||||
*/
|
*/
|
||||||
static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
|
static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
|
||||||
size_t buflen)
|
size_t buflen,
|
||||||
|
u8 **tmpbuf)
|
||||||
{
|
{
|
||||||
u8 *ebuf;
|
u8 *ebuf;
|
||||||
size_t ebuflen, len;
|
size_t ebuflen, len;
|
||||||
|
@ -59,7 +64,9 @@ static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
|
||||||
if (buflen > sizeof(pkcs7_hdr) &&
|
if (buflen > sizeof(pkcs7_hdr) &&
|
||||||
!memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
|
!memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
|
||||||
msg = pkcs7_parse_message(buf, buflen);
|
msg = pkcs7_parse_message(buf, buflen);
|
||||||
goto out;
|
if (IS_ERR(msg))
|
||||||
|
return NULL;
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -94,12 +101,12 @@ static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
|
||||||
|
|
||||||
msg = pkcs7_parse_message(ebuf, ebuflen);
|
msg = pkcs7_parse_message(ebuf, ebuflen);
|
||||||
|
|
||||||
free(ebuf);
|
if (IS_ERR(msg)) {
|
||||||
|
free(ebuf);
|
||||||
out:
|
|
||||||
if (IS_ERR(msg))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*tmpbuf = ebuf;
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +143,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
|
||||||
struct efi_time timestamp;
|
struct efi_time timestamp;
|
||||||
struct rtc_time tm;
|
struct rtc_time tm;
|
||||||
u64 new_time;
|
u64 new_time;
|
||||||
|
u8 *ebuf;
|
||||||
enum efi_auth_var_type var_type;
|
enum efi_auth_var_type var_type;
|
||||||
efi_status_t ret;
|
efi_status_t ret;
|
||||||
|
|
||||||
|
@ -143,6 +151,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
|
||||||
truststore = NULL;
|
truststore = NULL;
|
||||||
truststore2 = NULL;
|
truststore2 = NULL;
|
||||||
regs = NULL;
|
regs = NULL;
|
||||||
|
ebuf = NULL;
|
||||||
ret = EFI_SECURITY_VIOLATION;
|
ret = EFI_SECURITY_VIOLATION;
|
||||||
|
|
||||||
if (*data_size < sizeof(struct efi_variable_authentication_2))
|
if (*data_size < sizeof(struct efi_variable_authentication_2))
|
||||||
|
@ -204,9 +213,12 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
|
||||||
/* variable's signature list */
|
/* variable's signature list */
|
||||||
if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info))
|
if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* ebuf should be kept valid during the authentication */
|
||||||
var_sig = efi_variable_parse_signature(auth->auth_info.cert_data,
|
var_sig = efi_variable_parse_signature(auth->auth_info.cert_data,
|
||||||
auth->auth_info.hdr.dwLength
|
auth->auth_info.hdr.dwLength
|
||||||
- sizeof(auth->auth_info));
|
- sizeof(auth->auth_info),
|
||||||
|
&ebuf);
|
||||||
if (!var_sig) {
|
if (!var_sig) {
|
||||||
EFI_PRINT("Parsing variable's signature failed\n");
|
EFI_PRINT("Parsing variable's signature failed\n");
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -262,6 +274,7 @@ err:
|
||||||
efi_sigstore_free(truststore);
|
efi_sigstore_free(truststore);
|
||||||
efi_sigstore_free(truststore2);
|
efi_sigstore_free(truststore2);
|
||||||
pkcs7_free_message(var_sig);
|
pkcs7_free_message(var_sig);
|
||||||
|
free(ebuf);
|
||||||
free(regs);
|
free(regs);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue