diff options
Diffstat (limited to 'lib/variables.c')
-rw-r--r-- | lib/variables.c | 127 |
1 files changed, 109 insertions, 18 deletions
diff --git a/lib/variables.c b/lib/variables.c index 0431d4a2..f606e248 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -10,24 +10,27 @@ * Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR> * */ -#include <efi.h> -#include <efilib.h> - #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; + + dprint(L"fill_esl: first_sig=0x%llx, data_len=%lu\n", first_sig, data_len); + + if ((out && !first_sig) || !howmany || !type || !sig_size || !outlen) + return EFI_INVALID_PARAMETER; - if (!data || !data_len || !type || !outlen) + 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; @@ -38,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; @@ -66,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 @@ -156,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); @@ -227,6 +275,9 @@ get_variable_attr(const CHAR16 * const var, UINT8 **data, UINTN *len, { EFI_STATUS efi_status; + if (!len) + return EFI_INVALID_PARAMETER; + *len = 0; efi_status = gRT->GetVariable((CHAR16 *)var, &owner, NULL, len, NULL); @@ -236,6 +287,9 @@ get_variable_attr(const CHAR16 * const var, UINT8 **data, UINTN *len, return efi_status; } + if (!data) + return EFI_INVALID_PARAMETER; + /* * Add three zero pad bytes; at least one correctly aligned UCS-2 * character. @@ -260,6 +314,43 @@ get_variable(const CHAR16 * const var, UINT8 **data, UINTN *len, EFI_GUID owner) } EFI_STATUS +get_variable_size(const CHAR16 * const var, EFI_GUID owner, UINTN *lenp) +{ + UINTN len = 0; + EFI_STATUS efi_status; + + efi_status = get_variable_attr(var, NULL, &len, owner, NULL); + if (EFI_ERROR(efi_status)) { + if (efi_status == EFI_BUFFER_TOO_SMALL) { + *lenp = len; + return EFI_SUCCESS; + } else if (efi_status == EFI_NOT_FOUND) { + *lenp = 0; + return EFI_SUCCESS; + } + return efi_status; + } + /* + * who knows what this means, but... + */ + *lenp = len; + return efi_status; +} + +EFI_STATUS +set_variable(CHAR16 *var, EFI_GUID owner, UINT32 attributes, + UINTN datasize, void *data) +{ + return gRT->SetVariable(var, &owner, attributes, datasize, data); +} + +EFI_STATUS +del_variable(CHAR16 *var, EFI_GUID owner) +{ + return set_variable(var, owner, 0, 0, ""); +} + +EFI_STATUS find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen) { EFI_SIGNATURE_LIST *CertList; |