mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-05-16 13:12:01 +00:00
Add black/white listing
This commit is contained in:
parent
8877e13127
commit
c16548d08b
101
shim.c
101
shim.c
@ -51,6 +51,12 @@ static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TAB
|
|||||||
|
|
||||||
#include "cert.h"
|
#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,
|
static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid,
|
||||||
UINTN *size, void **buffer)
|
UINTN *size, void **buffer)
|
||||||
{
|
{
|
||||||
@ -193,33 +199,81 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
|||||||
return EFI_SUCCESS;
|
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_STATUS efi_status;
|
||||||
EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
|
EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
|
||||||
EFI_SIGNATURE_LIST *CertList;
|
EFI_SIGNATURE_LIST *CertList;
|
||||||
EFI_SIGNATURE_DATA *Cert;
|
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;
|
UINTN CertCount, Index;
|
||||||
BOOLEAN IsFound;
|
BOOLEAN IsFound;
|
||||||
void *db;
|
void *db;
|
||||||
unsigned int SignatureSize = SHA256_DIGEST_SIZE;
|
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)
|
if (efi_status != EFI_SUCCESS)
|
||||||
return EFI_SUCCESS;
|
return VAR_NOT_FOUND;
|
||||||
|
|
||||||
CertList = db;
|
CertList = db;
|
||||||
|
|
||||||
while ((dbxsize > 0) && (dbxsize >= CertList->SignatureListSize)) {
|
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
||||||
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
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))) {
|
if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &CertType))) {
|
||||||
for (Index = 0; Index < CertCount; Index++) {
|
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.
|
// 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);
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreePool(db);
|
FreePool(db);
|
||||||
|
|
||||||
if (IsFound)
|
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_ACCESS_DENIED;
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
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
|
* 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;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = check_blacklist(vendor_cert, hash);
|
status = check_blacklist(cert, hash);
|
||||||
|
|
||||||
if (status != EFI_SUCCESS) {
|
if (status != EFI_SUCCESS) {
|
||||||
Print(L"Binary is blacklisted\n");
|
Print(L"Binary is blacklisted\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = check_whitelist(cert, hash);
|
||||||
|
|
||||||
|
if (status == EFI_SUCCESS) {
|
||||||
|
Print(L"Binary is whitelisted\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (!AuthenticodeVerify(cert->CertData,
|
if (!AuthenticodeVerify(cert->CertData,
|
||||||
context->SecDir->Size - sizeof(cert->Hdr),
|
context->SecDir->Size - sizeof(cert->Hdr),
|
||||||
vendor_cert, sizeof(vendor_cert), hash,
|
vendor_cert, sizeof(vendor_cert), hash,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#define SHA256_DIGEST_SIZE 32
|
#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 {
|
typedef struct {
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user