aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2015-01-22 11:08:07 -0800
committerJames Bottomley <JBottomley@Parallels.com>2015-01-22 16:58:41 -0800
commit23c32a94d9d8932bb8dbaa5bff190dc3d28b27c8 (patch)
treeceab5c28cda96a168ead82d6489b2ac9a1b8a301
parentc2060c269bb4f9f44feebd84f66de08a0661e67c (diff)
downloadefitools-23c32a94d9d8932bb8dbaa5bff190dc3d28b27c8.tar.gz
sha256: Calculate hashes correctly for both X64 and IA32
In fact, the hash calculation was working more by luck than judgement. We need to be very careful dealing with the sections to make sure we use the correct part of the optional header. Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--hash-to-efi-sig-list.c4
-rw-r--r--include/PeImage.h1
-rw-r--r--lib/pecoff.c12
-rw-r--r--lib/sha256.c42
-rw-r--r--lib/simple_file.c4
5 files changed, 41 insertions, 22 deletions
diff --git a/hash-to-efi-sig-list.c b/hash-to-efi-sig-list.c
index 72135ac..4969052 100644
--- a/hash-to-efi-sig-list.c
+++ b/hash-to-efi-sig-list.c
@@ -17,6 +17,7 @@
#include <unistd.h>
#include <wchar.h>
+#include <PeImage.h> /* for ALIGN_VALUE */
#include <sha256.h>
#include <efiauthenticated.h>
#include <guid.h>
@@ -80,7 +81,8 @@ main(int argc, char *argv[])
exit(1);
}
fstat(fdefifile, &st);
- efifile = malloc(st.st_size);
+ efifile = malloc(ALIGN_VALUE(st.st_size, 4096));
+ memset(efifile, 0, ALIGN_VALUE(st.st_size, 4096));
read(fdefifile, efifile, st.st_size);
close(fdefifile);
status = sha256_get_pecoff_digest_mem(efifile, st.st_size,
diff --git a/include/PeImage.h b/include/PeImage.h
index ec13404..2e0c6c5 100644
--- a/include/PeImage.h
+++ b/include/PeImage.h
@@ -777,6 +777,7 @@ typedef struct {
UINTN SizeOfHeaders;
UINT16 ImageType;
UINT16 NumberOfSections;
+ UINT32 FileAlignment;
EFI_IMAGE_SECTION_HEADER *FirstSection;
EFI_IMAGE_DATA_DIRECTORY *RelocDir;
EFI_IMAGE_DATA_DIRECTORY *SecDir;
diff --git a/lib/pecoff.c b/lib/pecoff.c
index 8fa10da..11445cd 100644
--- a/lib/pecoff.c
+++ b/lib/pecoff.c
@@ -59,7 +59,8 @@
#include <errors.h>
#ifndef BUILD_EFI
-#define Print(...) do { } while(0)
+#include <stdio.h>
+#define Print(...) printf("%ls", __VA_ARGS__)
#define AllocatePool(x) malloc(x)
#define CopyMem(d, s, l) memcpy(d, s, l)
#define ZeroMem(s, l) memset(s, 0, l)
@@ -99,6 +100,7 @@ pecoff_read_header(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *data)
context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+ context->FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment;
} else if (PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
context->ImageAddress = PEHdr->Pe32.OptionalHeader.ImageBase;
@@ -108,7 +110,7 @@ pecoff_read_header(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *data)
context->RelocDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes;
context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
- }
+ context->FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment; }
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));
@@ -132,10 +134,8 @@ pecoff_image_layout(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data)
for (i = 0; i < context->NumberOfSections; i++) {
s = &context->FirstSection[i];
- size = s->Misc.VirtualSize;
-
- if (size > s->SizeOfRawData)
- size = s->SizeOfRawData;
+ size = ALIGN_VALUE(s->SizeOfRawData, context->FileAlignment);
+
base = pecoff_image_address(buffer, context->ImageSize, s->VirtualAddress);
end = pecoff_image_address(buffer, context->ImageSize, s->VirtualAddress + size - 1);
diff --git a/lib/sha256.c b/lib/sha256.c
index a34cab0..8966ff5 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -26,7 +26,8 @@
#include <simple_file.h>
#ifndef BUILD_EFI
-#define Print(...) do { } while(0)
+#include <stdio.h>
+#define Print(...) printf("%ls", __VA_ARGS__)
#define AllocatePool(x) malloc(x)
#define CopyMem(d, s, l) memcpy(d, s, l)
#define ZeroMem(s, l) memset(s, 0, l)
@@ -281,8 +282,13 @@ sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize,
unsigned int hashsize;
EFI_IMAGE_SECTION_HEADER *section;
EFI_IMAGE_SECTION_HEADER **sections;
- int i, sum_of_bytes;
+ int i, sum_of_bytes, checksum_size;
EFI_STATUS efi_status;
+ void *checksum_ptr;
+
+ /* add extra end alignment; rely on data buffer being zero
+ * filled to the end of the page */
+ DataSize = ALIGN_VALUE(DataSize, 8);
efi_status = pecoff_read_header(&context, buffer);
if (efi_status != EFI_SUCCESS) {
@@ -290,7 +296,15 @@ sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize,
return efi_status;
}
- sections = AllocatePool(context.PEHdr->Pe32.FileHeader.NumberOfSections * sizeof(*sections));
+ if (context.PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ checksum_ptr = &context.PEHdr->Pe32Plus.OptionalHeader.CheckSum;
+ checksum_size = sizeof(context.PEHdr->Pe32Plus.OptionalHeader.CheckSum);
+ } else {
+ checksum_ptr = &context.PEHdr->Pe32.OptionalHeader.CheckSum;
+ checksum_size = sizeof(context.PEHdr->Pe32.OptionalHeader.CheckSum);
+ }
+
+ sections = AllocatePool(context.NumberOfSections * sizeof(*sections));
if (!sections)
return EFI_OUT_OF_RESOURCES;
@@ -298,27 +312,26 @@ sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize,
/* hash start to checksum */
hashbase = buffer;
- hashsize = (void *)&context.PEHdr->Pe32.OptionalHeader.CheckSum - buffer;
+ hashsize = checksum_ptr - buffer;
sha256_update(&ctx, hashbase, hashsize);
/* hash post-checksum to start of certificate table */
- hashbase = (void *)&context.PEHdr->Pe32.OptionalHeader.CheckSum + sizeof (int);
+ hashbase = checksum_ptr + checksum_size;
hashsize = (void *)context.SecDir - hashbase;
sha256_update(&ctx, hashbase, hashsize);
/* Hash end of certificate table to end of image header */
- hashbase = &context.PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
- hashsize = context.PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders -
- (int) ((void *) (&context.PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - buffer);
+ hashbase = context.SecDir + 1;
+ hashsize = context.SizeOfHeaders -
+ (int) (hashbase - buffer);
sha256_update(&ctx, hashbase, hashsize);
- sum_of_bytes = context.PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
+ sum_of_bytes = context.SizeOfHeaders;
section = (EFI_IMAGE_SECTION_HEADER *) ((char *)context.PEHdr + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + context.PEHdr->Pe32.FileHeader.SizeOfOptionalHeader);
-
/* Sort the section headers by their data pointers */
- for (i = 0; i < context.PEHdr->Pe32.FileHeader.NumberOfSections; i++) {
+ for (i = 0; i < context.NumberOfSections; i++) {
int p = i;
while (p > 0 && section->PointerToRawData < sections[p - 1]->PointerToRawData) {
sections[p] = sections[p-1];
@@ -327,10 +340,11 @@ sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize,
sections[p] = section++;
}
/* hash the sorted sections */
- for (i = 0; i < context.PEHdr->Pe32.FileHeader.NumberOfSections; i++) {
+ for (i = 0; i < context.NumberOfSections; i++) {
section = sections[i];
hashbase = pecoff_image_address(buffer, DataSize, section->PointerToRawData);
- hashsize = (unsigned int) section->SizeOfRawData;
+ hashsize = (unsigned int) ALIGN_VALUE(section->SizeOfRawData,
+ context.FileAlignment);
if (hashsize == 0)
continue;
sha256_update(&ctx, hashbase, hashsize);
@@ -340,7 +354,7 @@ sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize,
if (DataSize > sum_of_bytes) {
/* stuff at end to hash */
hashbase = buffer + sum_of_bytes;
- hashsize = (unsigned int)(DataSize - context.PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - sum_of_bytes);
+ hashsize = (unsigned int)(DataSize - context.SecDir->Size - sum_of_bytes);
sha256_update(&ctx, hashbase, hashsize);
}
sha256_finish(&ctx, hash);
diff --git a/lib/simple_file.c b/lib/simple_file.c
index 0e5ecd2..7b37418 100644
--- a/lib/simple_file.c
+++ b/lib/simple_file.c
@@ -7,6 +7,7 @@
#include <efi.h>
#include <efilib.h>
+#include <PeImage.h> /* for ALIGN_VALUE */
#include <console.h>
#include <simple_file.h>
#include <efiauthenticated.h>
@@ -167,7 +168,8 @@ simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer)
*size = fi->FileSize;
- *buffer = AllocatePool(*size);
+ /* might use memory mapped, so align up to nearest page */
+ *buffer = AllocateZeroPool(ALIGN_VALUE(*size, 4096));
if (!*buffer) {
Print(L"Failed to allocate buffer of size %d\n", *size);
return EFI_OUT_OF_RESOURCES;