summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Ching-Pang Lin <glin@suse.com>2012-09-11 16:39:12 +0800
committerGary Ching-Pang Lin <glin@suse.com>2012-09-11 16:39:12 +0800
commit28c581335edefd199abd7eb6be1721bc8640729a (patch)
tree3bdadc24359c50399e877ba893f0fb1c2fde9ffe
parent481c1e1e76f8158d262589dc571f95623a74e846 (diff)
downloadefi-boot-shim-28c581335edefd199abd7eb6be1721bc8640729a.tar.gz
efi-boot-shim-28c581335edefd199abd7eb6be1721bc8640729a.zip
Use the machine owner keys to verify images
-rw-r--r--shim.c98
1 files changed, 92 insertions, 6 deletions
diff --git a/shim.c b/shim.c
index 66709d7d..80c82ce7 100644
--- a/shim.c
+++ b/shim.c
@@ -60,6 +60,11 @@ typedef enum {
VAR_NOT_FOUND
} CHECK_STATUS;
+typedef struct {
+ UINT32 MokSize;
+ UINT8 *Mok;
+} MokListNode;
+
static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes,
UINTN *size, void **buffer)
{
@@ -97,6 +102,37 @@ static EFI_STATUS delete_variable (CHAR16 *name, EFI_GUID guid)
return efi_status;
}
+static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
+ MokListNode *list;
+ int i, remain = DataSize;
+ void *ptr;
+
+ list = AllocatePool(sizeof(MokListNode) * num);
+
+ if (!list) {
+ Print(L"Unable to allocate MOK list\n");
+ return NULL;
+ }
+
+ ptr = Data;
+ for (i = 0; i < num; i++) {
+ if (remain < 0) {
+ Print(L"MOK list was corrupted\n");
+ FreePool(list);
+ return NULL;
+ }
+
+ CopyMem(&list[i].MokSize, ptr, sizeof(UINT32));
+ ptr += sizeof(UINT32);
+ list[i].Mok = ptr;
+ ptr += list[i].MokSize;
+
+ remain -= sizeof(UINT32) + list[i].MokSize;
+ }
+
+ return list;
+}
+
/*
* Perform basic bounds checking of the intra-image pointers
*/
@@ -373,6 +409,7 @@ static BOOLEAN secure_mode (void)
static EFI_STATUS verify_buffer (char *data, int datasize,
PE_COFF_LOADER_IMAGE_CONTEXT *context, int whitelist)
{
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
unsigned int size = datasize;
unsigned int ctxsize;
void *ctx = NULL;
@@ -386,6 +423,11 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
EFI_IMAGE_SECTION_HEADER *Section;
EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL;
EFI_IMAGE_SECTION_HEADER *SectionCache;
+ unsigned int i;
+ void *MokListData = NULL;
+ UINTN MokListDataSize = 0;
+ UINT32 MokNum, attributes;
+ MokListNode *list = NULL;
cert = ImageAddress (data, size, context->SecDir->VirtualAddress);
@@ -547,15 +589,59 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
}
}
- if (!AuthenticodeVerify(cert->CertData,
- context->SecDir->Size - sizeof(cert->Hdr),
- vendor_cert, vendor_cert_size, hash,
- SHA256_DIGEST_SIZE)) {
+ if (AuthenticodeVerify(cert->CertData,
+ context->SecDir->Size - sizeof(cert->Hdr),
+ vendor_cert, vendor_cert_size, hash,
+ SHA256_DIGEST_SIZE)) {
+ status = EFI_SUCCESS;
+ Print(L"Binary is verified by the vendor certificate\n");
+ goto done;
+ }
+
+ status = get_variable(L"MokList", shim_lock_guid, &attributes,
+ &MokListDataSize, &MokListData);
+
+ if (status != EFI_SUCCESS) {
+ status = EFI_ACCESS_DENIED;
Print(L"Invalid signature\n");
+ goto done;
+ }
+
+ if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
+ Print(L"MokList is compromised!\nErase all keys in MokList!\n");
+ if (delete_variable(L"MokList", shim_lock_guid) != EFI_SUCCESS) {
+ Print(L"Failed to erase MokList\n");
+ }
status = EFI_ACCESS_DENIED;
- } else {
- status = EFI_SUCCESS;
+ goto done;
+ }
+
+ CopyMem(&MokNum, MokListData, sizeof(UINT32));
+ if (MokNum == 0)
+ goto done;
+
+ list = build_mok_list(MokNum,
+ (void *)MokListData + sizeof(UINT32),
+ MokListDataSize - sizeof(UINT32));
+
+ if (!list) {
+ Print(L"Failed to construct MOK list\n");
+ status = EFI_OUT_OF_RESOURCES;
+ goto done;
+ }
+
+ for (i = 0; i < MokNum; i++) {
+ if (AuthenticodeVerify(cert->CertData,
+ context->SecDir->Size - sizeof(cert->Hdr),
+ list[i].Mok, list[i].MokSize, hash,
+ SHA256_DIGEST_SIZE)) {
+ status = EFI_SUCCESS;
+ Print(L"Binary is verified by the machine owner key\n");
+ goto done;
+ }
}
+ Print(L"Invalid signature\n");
+ status = EFI_ACCESS_DENIED;
done:
if (SectionHeader)