summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/variables.h16
-rw-r--r--lib/variables.c81
-rw-r--r--mok.c56
3 files changed, 106 insertions, 47 deletions
diff --git a/include/variables.h b/include/variables.h
index 31cfcb65..493f433f 100644
--- a/include/variables.h
+++ b/include/variables.h
@@ -64,12 +64,20 @@ EFI_STATUS
variable_enroll_hash(const CHAR16 * const var, EFI_GUID owner,
UINT8 hash[SHA256_DIGEST_SIZE]);
EFI_STATUS
-variable_create_esl(const uint8_t *cert, const size_t cert_len,
- const EFI_GUID *type, const EFI_GUID *owner,
+variable_create_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany,
+ const EFI_GUID *type, const UINT32 sig_size,
uint8_t **out, size_t *outlen);
EFI_STATUS
-fill_esl(const uint8_t *data, const size_t data_len,
- const EFI_GUID *type, const EFI_GUID *owner,
+variable_create_esl_with_one_signature(const uint8_t* data, const size_t data_len,
+ const EFI_GUID *type, const EFI_GUID *owner,
+ uint8_t **out, size_t *outlen);
+EFI_STATUS
+fill_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany,
+ const EFI_GUID *type, const UINT32 sig_size,
uint8_t *out, size_t *outlen);
+EFI_STATUS
+fill_esl_with_one_signature(const uint8_t *data, const uint32_t data_len,
+ const EFI_GUID *type, const EFI_GUID *owner,
+ uint8_t *out, size_t *outlen);
#endif /* SHIM_VARIABLES_H */
diff --git a/lib/variables.c b/lib/variables.c
index 9f5b2b57..53a5d14a 100644
--- a/lib/variables.c
+++ b/lib/variables.c
@@ -13,18 +13,24 @@
#include "shim.h"
EFI_STATUS
-fill_esl(const uint8_t *data, const size_t data_len,
- const EFI_GUID *type, const EFI_GUID *owner,
+fill_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany,
+ const EFI_GUID *type, const UINT32 sig_size,
uint8_t *out, size_t *outlen)
{
EFI_SIGNATURE_LIST *sl;
EFI_SIGNATURE_DATA *sd;
size_t needed = 0;
+ size_t data_len = howmany * sig_size;
- if (!data || !data_len || !type || !outlen)
+ dprint(L"fill_esl: data=%p, data_len=%lu", first_sig, data_len);
+
+ if ((out && !first_sig) || !howmany || !type || !sig_size || !outlen)
+ return EFI_INVALID_PARAMETER;
+
+ if (howmany > (UINT32_MAX - sizeof(EFI_SIGNATURE_LIST)) / sig_size)
return EFI_INVALID_PARAMETER;
- needed = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) + data_len;
+ needed = sizeof(EFI_SIGNATURE_LIST) + data_len;
if (!out || *outlen < needed) {
*outlen = needed;
return EFI_BUFFER_TOO_SMALL;
@@ -35,27 +41,70 @@ fill_esl(const uint8_t *data, const size_t data_len,
sl->SignatureHeaderSize = 0;
sl->SignatureType = *type;
- sl->SignatureSize = sizeof(EFI_GUID) + data_len;
+ sl->SignatureSize = sig_size;
sl->SignatureListSize = needed;
sd = (EFI_SIGNATURE_DATA *)(out + sizeof(EFI_SIGNATURE_LIST));
- if (owner)
- sd->SignatureOwner = *owner;
-
- CopyMem(sd->SignatureData, data, data_len);
+ CopyMem(sd, first_sig, data_len);
return EFI_SUCCESS;
}
EFI_STATUS
-variable_create_esl(const uint8_t *data, const size_t data_len,
- const EFI_GUID *type, const EFI_GUID *owner,
+fill_esl_with_one_signature(const uint8_t *data, const uint32_t data_len,
+ const EFI_GUID *type, const EFI_GUID *owner,
+ uint8_t *out, size_t *outlen)
+{
+ EFI_STATUS efi_status;
+ EFI_SIGNATURE_DATA *sd = NULL;
+ UINT32 sig_size = sizeof(EFI_SIGNATURE_DATA) - 1 + data_len;
+
+ if (data_len > UINT32_MAX - sizeof(EFI_SIGNATURE_DATA) + 1)
+ return EFI_INVALID_PARAMETER;
+
+ if (out) {
+ sd = AllocateZeroPool(sig_size);
+ if (owner)
+ CopyMem(sd, owner, sizeof(EFI_GUID));
+ CopyMem(sd->SignatureData, data, data_len);
+ }
+
+ efi_status = fill_esl(sd, 1, type, sig_size, out, outlen);
+
+ if (out)
+ FreePool(sd);
+ return efi_status;
+}
+
+EFI_STATUS
+variable_create_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany,
+ const EFI_GUID *type, const UINT32 sig_size,
uint8_t **out, size_t *outlen)
{
EFI_STATUS efi_status;
*outlen = 0;
- efi_status = fill_esl(data, data_len, type, owner, NULL, outlen);
+ efi_status = fill_esl(first_sig, howmany, type, sig_size, NULL, outlen);
+ if (efi_status != EFI_BUFFER_TOO_SMALL)
+ return efi_status;
+
+ *out = AllocateZeroPool(*outlen);
+ if (!*out)
+ return EFI_OUT_OF_RESOURCES;
+
+ return fill_esl(first_sig, howmany, type, sig_size, *out, outlen);
+}
+
+EFI_STATUS
+variable_create_esl_with_one_signature(const uint8_t* data, const size_t data_len,
+ const EFI_GUID *type, const EFI_GUID *owner,
+ uint8_t **out, size_t *outlen)
+{
+ EFI_STATUS efi_status;
+
+ *outlen = 0;
+ efi_status = fill_esl_with_one_signature(data, data_len, type, owner,
+ NULL, outlen);
if (efi_status != EFI_BUFFER_TOO_SMALL)
return efi_status;
@@ -63,7 +112,8 @@ variable_create_esl(const uint8_t *data, const size_t data_len,
if (!*out)
return EFI_OUT_OF_RESOURCES;
- return fill_esl(data, data_len, type, owner, *out, outlen);
+ return fill_esl_with_one_signature(data, data_len, type, owner, *out,
+ outlen);
}
EFI_STATUS
@@ -153,8 +203,9 @@ SetSecureVariable(const CHAR16 * const var, UINT8 *Data, UINTN len,
if (createtimebased) {
size_t ds;
- efi_status = variable_create_esl(Data, len, &X509_GUID, NULL,
- (uint8_t **)&Cert, &ds);
+ efi_status = variable_create_esl_with_one_signature(
+ Data, len, &X509_GUID, NULL,
+ (uint8_t **)&Cert, &ds);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to create %s certificate %d\n",
var, efi_status);
diff --git a/mok.c b/mok.c
index e3c3d9ee..3d2b398c 100644
--- a/mok.c
+++ b/mok.c
@@ -303,8 +303,8 @@ mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
UINTN *newsz, SIZE_T maxsz)
{
EFI_STATUS efi_status;
- SIZE_T howmany, varsz = 0, esdsz;
- UINT8 *var, *data;
+ SIZE_T howmany, varsz = 0;
+ UINT8 *var;
howmany = MIN((maxsz - sizeof(*esl)) / esl->SignatureSize,
(esl->SignatureListSize - sizeof(*esl)) / esl->SignatureSize);
@@ -316,8 +316,6 @@ mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
* We always assume esl->SignatureHeaderSize is 0 (and so far,
* that's true as per UEFI 2.8)
*/
- esdsz = howmany * esl->SignatureSize;
- data = (UINT8 *)esd;
dprint(L"Trying to add %lx signatures to \"%s\" of size %lx\n",
howmany, name, esl->SignatureSize);
@@ -327,10 +325,9 @@ mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
*
* Compensate here.
*/
- efi_status = variable_create_esl(data + sizeof(EFI_GUID),
- esdsz - sizeof(EFI_GUID),
+ efi_status = variable_create_esl(esd, howmany,
&esl->SignatureType,
- &esd->SignatureOwner,
+ esl->SignatureSize,
&var, &varsz);
if (EFI_ERROR(efi_status) || !var || !varsz) {
LogError(L"Couldn't allocate %lu bytes for mok variable \"%s\": %r\n",
@@ -349,7 +346,7 @@ mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
return efi_status;
}
- *newsz = esdsz;
+ *newsz = howmany * esl->SignatureSize;
return efi_status;
}
@@ -507,7 +504,7 @@ mirror_mok_db(CHAR16 *name, CHAR8 *name8, EFI_GUID *guid, UINT32 attrs,
UINT8 *var;
UINTN varsz;
- efi_status = variable_create_esl(
+ efi_status = variable_create_esl_with_one_signature(
null_sha256, sizeof(null_sha256),
&EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
&var, &varsz);
@@ -592,10 +589,12 @@ mirror_one_mok_variable(struct mok_state_variable *v,
FullDataSize, FullData);
break;
case VENDOR_ADDEND_X509:
- efi_status = fill_esl(*v->addend, *v->addend_size,
- &EFI_CERT_TYPE_X509_GUID,
- &SHIM_LOCK_GUID,
- NULL, &addend_esl_sz);
+ efi_status = fill_esl_with_one_signature(*v->addend,
+ *v->addend_size,
+ &EFI_CERT_TYPE_X509_GUID,
+ &SHIM_LOCK_GUID,
+ NULL,
+ &addend_esl_sz);
if (efi_status != EFI_BUFFER_TOO_SMALL) {
perror(L"Could not add built-in cert to %s: %r\n",
v->name, efi_status);
@@ -616,11 +615,11 @@ mirror_one_mok_variable(struct mok_state_variable *v,
* then the build cert if it's there
*/
if (should_mirror_build_cert(v)) {
- efi_status = fill_esl(*v->build_cert,
- *v->build_cert_size,
- &EFI_CERT_TYPE_X509_GUID,
- &SHIM_LOCK_GUID,
- NULL, &build_cert_esl_sz);
+ efi_status = fill_esl_with_one_signature(*v->build_cert,
+ *v->build_cert_size,
+ &EFI_CERT_TYPE_X509_GUID,
+ &SHIM_LOCK_GUID,
+ NULL, &build_cert_esl_sz);
if (efi_status != EFI_BUFFER_TOO_SMALL) {
perror(L"Could not add built-in cert to %s: %r\n",
v->name, efi_status);
@@ -703,10 +702,11 @@ mirror_one_mok_variable(struct mok_state_variable *v,
FullDataSize, FullData, p, p-(uintptr_t)FullData);
break;
case VENDOR_ADDEND_X509:
- efi_status = fill_esl(*v->addend, *v->addend_size,
- &EFI_CERT_TYPE_X509_GUID,
- &SHIM_LOCK_GUID,
- p, &addend_esl_sz);
+ efi_status = fill_esl_with_one_signature(*v->addend,
+ *v->addend_size,
+ &EFI_CERT_TYPE_X509_GUID,
+ &SHIM_LOCK_GUID,
+ p, &addend_esl_sz);
if (EFI_ERROR(efi_status)) {
perror(L"Could not add built-in cert to %s: %r\n",
v->name, efi_status);
@@ -729,11 +729,11 @@ mirror_one_mok_variable(struct mok_state_variable *v,
dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
FullDataSize, FullData, p, p-(uintptr_t)FullData);
if (should_mirror_build_cert(v)) {
- efi_status = fill_esl(*v->build_cert,
- *v->build_cert_size,
- &EFI_CERT_TYPE_X509_GUID,
- &SHIM_LOCK_GUID,
- p, &build_cert_esl_sz);
+ efi_status = fill_esl_with_one_signature(*v->build_cert,
+ *v->build_cert_size,
+ &EFI_CERT_TYPE_X509_GUID,
+ &SHIM_LOCK_GUID,
+ p, &build_cert_esl_sz);
if (EFI_ERROR(efi_status)) {
perror(L"Could not add built-in cert to %s: %r\n",
v->name, efi_status);
@@ -765,7 +765,7 @@ mirror_one_mok_variable(struct mok_state_variable *v,
* need a dummy entry
*/
if ((v->flags & MOK_MIRROR_KEYDB) && FullDataSize == 0) {
- efi_status = variable_create_esl(
+ efi_status = variable_create_esl_with_one_signature(
null_sha256, sizeof(null_sha256),
&EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
&FullData, &FullDataSize);