Add black/white listing

This commit is contained in:
Matthew Garrett 2012-06-25 10:59:08 -04:00
parent 8877e13127
commit c16548d08b
2 changed files with 93 additions and 11 deletions

101
shim.c
View File

@ -51,6 +51,12 @@ static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TAB
#include "cert.h"
typedef enum {
DATA_FOUND,
DATA_NOT_FOUND,
VAR_NOT_FOUND
} CHECK_STATUS;
static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid,
UINTN *size, void **buffer)
{
@ -193,33 +199,81 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
return EFI_SUCCESS;
}
static EFI_STATUS check_blacklist (UINT8 *cert, UINT8 *hash)
static CHECK_STATUS check_db_cert(CHAR16 *dbname, WIN_CERTIFICATE_EFI_PKCS *data, 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 dbsize = 0;
UINTN CertCount, Index;
BOOLEAN IsFound;
void *db;
EFI_GUID CertType = EfiCertX509Guid;
efi_status = get_variable(dbname, global_var, &dbsize, &db);
if (efi_status != EFI_SUCCESS)
return VAR_NOT_FOUND;
CertList = db;
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
if (CompareGuid (&CertList->SignatureType, &CertType)) {
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
for (Index = 0; Index < CertCount; Index++) {
IsFound = AuthenticodeVerify (data->CertData,
data->Hdr.dwLength - sizeof(data->Hdr),
Cert->SignatureData,
CertList->SignatureSize,
hash, SHA256_DIGEST_SIZE);
}
if (IsFound) {
break;
}
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
}
dbsize -= CertList->SignatureListSize;
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
}
FreePool(db);
if (IsFound)
return DATA_FOUND;
return DATA_NOT_FOUND;
}
static CHECK_STATUS check_db_hash(CHAR16 *dbname, UINT8 *data)
{
EFI_STATUS efi_status;
EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
EFI_SIGNATURE_LIST *CertList;
EFI_SIGNATURE_DATA *Cert;
UINTN dbsize = 0;
UINTN CertCount, Index;
BOOLEAN IsFound;
void *db;
unsigned int SignatureSize = SHA256_DIGEST_SIZE;
EFI_GUID CertType = EfiCertSha256Guid;
EFI_GUID CertType = EfiHashSha256Guid;
efi_status = get_variable(L"dbx", global_var, &dbxsize, &db);
efi_status = get_variable(dbname, global_var, &dbsize, &db);
/* If we can't read it then it can't be blacklisted */
if (efi_status != EFI_SUCCESS)
return EFI_SUCCESS;
return VAR_NOT_FOUND;
CertList = db;
while ((dbxsize > 0) && (dbxsize >= CertList->SignatureListSize)) {
while ((dbsize > 0) && (dbsize >= 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) {
if (CompareMem (Cert->SignatureData, data, SignatureSize) == 0) {
//
// Find the signature in database.
//
@ -234,18 +288,38 @@ static EFI_STATUS check_blacklist (UINT8 *cert, UINT8 *hash)
}
}
dbxsize -= CertList->SignatureListSize;
dbsize -= CertList->SignatureListSize;
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
}
FreePool(db);
if (IsFound)
return DATA_FOUND;
return DATA_NOT_FOUND;
}
static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, UINT8 *hash)
{
if (check_db_hash(L"dbx", hash) == DATA_FOUND)
return EFI_ACCESS_DENIED;
if (check_db_cert(L"dbx", cert, hash) == DATA_FOUND)
return EFI_ACCESS_DENIED;
return EFI_SUCCESS;
}
static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, UINT8 *hash)
{
if (check_db_hash(L"db", hash) == DATA_FOUND)
return EFI_SUCCESS;
if (check_db_cert(L"db", cert, hash) == DATA_FOUND)
return EFI_SUCCESS;
return EFI_ACCESS_DENIED;
}
/*
* Check that the signature is valid and matches the binary
*/
@ -429,13 +503,20 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
goto done;
}
status = check_blacklist(vendor_cert, hash);
status = check_blacklist(cert, hash);
if (status != EFI_SUCCESS) {
Print(L"Binary is blacklisted\n");
goto done;
}
status = check_whitelist(cert, hash);
if (status == EFI_SUCCESS) {
Print(L"Binary is whitelisted\n");
goto done;
}
if (!AuthenticodeVerify(cert->CertData,
context->SecDir->Size - sizeof(cert->Hdr),
vendor_cert, sizeof(vendor_cert), hash,

View File

@ -1,6 +1,7 @@
#define SHA256_DIGEST_SIZE 32
EFI_GUID EfiCertSha256Guid = { 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 }};
EFI_GUID EfiHashSha256Guid = { 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 }};
EFI_GUID EfiCertX509Guid = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 }};
typedef struct {
///