summaryrefslogtreecommitdiff
path: root/shim.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2012-06-18 17:31:42 -0400
committerMatthew Garrett <mjg@redhat.com>2012-06-18 17:31:42 -0400
commit3df68c187cac181c1d40dc52517b88b9fb992852 (patch)
tree3b81d2542a67def840a1ae1e5bdb9b6c84ae5f86 /shim.c
parentdb54b0a4c6fec60960f7bdc63530cc91cb682b45 (diff)
downloadefi-boot-shim-3df68c187cac181c1d40dc52517b88b9fb992852.tar.gz
efi-boot-shim-3df68c187cac181c1d40dc52517b88b9fb992852.zip
Check binary against blacklist
Diffstat (limited to 'shim.c')
-rw-r--r--shim.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/shim.c b/shim.c
index 106b8585..1bd595bc 100644
--- a/shim.c
+++ b/shim.c
@@ -38,6 +38,7 @@
#include <Library/BaseCryptLib.h>
#include "PeImage.h"
#include "shim.h"
+#include "signature.h"
#define SECOND_STAGE L"\\grub.efi"
@@ -51,7 +52,7 @@ static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TAB
#include "cert.h"
static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid,
- unsigned int *size,void **buffer)
+ UINTN *size, void **buffer)
{
EFI_STATUS efi_status;
UINT32 attributes;
@@ -192,6 +193,59 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
return EFI_SUCCESS;
}
+static EFI_STATUS check_blacklist (UINT8 *cert, UINT8 *hash)
+{
+ EFI_STATUS efi_status;
+ EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINTN dbxsize = 0;
+ UINTN CertCount, Index;
+ BOOLEAN IsFound;
+ void *db;
+ unsigned int SignatureSize = SHA256_DIGEST_SIZE;
+ EFI_GUID CertType = EfiCertSha256Guid;
+
+ efi_status = get_variable(L"dbx", global_var, &dbxsize, &db);
+
+ /* If we can't read it then it can't be blacklisted */
+ if (efi_status != EFI_SUCCESS)
+ return EFI_SUCCESS;
+
+ CertList = db;
+
+ while ((dbxsize > 0) && (dbxsize >= CertList->SignatureListSize)) {
+ CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &CertType))) {
+ for (Index = 0; Index < CertCount; Index++) {
+ if (CompareMem (Cert->SignatureData, hash, SignatureSize) == 0) {
+ //
+ // Find the signature in database.
+ //
+ IsFound = TRUE;
+ break;
+ }
+
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ }
+ if (IsFound) {
+ break;
+ }
+ }
+
+ dbxsize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ }
+
+ FreePool(db);
+
+ if (IsFound)
+ return EFI_ACCESS_DENIED;
+
+ return EFI_SUCCESS;
+}
+
/*
* Check that the signature is valid and matches the binary
*/
@@ -208,7 +262,8 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
unsigned int hashsize;
WIN_CERTIFICATE_EFI_PKCS *cert;
unsigned int SumOfBytesHashed, SumOfSectionBytes;
- unsigned int index, pos, charsize = sizeof(char);
+ unsigned int index, pos;
+ UINTN charsize = sizeof(char);
EFI_IMAGE_SECTION_HEADER *Section;
EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL;
EFI_IMAGE_SECTION_HEADER *SectionCache;
@@ -374,6 +429,13 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
goto done;
}
+ status = check_blacklist(vendor_cert, hash);
+
+ if (status != EFI_SUCCESS) {
+ Print(L"Binary is blacklisted\n");
+ goto done;
+ }
+
if (!AuthenticodeVerify(cert->CertData,
context->SecDir->Size - sizeof(cert->Hdr),
vendor_cert, sizeof(cert), hash,