diff options
| author | Gary Ching-Pang Lin <glin@suse.com> | 2012-09-11 16:39:12 +0800 |
|---|---|---|
| committer | Gary Ching-Pang Lin <glin@suse.com> | 2012-09-11 16:39:12 +0800 |
| commit | 28c581335edefd199abd7eb6be1721bc8640729a (patch) | |
| tree | 3bdadc24359c50399e877ba893f0fb1c2fde9ffe | |
| parent | 481c1e1e76f8158d262589dc571f95623a74e846 (diff) | |
| download | efi-boot-shim-28c581335edefd199abd7eb6be1721bc8640729a.tar.gz efi-boot-shim-28c581335edefd199abd7eb6be1721bc8640729a.zip | |
Use the machine owner keys to verify images
| -rw-r--r-- | shim.c | 98 |
1 files changed, 92 insertions, 6 deletions
@@ -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) |
