mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-05-17 15:28:05 +00:00
Add image verification
This commit is contained in:
parent
9d56c38fd1
commit
7f0553356c
17
Makefile
17
Makefile
@ -3,11 +3,11 @@ ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
|||||||
LIB_PATH = /usr/lib64
|
LIB_PATH = /usr/lib64
|
||||||
|
|
||||||
EFI_INCLUDE = /usr/include/efi
|
EFI_INCLUDE = /usr/include/efi
|
||||||
EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol
|
EFI_INCLUDES = -nostdinc -I../Cryptlib -I../Cryptlib/Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol
|
||||||
EFI_PATH = /usr/lib64/gnuefi
|
EFI_PATH = /usr/lib64/gnuefi
|
||||||
|
|
||||||
LIB_GCC = $(shell $(CC) -print-libgcc-file-name)
|
LIB_GCC = $(shell $(CC) -print-libgcc-file-name)
|
||||||
EFI_LIBS = -lefi -lgnuefi $(LIB_GCC)
|
EFI_LIBS = -lefi -lgnuefi --start-group ../Cryptlib/libcryptlib.a ../Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC)
|
||||||
|
|
||||||
EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o
|
EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o
|
||||||
EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds
|
EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds
|
||||||
@ -19,22 +19,23 @@ CFLAGS = -O2 -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar \
|
|||||||
ifeq ($(ARCH),x86_64)
|
ifeq ($(ARCH),x86_64)
|
||||||
CFLAGS += -DEFI_FUNCTION_WRAPPER
|
CFLAGS += -DEFI_FUNCTION_WRAPPER
|
||||||
endif
|
endif
|
||||||
LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIB_PATH) $(EFI_CRT_OBJS)
|
LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIB_PATH) -L../Cryptlib -L../Cryptlib/OpenSSL $(EFI_CRT_OBJS)
|
||||||
|
|
||||||
TARGET = shim.efi
|
TARGET = shim.efi
|
||||||
OBJS = shim.o
|
OBJS = shim.o
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
shim.efi: $(OBJS)
|
shim.efi: shim.so
|
||||||
|
|
||||||
%.efi: %.o
|
shim.so: $(OBJS)
|
||||||
$(LD) $(LDFLAGS) $^ -o $@ $(EFI_LIBS)
|
$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS)
|
||||||
|
|
||||||
|
%.efi: %.so
|
||||||
objcopy -j .text -j .sdata -j .data \
|
objcopy -j .text -j .sdata -j .data \
|
||||||
-j .dynamic -j .dynsym -j .rel \
|
-j .dynamic -j .dynsym -j .rel \
|
||||||
-j .rela -j .reloc \
|
-j .rela -j .reloc \
|
||||||
--target=efi-app-$(ARCH) $@
|
--target=efi-app-$(ARCH) $^ $@
|
||||||
strip $@
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGET) $(OBJS)
|
rm -f $(TARGET) $(OBJS)
|
||||||
|
17
PeImage.h
17
PeImage.h
@ -760,6 +760,21 @@ typedef union {
|
|||||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
|
||||||
} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
|
} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
|
||||||
|
|
||||||
|
typedef struct _WIN_CERTIFICATE {
|
||||||
|
UINT32 dwLength;
|
||||||
|
UINT16 wRevision;
|
||||||
|
UINT16 wCertificateType;
|
||||||
|
//UINT8 bCertificate[ANYSIZE_ARRAY];
|
||||||
|
} WIN_CERTIFICATE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WIN_CERTIFICATE Hdr;
|
||||||
|
UINT8 CertData[1];
|
||||||
|
} WIN_CERTIFICATE_EFI_PKCS;
|
||||||
|
|
||||||
|
#define SHA256_DIGEST_SIZE 32
|
||||||
|
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT64 ImageAddress;
|
UINT64 ImageAddress;
|
||||||
UINT64 ImageSize;
|
UINT64 ImageSize;
|
||||||
@ -769,7 +784,9 @@ typedef struct {
|
|||||||
UINT16 NumberOfSections;
|
UINT16 NumberOfSections;
|
||||||
EFI_IMAGE_SECTION_HEADER *FirstSection;
|
EFI_IMAGE_SECTION_HEADER *FirstSection;
|
||||||
EFI_IMAGE_DATA_DIRECTORY *RelocDir;
|
EFI_IMAGE_DATA_DIRECTORY *RelocDir;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY *SecDir;
|
||||||
UINT64 NumberOfRvaAndSizes;
|
UINT64 NumberOfRvaAndSizes;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr;
|
||||||
} PE_COFF_LOADER_IMAGE_CONTEXT;
|
} PE_COFF_LOADER_IMAGE_CONTEXT;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
235
shim.c
235
shim.c
@ -1,17 +1,15 @@
|
|||||||
/* Read path */
|
|
||||||
/* Load real bootloader */
|
|
||||||
/* Check signature */
|
|
||||||
/* Relocate real bootloader */
|
|
||||||
/* Jump to real bootloader */
|
|
||||||
|
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
|
#include <Library/BaseCryptLib.h>
|
||||||
#include "PeImage.h"
|
#include "PeImage.h"
|
||||||
|
|
||||||
EFI_SYSTEM_TABLE *systab;
|
static EFI_SYSTEM_TABLE *systab;
|
||||||
EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
|
static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
|
||||||
|
|
||||||
EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
#include "cert.h"
|
||||||
|
|
||||||
|
static EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata,
|
||||||
|
int *grubsize)
|
||||||
{
|
{
|
||||||
EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
|
EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
|
||||||
EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
|
EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
|
||||||
@ -25,7 +23,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
|||||||
CHAR16 *PathName;
|
CHAR16 *PathName;
|
||||||
CHAR16 *Dir;
|
CHAR16 *Dir;
|
||||||
EFI_HANDLE device;
|
EFI_HANDLE device;
|
||||||
unsigned int buffersize = 0;
|
unsigned int buffersize = sizeof(EFI_FILE_INFO);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
|
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
|
||||||
@ -38,7 +36,6 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
|||||||
DevicePathSubType(li->FilePath) != MEDIA_FILEPATH_DP)
|
DevicePathSubType(li->FilePath) != MEDIA_FILEPATH_DP)
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
|
||||||
device = li->DeviceHandle;
|
device = li->DeviceHandle;
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
|
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
|
||||||
@ -63,10 +60,18 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
|||||||
0);
|
0);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
if (efi_status != EFI_SUCCESS) {
|
||||||
Print(L"Failed to open %s - %lx\n", FilePath->PathName, efi_status);
|
Print(L"Failed to open %s - %lx\n", FilePath->PathName,
|
||||||
|
efi_status);
|
||||||
return efi_status;
|
return efi_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileinfo = AllocatePool(buffersize);
|
||||||
|
|
||||||
|
if (!fileinfo) {
|
||||||
|
Print(L"Unable to allocate info buffer\n");
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, &file_info_id,
|
efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, &file_info_id,
|
||||||
&buffersize, fileinfo);
|
&buffersize, fileinfo);
|
||||||
|
|
||||||
@ -113,7 +118,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
|||||||
|
|
||||||
StrCpy(PathName, Dir);
|
StrCpy(PathName, Dir);
|
||||||
|
|
||||||
StrCat(PathName, L"\\grub.efi");
|
StrCat(PathName, L"grub.efi");
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(root->Open, 5, root, &grub, PathName,
|
efi_status = uefi_call_wrapper(root->Open, 5, root, &grub, PathName,
|
||||||
EFI_FILE_MODE_READ, 0);
|
EFI_FILE_MODE_READ, 0);
|
||||||
@ -154,7 +159,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
|||||||
*grubdata);
|
*grubdata);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
if (efi_status != EFI_SUCCESS) {
|
||||||
Print(L"Unexpected return from initial read\n");
|
Print(L"Unexpected return from initial read: %x, buffersize %x\n", efi_status, buffersize);
|
||||||
return efi_status;
|
return efi_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +173,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS read_header(void *grubdata, PE_COFF_LOADER_IMAGE_CONTEXT *context)
|
static EFI_STATUS read_header(void *grubdata, PE_COFF_LOADER_IMAGE_CONTEXT *context)
|
||||||
{
|
{
|
||||||
EFI_IMAGE_DOS_HEADER *DosHdr = grubdata;
|
EFI_IMAGE_DOS_HEADER *DosHdr = grubdata;
|
||||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = grubdata;
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = grubdata;
|
||||||
@ -191,8 +196,8 @@ EFI_STATUS read_header(void *grubdata, PE_COFF_LOADER_IMAGE_CONTEXT *context)
|
|||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context->PEHdr = PEHdr;
|
||||||
context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
|
context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
|
||||||
PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)grubdata;
|
|
||||||
context->ImageSize = (UINT64)PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
|
context->ImageSize = (UINT64)PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
|
||||||
context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
|
context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
|
||||||
context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint;
|
context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint;
|
||||||
@ -200,19 +205,196 @@ EFI_STATUS read_header(void *grubdata, PE_COFF_LOADER_IMAGE_CONTEXT *context)
|
|||||||
context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
|
context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
|
||||||
context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
|
context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
|
||||||
context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
|
context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
|
||||||
|
context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||||
|
|
||||||
|
if (context->SecDir->VirtualAddress >= context->ImageSize) {
|
||||||
|
Print(L"Malformed security header\n");
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->SecDir->Size == 0) {
|
||||||
|
Print(L"Empty security header\n");
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ImageAddress (void *image, int size, unsigned int address)
|
static void *ImageAddress (void *image, int size, unsigned int address)
|
||||||
{
|
{
|
||||||
if (address > size)
|
if (address > size)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
return image + address;
|
return image + address;
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS relocate_grub (PE_COFF_LOADER_IMAGE_CONTEXT *context, void *grubdata)
|
static EFI_STATUS verify_grub (PE_COFF_LOADER_IMAGE_CONTEXT *context, char *grubdata, int grubsize)
|
||||||
|
{
|
||||||
|
unsigned int size = grubsize;
|
||||||
|
unsigned int ctxsize;
|
||||||
|
void *ctx;
|
||||||
|
UINT8 hash[SHA256_DIGEST_SIZE];
|
||||||
|
EFI_STATUS status = EFI_ACCESS_DENIED;
|
||||||
|
char *hashbase;
|
||||||
|
unsigned int hashsize;
|
||||||
|
WIN_CERTIFICATE_EFI_PKCS *cer;
|
||||||
|
unsigned int SumOfBytesHashed, SumOfSectionBytes;
|
||||||
|
unsigned int index, pos;
|
||||||
|
EFI_IMAGE_SECTION_HEADER *Section;
|
||||||
|
EFI_IMAGE_SECTION_HEADER *SectionHeader;
|
||||||
|
EFI_IMAGE_SECTION_HEADER *SectionCache;
|
||||||
|
|
||||||
|
cert = ImageAddress (grubdata, size, context->SecDir->VirtualAddress);
|
||||||
|
|
||||||
|
if (cer->Hdr.wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
|
||||||
|
Print(L"Unsupported certificate type %x\n",
|
||||||
|
cert->Hdr.wCertificateType);
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check which kind of hash */
|
||||||
|
|
||||||
|
ctxsize = Sha256GetContextSize();
|
||||||
|
ctx = AllocatePool(ctxsize);
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
Print(L"Unable to allocate memory for hash context\n");
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Sha256Init(ctx)) {
|
||||||
|
Print(L"Unable to initialise hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash start to checksum */
|
||||||
|
hashbase = grubdata;
|
||||||
|
hashsize = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum -
|
||||||
|
hashbase;
|
||||||
|
|
||||||
|
if (!(Sha256Update(ctx, hashbase, hashsize))) {
|
||||||
|
Print(L"Unable to generate hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash post-checksum to start of certificate table */
|
||||||
|
hashbase = (char *)&context->PEHdr->Pe32.OptionalHeader.CheckSum +
|
||||||
|
sizeof (int);
|
||||||
|
hashsize = (char *)context->SecDir - hashbase;
|
||||||
|
|
||||||
|
if (!(Sha256Update(ctx, hashbase, hashsize))) {
|
||||||
|
Print(L"Unable to generate hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash end of certificate table to end of image header */
|
||||||
|
hashbase = (char *) &context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
|
||||||
|
hashsize = context->PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders -
|
||||||
|
(int) ((char *) (&context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - grubdata);
|
||||||
|
if (!(Sha256Update(ctx, hashbase, hashsize))) {
|
||||||
|
Print(L"Unable to generate hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort sections and hash SizeOfRawData of each section */
|
||||||
|
SumOfBytesHashed = context->PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
|
||||||
|
|
||||||
|
Section = (EFI_IMAGE_SECTION_HEADER *) (
|
||||||
|
(char *)context->PEHdr + sizeof (UINT32) +
|
||||||
|
sizeof (EFI_IMAGE_FILE_HEADER) +
|
||||||
|
context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
SectionCache = Section;
|
||||||
|
|
||||||
|
for (index = 0, SumOfSectionBytes = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++, SectionCache++) {
|
||||||
|
SumOfSectionBytes += SectionCache->SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SumOfSectionBytes >= grubsize) {
|
||||||
|
Print(L"Malformed binary: %x %x\n", SumOfSectionBytes, size);
|
||||||
|
status = EFI_INVALID_PARAMETER;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections);
|
||||||
|
if (SectionHeader == NULL) {
|
||||||
|
Print(L"Unable to allocate section header\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort the section headers */
|
||||||
|
for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
|
||||||
|
pos = index;
|
||||||
|
while ((pos > 0) && (Section->PointerToRawData < SectionHeader[pos - 1].PointerToRawData)) {
|
||||||
|
CopyMem (&SectionHeader[pos], &SectionHeader[pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
CopyMem (&SectionHeader[pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
|
||||||
|
Section += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash the sections */
|
||||||
|
for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
|
||||||
|
Section = &SectionHeader[index];
|
||||||
|
if (Section->SizeOfRawData == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hashbase = ImageAddress(grubdata, size, Section->PointerToRawData);
|
||||||
|
hashsize = (unsigned int) Section->SizeOfRawData;
|
||||||
|
|
||||||
|
if (!(Sha256Update(ctx, hashbase, hashsize))) {
|
||||||
|
Print(L"Unable to generate hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
SumOfBytesHashed += Section->SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash all remaining data */
|
||||||
|
if (size > SumOfBytesHashed) {
|
||||||
|
hashbase = grubdata + SumOfBytesHashed;
|
||||||
|
hashsize = (unsigned int)(
|
||||||
|
size -
|
||||||
|
context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
|
||||||
|
SumOfBytesHashed);
|
||||||
|
|
||||||
|
if (!(Sha256Update(ctx, hashbase, hashsize))) {
|
||||||
|
Print(L"Unable to generate hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Sha256Final(ctx, hash))) {
|
||||||
|
Print(L"Unable to finalise hash\n");
|
||||||
|
status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AuthenticodeVerify(WinCertificate->CertData,
|
||||||
|
context->SecDir->Size - sizeof(WinCertificate->Hdr),
|
||||||
|
cert, sizeof(cert), hash,
|
||||||
|
SHA256_DIGEST_SIZE)) {
|
||||||
|
Print(L"Invalid signature\n");
|
||||||
|
status = EFI_ACCESS_DENIED;
|
||||||
|
} else {
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (ctx)
|
||||||
|
FreePool(ctx);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS relocate_grub (PE_COFF_LOADER_IMAGE_CONTEXT *context, void *grubdata)
|
||||||
{
|
{
|
||||||
EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
|
EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
|
||||||
UINT64 Adjust;
|
UINT64 Adjust;
|
||||||
@ -224,6 +406,8 @@ EFI_STATUS relocate_grub (PE_COFF_LOADER_IMAGE_CONTEXT *context, void *grubdata)
|
|||||||
int size = context->ImageSize;
|
int size = context->ImageSize;
|
||||||
void *ImageEnd = (char *)grubdata + size;
|
void *ImageEnd = (char *)grubdata + size;
|
||||||
|
|
||||||
|
context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)grubdata;
|
||||||
|
|
||||||
if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
|
if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
|
||||||
Print(L"Image has no relocation entry\n");
|
Print(L"Image has no relocation entry\n");
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
@ -311,7 +495,7 @@ EFI_STATUS relocate_grub (PE_COFF_LOADER_IMAGE_CONTEXT *context, void *grubdata)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS handle_grub (void *grubdata, int grubsize)
|
static EFI_STATUS handle_grub (void *grubdata, int grubsize)
|
||||||
{
|
{
|
||||||
EFI_STATUS efi_status;
|
EFI_STATUS efi_status;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
@ -326,6 +510,13 @@ EFI_STATUS handle_grub (void *grubdata, int grubsize)
|
|||||||
return efi_status;
|
return efi_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
efi_status = verify_grub(&context, grubdata, grubsize);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Verification failed\n");
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
buffer = AllocatePool(context.ImageSize);
|
buffer = AllocatePool(context.ImageSize);
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
@ -387,8 +578,10 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
|||||||
|
|
||||||
efi_status = load_grub(image_handle, &grubdata, &grubsize);
|
efi_status = load_grub(image_handle, &grubdata, &grubsize);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS)
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to load grub\n");
|
||||||
return efi_status;
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
efi_status = handle_grub(grubdata, grubsize);
|
efi_status = handle_grub(grubdata, grubsize);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user