mirror of
				https://git.proxmox.com/git/efi-boot-shim
				synced 2025-11-04 07:52:55 +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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
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_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)
 | 
			
		||||
	CFLAGS	+= -DEFI_FUNCTION_WRAPPER
 | 
			
		||||
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
 | 
			
		||||
OBJS		= shim.o
 | 
			
		||||
 | 
			
		||||
all: $(TARGET)
 | 
			
		||||
 | 
			
		||||
shim.efi: $(OBJS)
 | 
			
		||||
shim.efi: shim.so
 | 
			
		||||
 | 
			
		||||
%.efi: %.o 
 | 
			
		||||
	$(LD) $(LDFLAGS) $^ -o $@ $(EFI_LIBS)
 | 
			
		||||
shim.so: $(OBJS)
 | 
			
		||||
	$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS)
 | 
			
		||||
 | 
			
		||||
%.efi: %.so 
 | 
			
		||||
	objcopy -j .text -j .sdata -j .data \
 | 
			
		||||
		-j .dynamic -j .dynsym  -j .rel \
 | 
			
		||||
		-j .rela -j .reloc \
 | 
			
		||||
		--target=efi-app-$(ARCH) $@
 | 
			
		||||
	strip $@
 | 
			
		||||
		--target=efi-app-$(ARCH) $^ $@
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	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_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 {
 | 
			
		||||
	UINT64 ImageAddress;
 | 
			
		||||
	UINT64 ImageSize;
 | 
			
		||||
@ -769,7 +784,9 @@ typedef struct {
 | 
			
		||||
	UINT16 NumberOfSections;
 | 
			
		||||
	EFI_IMAGE_SECTION_HEADER *FirstSection;
 | 
			
		||||
	EFI_IMAGE_DATA_DIRECTORY *RelocDir;
 | 
			
		||||
	EFI_IMAGE_DATA_DIRECTORY *SecDir;
 | 
			
		||||
	UINT64 NumberOfRvaAndSizes;
 | 
			
		||||
	EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr;
 | 
			
		||||
} PE_COFF_LOADER_IMAGE_CONTEXT;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										237
									
								
								shim.c
									
									
									
									
									
								
							
							
						
						
									
										237
									
								
								shim.c
									
									
									
									
									
								
							@ -1,17 +1,15 @@
 | 
			
		||||
/* Read path */
 | 
			
		||||
/* Load real bootloader */
 | 
			
		||||
/* Check signature */
 | 
			
		||||
/* Relocate real bootloader */
 | 
			
		||||
/* Jump to real bootloader */
 | 
			
		||||
 | 
			
		||||
#include <efi.h>
 | 
			
		||||
#include <efilib.h>
 | 
			
		||||
#include <Library/BaseCryptLib.h>
 | 
			
		||||
#include "PeImage.h"
 | 
			
		||||
 | 
			
		||||
EFI_SYSTEM_TABLE *systab;
 | 
			
		||||
EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
 | 
			
		||||
static EFI_SYSTEM_TABLE *systab;
 | 
			
		||||
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 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 *Dir;
 | 
			
		||||
	EFI_HANDLE device;
 | 
			
		||||
	unsigned int buffersize = 0;
 | 
			
		||||
	unsigned int buffersize = sizeof(EFI_FILE_INFO);
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
		return EFI_NOT_FOUND;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	device = li->DeviceHandle;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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,
 | 
			
		||||
				       &buffersize, fileinfo);
 | 
			
		||||
 | 
			
		||||
@ -113,7 +118,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
 | 
			
		||||
 | 
			
		||||
	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_FILE_MODE_READ, 0);
 | 
			
		||||
@ -154,7 +159,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
 | 
			
		||||
				       *grubdata);
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -168,7 +173,7 @@ EFI_STATUS load_grub (EFI_HANDLE image_handle, void **grubdata, int *grubsize)
 | 
			
		||||
	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_OPTIONAL_HEADER_UNION *PEHdr = grubdata;
 | 
			
		||||
@ -191,8 +196,8 @@ EFI_STATUS read_header(void *grubdata, PE_COFF_LOADER_IMAGE_CONTEXT *context)
 | 
			
		||||
		return EFI_UNSUPPORTED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	context->PEHdr = PEHdr;
 | 
			
		||||
	context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
 | 
			
		||||
	PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)grubdata;
 | 
			
		||||
	context->ImageSize = (UINT64)PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
 | 
			
		||||
	context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
 | 
			
		||||
	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->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->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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *ImageAddress (void *image, int size, unsigned int address)
 | 
			
		||||
static void *ImageAddress (void *image, int size, unsigned int address)
 | 
			
		||||
{
 | 
			
		||||
	if (address > size)
 | 
			
		||||
		return 0;
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	UINT64 Adjust;
 | 
			
		||||
@ -224,6 +406,8 @@ EFI_STATUS relocate_grub (PE_COFF_LOADER_IMAGE_CONTEXT *context, void *grubdata)
 | 
			
		||||
	int size = context->ImageSize;
 | 
			
		||||
	void *ImageEnd = (char *)grubdata + size;
 | 
			
		||||
 | 
			
		||||
	context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)grubdata;
 | 
			
		||||
 | 
			
		||||
	if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
 | 
			
		||||
		Print(L"Image has no relocation entry\n");
 | 
			
		||||
		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;
 | 
			
		||||
	char *buffer;
 | 
			
		||||
@ -319,13 +503,20 @@ EFI_STATUS handle_grub (void *grubdata, int grubsize)
 | 
			
		||||
	EFI_IMAGE_SECTION_HEADER *Section;
 | 
			
		||||
	char *base, *end;
 | 
			
		||||
	PE_COFF_LOADER_IMAGE_CONTEXT context;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	efi_status = read_header(grubdata, &context);
 | 
			
		||||
	if (efi_status != EFI_SUCCESS) {
 | 
			
		||||
		Print(L"Failed to read header\n");
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	if (efi_status != EFI_SUCCESS)
 | 
			
		||||
	if (efi_status != EFI_SUCCESS) {
 | 
			
		||||
		Print(L"Failed to load grub\n");
 | 
			
		||||
		return efi_status;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	efi_status = handle_grub(grubdata, grubsize);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user