blob: 530d09779eb46f5963c39d7db5c687b763c76402 [file]
#include <efi.h>
#include <efilib.h>
#include <guid.h>
#include <pecoff.h>
#include <sha256.h>
#include <efiauthenticated.h>
#include <pkcs7verify.h>
#include <variables.h>
#include <shim_protocol.h>
#include <console.h>
static EFI_PKCS7_VERIFY_PROTOCOL *p7vp;
/*
* The Plcs7Verify protocol doesn't take raw signature lists and lengths,
* it takes a null terminated list of pointers to signature lists, so
* make the conversion
*/
static EFI_SIGNATURE_LIST **to_cert_list(VOID *data, UINTN len)
{
EFI_SIGNATURE_LIST *CertList, **retval;
int size, count=0;
if (!data)
return data;
certlist_for_each_certentry(CertList, data, size, len)
count++;
retval = AllocatePool((count + 1) * sizeof(void *));
if (!retval)
return NULL;
count = 0;
certlist_for_each_certentry(CertList, data, size, len)
retval[count++] = CertList;
retval[count] = NULL;
return retval;
}
static EFI_STATUS shimprotocol_context(void *data, unsigned int size,
PE_COFF_LOADER_IMAGE_CONTEXT *context)
{
return pecoff_read_header(context, data);
}
static EFI_STATUS shimprotocol_verify(void *buffer, UINT32 size)
{
EFI_STATUS status;
PE_COFF_LOADER_IMAGE_CONTEXT context;
UINT8 hash[SHA256_DIGEST_SIZE];
VOID *db = NULL, *dbx = NULL;
EFI_SIGNATURE_LIST **dblist, **dbxlist;
UINTN db_len, dbx_len;
int i;
if (!variable_is_secureboot() || variable_is_setupmode())
return EFI_SUCCESS;
status = pecoff_read_header(&context, buffer);
if (status != EFI_SUCCESS)
goto out;
status = sha256_get_pecoff_digest_mem(buffer, size, hash);
if (status != EFI_SUCCESS)
goto out;
get_variable(L"db", (UINT8 **)&db, &db_len, SIG_DB);
get_variable(L"dbx", (UINT8 **)&dbx, &dbx_len, SIG_DB);
dblist = to_cert_list(db, db_len);
dbxlist = to_cert_list(dbx, dbx_len);
for (i = 0; ; i++) {
WIN_CERTIFICATE *cert;
status = pecoff_get_signature(&context, buffer, &cert, i);
if (status != EFI_SUCCESS)
break;
status = p7vp->VerifySignature(p7vp, (VOID *)(cert + 1),
cert->dwLength - sizeof(*cert),
hash, sizeof(hash),
dblist, dbxlist, NULL);
if (status == EFI_SUCCESS)
goto out;
}
status = EFI_ACCESS_DENIED;
out:
if (db)
FreePool(db);
if (dbx)
FreePool(dbx);
if (dblist)
FreePool(dblist);
if (dbxlist)
FreePool(dbxlist);
return status;
}
static SHIM_LOCK shim_protocol_interface = {
.Verify = shimprotocol_verify,
.Context = shimprotocol_context,
};
static EFI_HANDLE shim_protocol_handle;
EFI_STATUS
shim_protocol_install(EFI_PKCS7_VERIFY_PROTOCOL *p)
{
p7vp = p;
return BS->InstallProtocolInterface(&shim_protocol_handle, &MOK_OWNER, EFI_NATIVE_INTERFACE, &shim_protocol_interface);
}
void
shim_protocol_uninstall(void)
{
BS->UninstallProtocolInterface(shim_protocol_handle, &MOK_OWNER, &shim_protocol_interface);
}