Skip to content

Commit

Permalink
Load concatenated EFI_SIGNATURE_LISTs from shim_certificate.efi
Browse files Browse the repository at this point in the history
For multiple reasons, it may be useful for different keys to be used to
sign different parts of the boot chain (e.g. a different key for GRUB
and the Linux kernel). Allow this by loading concatenated
EFI_SIGNATURE_LISTs from shim_certificate.efi rather than only the
first.

At the same time, be a bit more robust by checking for allocation
failures and overflows due to invalid data in the binary.
Use VirtualSize rather than SizeOfRawData since the latter is rounded up
to the section alignment and therefore contains non-certificate data.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
  • Loading branch information
rosslagerwall committed May 9, 2024
1 parent 6228e2c commit 0885b25
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,7 @@ load_cert_file(EFI_HANDLE image_handle, CHAR16 *filename, CHAR16 *PathName)
EFI_SIGNATURE_LIST *certlist;
void *pointer;
UINT32 original;
UINT32 offset;
int datasize = 0;
void *data = NULL;
int i;
Expand All @@ -1535,22 +1536,36 @@ load_cert_file(EFI_HANDLE image_handle, CHAR16 *filename, CHAR16 *PathName)

Section = context.FirstSection;
for (i = 0; i < context.NumberOfSections; i++, Section++) {
if (CompareMem(Section->Name, ".db\0\0\0\0\0", 8) == 0) {
original = user_cert_size;
if (Section->SizeOfRawData < sizeof(EFI_SIGNATURE_LIST)) {
continue;
}
pointer = ImageAddress(data, datasize,
Section->PointerToRawData);
if (!pointer) {
continue;
if (CompareMem(Section->Name, ".db\0\0\0\0\0", 8) == 0 &&
Section->Misc.VirtualSize <= Section->SizeOfRawData) {
offset = 0;
while ((Section->Misc.VirtualSize - offset) >= sizeof(EFI_SIGNATURE_LIST)) {
original = user_cert_size;
pointer = ImageAddress(data, datasize,
Section->PointerToRawData + offset);
if (!pointer) {
break;
}
certlist = pointer;

if (certlist->SignatureListSize < sizeof(EFI_SIGNATURE_LIST) ||
checked_add(offset, certlist->SignatureListSize, &offset) ||
offset > Section->Misc.VirtualSize ||
checked_add(user_cert_size, certlist->SignatureListSize,
&user_cert_size)) {
break;
}

user_cert = ReallocatePool(user_cert, original,
user_cert_size);
if (!user_cert) {
FreePool(data);
return EFI_OUT_OF_RESOURCES;
}

CopyMem(user_cert + original, pointer,
certlist->SignatureListSize);
}
certlist = pointer;
user_cert_size += certlist->SignatureListSize;;
user_cert = ReallocatePool(user_cert, original,
user_cert_size);
CopyMem(user_cert + original, pointer,
certlist->SignatureListSize);
}
}
FreePool(data);
Expand Down

0 comments on commit 0885b25

Please sign in to comment.