mirror of https://github.com/acidanthera/audk.git
SecurityPkg: Update DxeImageVerificationLib with following changes:
1. Update to check image digest against dbx before execute it. 2. Update to support revoke certificate. 3. Update to support enroll unsigned PE image's Hash to allowed database (db). (Note: Unsigned Image's Hash is calculated in the same way with authenticode, the algorithm is assumed to be SHA256.) Signed-off-by: xdu2 Reviewed-by: tye Reviewed-by: gdong1 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12598 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
d26727de5f
commit
45bf2c4789
|
@ -2,12 +2,12 @@
|
||||||
Implement image verification services for secure boot service in UEFI2.3.1.
|
Implement image verification services for secure boot service in UEFI2.3.1.
|
||||||
|
|
||||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
http://opensource.org/licenses/bsd-license.php
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
|
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
|
||||||
UINTN mImageSize;
|
UINTN mImageSize;
|
||||||
UINT32 mPeCoffHeaderOffset;
|
UINT32 mPeCoffHeaderOffset;
|
||||||
UINT8 mImageDigest[MAX_DIGEST_SIZE];
|
UINT8 mImageDigest[MAX_DIGEST_SIZE];
|
||||||
UINTN mImageDigestSize;
|
UINTN mImageDigestSize;
|
||||||
EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;
|
EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;
|
||||||
|
@ -59,9 +59,9 @@ HASH_TABLE mHash[] = {
|
||||||
Get the image type.
|
Get the image type.
|
||||||
|
|
||||||
@param[in] File This is a pointer to the device path of the file that is
|
@param[in] File This is a pointer to the device path of the file that is
|
||||||
being dispatched.
|
being dispatched.
|
||||||
|
|
||||||
@return UINT32 Image Type
|
@return UINT32 Image Type
|
||||||
|
|
||||||
**/
|
**/
|
||||||
UINT32
|
UINT32
|
||||||
|
@ -70,7 +70,7 @@ GetImageType (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_HANDLE DeviceHandle;
|
EFI_HANDLE DeviceHandle;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
||||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ GetImageType (
|
||||||
// First check to see if File is from a Firmware Volume
|
// First check to see if File is from a Firmware Volume
|
||||||
//
|
//
|
||||||
DeviceHandle = NULL;
|
DeviceHandle = NULL;
|
||||||
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
|
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
|
||||||
Status = gBS->LocateDevicePath (
|
Status = gBS->LocateDevicePath (
|
||||||
&gEfiFirmwareVolume2ProtocolGuid,
|
&gEfiFirmwareVolume2ProtocolGuid,
|
||||||
&TempDevicePath,
|
&TempDevicePath,
|
||||||
|
@ -102,7 +102,7 @@ GetImageType (
|
||||||
// Next check to see if File is from a Block I/O device
|
// Next check to see if File is from a Block I/O device
|
||||||
//
|
//
|
||||||
DeviceHandle = NULL;
|
DeviceHandle = NULL;
|
||||||
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
|
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
|
||||||
Status = gBS->LocateDevicePath (
|
Status = gBS->LocateDevicePath (
|
||||||
&gEfiBlockIoProtocolGuid,
|
&gEfiBlockIoProtocolGuid,
|
||||||
&TempDevicePath,
|
&TempDevicePath,
|
||||||
|
@ -136,11 +136,11 @@ GetImageType (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// File is not in a Firmware Volume or on a Block I/O device, so check to see if
|
// File is not in a Firmware Volume or on a Block I/O device, so check to see if
|
||||||
// the device path supports the Simple File System Protocol.
|
// the device path supports the Simple File System Protocol.
|
||||||
//
|
//
|
||||||
DeviceHandle = NULL;
|
DeviceHandle = NULL;
|
||||||
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
|
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
|
||||||
Status = gBS->LocateDevicePath (
|
Status = gBS->LocateDevicePath (
|
||||||
&gEfiSimpleFileSystemProtocolGuid,
|
&gEfiSimpleFileSystemProtocolGuid,
|
||||||
&TempDevicePath,
|
&TempDevicePath,
|
||||||
|
@ -155,12 +155,12 @@ GetImageType (
|
||||||
|
|
||||||
//
|
//
|
||||||
// File is not from an FV, Block I/O or Simple File System, so the only options
|
// File is not from an FV, Block I/O or Simple File System, so the only options
|
||||||
// left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
|
// left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
|
||||||
//
|
//
|
||||||
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
|
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;
|
||||||
while (!IsDevicePathEndType (TempDevicePath)) {
|
while (!IsDevicePathEndType (TempDevicePath)) {
|
||||||
switch (DevicePathType (TempDevicePath)) {
|
switch (DevicePathType (TempDevicePath)) {
|
||||||
|
|
||||||
case MEDIA_DEVICE_PATH:
|
case MEDIA_DEVICE_PATH:
|
||||||
if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
|
if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
|
||||||
return IMAGE_FROM_OPTION_ROM;
|
return IMAGE_FROM_OPTION_ROM;
|
||||||
|
@ -170,7 +170,7 @@ GetImageType (
|
||||||
case MESSAGING_DEVICE_PATH:
|
case MESSAGING_DEVICE_PATH:
|
||||||
if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
|
if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
|
||||||
return IMAGE_FROM_REMOVABLE_MEDIA;
|
return IMAGE_FROM_REMOVABLE_MEDIA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -178,7 +178,7 @@ GetImageType (
|
||||||
}
|
}
|
||||||
TempDevicePath = NextDevicePathNode (TempDevicePath);
|
TempDevicePath = NextDevicePathNode (TempDevicePath);
|
||||||
}
|
}
|
||||||
return IMAGE_UNKNOWN;
|
return IMAGE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,12 +186,12 @@ GetImageType (
|
||||||
PE/COFF Specification 8.0 Appendix A
|
PE/COFF Specification 8.0 Appendix A
|
||||||
|
|
||||||
@param[in] HashAlg Hash algorithm type.
|
@param[in] HashAlg Hash algorithm type.
|
||||||
|
|
||||||
@retval TRUE Successfully hash image.
|
@retval TRUE Successfully hash image.
|
||||||
@retval FALSE Fail in hash image.
|
@retval FALSE Fail in hash image.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
HashPeImage (
|
HashPeImage (
|
||||||
IN UINT32 HashAlg
|
IN UINT32 HashAlg
|
||||||
)
|
)
|
||||||
|
@ -208,8 +208,8 @@ HashPeImage (
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINTN Pos;
|
UINTN Pos;
|
||||||
UINTN SumOfSectionBytes;
|
UINTN SumOfSectionBytes;
|
||||||
EFI_IMAGE_SECTION_HEADER *SectionCache;
|
EFI_IMAGE_SECTION_HEADER *SectionCache;
|
||||||
|
|
||||||
HashCtx = NULL;
|
HashCtx = NULL;
|
||||||
SectionHeader = NULL;
|
SectionHeader = NULL;
|
||||||
Status = FALSE;
|
Status = FALSE;
|
||||||
|
@ -217,7 +217,7 @@ HashPeImage (
|
||||||
if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
|
if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize context of hash.
|
// Initialize context of hash.
|
||||||
//
|
//
|
||||||
|
@ -234,7 +234,7 @@ HashPeImage (
|
||||||
}
|
}
|
||||||
|
|
||||||
CtxSize = mHash[HashAlg].GetContextSize();
|
CtxSize = mHash[HashAlg].GetContextSize();
|
||||||
|
|
||||||
HashCtx = AllocatePool (CtxSize);
|
HashCtx = AllocatePool (CtxSize);
|
||||||
if (HashCtx == NULL) {
|
if (HashCtx == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -244,7 +244,7 @@ HashPeImage (
|
||||||
|
|
||||||
// 2. Initialize a SHA hash context.
|
// 2. Initialize a SHA hash context.
|
||||||
Status = mHash[HashAlg].HashInit(HashCtx);
|
Status = mHash[HashAlg].HashInit(HashCtx);
|
||||||
|
|
||||||
if (!Status) {
|
if (!Status) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ HashPeImage (
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Use PE32+ offset.
|
// Use PE32+ offset.
|
||||||
//
|
//
|
||||||
HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
|
HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
|
||||||
HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
|
HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ HashPeImage (
|
||||||
for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) {
|
for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) {
|
||||||
SumOfSectionBytes += SectionCache->SizeOfRawData;
|
SumOfSectionBytes += SectionCache->SizeOfRawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sanity check for file corruption. Sections raw data size should be smaller
|
// Sanity check for file corruption. Sections raw data size should be smaller
|
||||||
// than Image Size.
|
// than Image Size.
|
||||||
|
@ -436,7 +436,7 @@ HashPeImage (
|
||||||
HashSize = (UINTN)(
|
HashSize = (UINTN)(
|
||||||
mImageSize -
|
mImageSize -
|
||||||
mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
|
mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
|
||||||
SumOfBytesHashed);
|
SumOfBytesHashed);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
|
Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);
|
||||||
|
@ -457,15 +457,15 @@ Done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
|
Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
|
||||||
Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
|
Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
|
||||||
8.0 Appendix A
|
8.0 Appendix A
|
||||||
|
|
||||||
@retval EFI_UNSUPPORTED Hash algorithm is not supported.
|
@retval EFI_UNSUPPORTED Hash algorithm is not supported.
|
||||||
@retval EFI_SUCCESS Hash successfully.
|
@retval EFI_SUCCESS Hash successfully.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
HashPeImageByType (
|
HashPeImageByType (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
|
@ -475,10 +475,10 @@ HashPeImageByType (
|
||||||
|
|
||||||
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
|
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
|
||||||
|
|
||||||
for (Index = 0; Index < HASHALG_MAX; Index++) {
|
for (Index = 0; Index < HASHALG_MAX; Index++) {
|
||||||
//
|
//
|
||||||
// Check the Hash algorithm in PE/COFF Authenticode.
|
// Check the Hash algorithm in PE/COFF Authenticode.
|
||||||
// According to PKCS#7 Definition:
|
// According to PKCS#7 Definition:
|
||||||
// SignedData ::= SEQUENCE {
|
// SignedData ::= SEQUENCE {
|
||||||
// version Version,
|
// version Version,
|
||||||
// digestAlgorithms DigestAlgorithmIdentifiers,
|
// digestAlgorithms DigestAlgorithmIdentifiers,
|
||||||
|
@ -486,7 +486,7 @@ HashPeImageByType (
|
||||||
// .... }
|
// .... }
|
||||||
// The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
|
// The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
|
||||||
// This field has the fixed offset (+32) in final Authenticode ASN.1 data.
|
// This field has the fixed offset (+32) in final Authenticode ASN.1 data.
|
||||||
//
|
//
|
||||||
if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
|
if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -514,7 +514,7 @@ HashPeImageByType (
|
||||||
ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
|
ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
|
||||||
|
|
||||||
@param ImageExeInfoTable A pointer to a image execution info table structure.
|
@param ImageExeInfoTable A pointer to a image execution info table structure.
|
||||||
|
|
||||||
@retval 0 If ImageExeInfoTable is NULL.
|
@retval 0 If ImageExeInfoTable is NULL.
|
||||||
@retval Others The size of a image execution info table in bytes.
|
@retval Others The size of a image execution info table in bytes.
|
||||||
|
|
||||||
|
@ -550,12 +550,12 @@ GetImageExeInfoTableSize (
|
||||||
@param[in] DevicePath Input device path pointer.
|
@param[in] DevicePath Input device path pointer.
|
||||||
@param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
|
@param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
|
||||||
@param[in] SignatureSize Size of signature.
|
@param[in] SignatureSize Size of signature.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
VOID
|
VOID
|
||||||
AddImageExeInfo (
|
AddImageExeInfo (
|
||||||
IN EFI_IMAGE_EXECUTION_ACTION Action,
|
IN EFI_IMAGE_EXECUTION_ACTION Action,
|
||||||
IN CHAR16 *Name OPTIONAL,
|
IN CHAR16 *Name OPTIONAL,
|
||||||
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
|
IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
|
||||||
IN UINTN SignatureSize
|
IN UINTN SignatureSize
|
||||||
|
@ -577,13 +577,13 @@ AddImageExeInfo (
|
||||||
if (DevicePath == NULL) {
|
if (DevicePath == NULL) {
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Name != NULL) {
|
if (Name != NULL) {
|
||||||
NameStringLen = StrSize (Name);
|
NameStringLen = StrSize (Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageExeInfoTable = NULL;
|
ImageExeInfoTable = NULL;
|
||||||
EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID**)&ImageExeInfoTable);
|
EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **) &ImageExeInfoTable);
|
||||||
if (ImageExeInfoTable != NULL) {
|
if (ImageExeInfoTable != NULL) {
|
||||||
//
|
//
|
||||||
// The table has been found!
|
// The table has been found!
|
||||||
|
@ -637,7 +637,7 @@ AddImageExeInfo (
|
||||||
// Update/replace the image execution table.
|
// Update/replace the image execution table.
|
||||||
//
|
//
|
||||||
gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
|
gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Free Old table data!
|
// Free Old table data!
|
||||||
//
|
//
|
||||||
|
@ -649,7 +649,7 @@ AddImageExeInfo (
|
||||||
/**
|
/**
|
||||||
Discover if the UEFI image is authorized by user's policy setting.
|
Discover if the UEFI image is authorized by user's policy setting.
|
||||||
|
|
||||||
@param[in] Policy Specify platform's policy setting.
|
@param[in] Policy Specify platform's policy setting.
|
||||||
|
|
||||||
@retval EFI_ACCESS_DENIED Image is not allowed to run.
|
@retval EFI_ACCESS_DENIED Image is not allowed to run.
|
||||||
@retval EFI_SECURITY_VIOLATION Image is deferred.
|
@retval EFI_SECURITY_VIOLATION Image is deferred.
|
||||||
|
@ -667,7 +667,7 @@ ImageAuthorization (
|
||||||
Status = EFI_ACCESS_DENIED;
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
|
||||||
switch (Policy) {
|
switch (Policy) {
|
||||||
|
|
||||||
case QUERY_USER_ON_SECURITY_VIOLATION:
|
case QUERY_USER_ON_SECURITY_VIOLATION:
|
||||||
do {
|
do {
|
||||||
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, mNotifyString1, mNotifyString2, NULL);
|
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, mNotifyString1, mNotifyString2, NULL);
|
||||||
|
@ -715,7 +715,7 @@ ImageAuthorization (
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
IsSignatureFoundInDatabase (
|
IsSignatureFoundInDatabase (
|
||||||
IN CHAR16 *VariableName,
|
IN CHAR16 *VariableName,
|
||||||
IN UINT8 *Signature,
|
IN UINT8 *Signature,
|
||||||
IN EFI_GUID *CertType,
|
IN EFI_GUID *CertType,
|
||||||
IN UINTN SignatureSize
|
IN UINTN SignatureSize
|
||||||
)
|
)
|
||||||
|
@ -786,16 +786,20 @@ Done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format .
|
Verify PKCS#7 SignedData using certificate found in Variable which formatted
|
||||||
|
as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Image pass verification.
|
@param VariableName Name of Variable to search for Certificate.
|
||||||
@retval EFI_SECURITY_VIOLATION Image fail verification.
|
@param VendorGuid Variable vendor GUID.
|
||||||
@retval EFI_OUT_OF_RESOURCE Fail to allocate memory.
|
|
||||||
|
@retval TRUE Image pass verification.
|
||||||
|
@retval FALSE Image fail verification.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
BOOLEAN
|
||||||
VerifyCertPkcsSignedData (
|
IsPkcsSignedDataVerifiedBySignatureList (
|
||||||
VOID
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
@ -804,55 +808,50 @@ VerifyCertPkcsSignedData (
|
||||||
EFI_SIGNATURE_LIST *CertList;
|
EFI_SIGNATURE_LIST *CertList;
|
||||||
EFI_SIGNATURE_DATA *Cert;
|
EFI_SIGNATURE_DATA *Cert;
|
||||||
UINTN DataSize;
|
UINTN DataSize;
|
||||||
UINT8 *KekData;
|
UINT8 *Data;
|
||||||
UINT8 *DbData;
|
|
||||||
UINT8 *RootCert;
|
UINT8 *RootCert;
|
||||||
UINTN RootCertSize;
|
UINTN RootCertSize;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINTN CertCount;
|
UINTN CertCount;
|
||||||
|
|
||||||
KekData = NULL;
|
Data = NULL;
|
||||||
DbData = NULL;
|
CertList = NULL;
|
||||||
CertList = NULL;
|
Cert = NULL;
|
||||||
Cert = NULL;
|
RootCert = NULL;
|
||||||
RootCert = NULL;
|
RootCertSize = 0;
|
||||||
RootCertSize = 0;
|
VerifyStatus = FALSE;
|
||||||
VerifyStatus = FALSE;
|
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
|
||||||
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
|
|
||||||
|
|
||||||
//
|
|
||||||
// 1: Find certificate from KEK database and try to verify authenticode struct.
|
|
||||||
//
|
|
||||||
DataSize = 0;
|
DataSize = 0;
|
||||||
Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);
|
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
|
||||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
KekData = (UINT8 *)AllocateZeroPool (DataSize);
|
Data = (UINT8 *) AllocateZeroPool (DataSize);
|
||||||
if (KekData == NULL) {
|
if (Data == NULL) {
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return VerifyStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, (VOID *)KekData);
|
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Find Cert Enrolled in KEK database to verify the signature in pkcs7 signed data.
|
// Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.
|
||||||
//
|
//
|
||||||
CertList = (EFI_SIGNATURE_LIST *) KekData;
|
CertList = (EFI_SIGNATURE_LIST *) Data;
|
||||||
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
|
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
|
||||||
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
|
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
||||||
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||||
for (Index = 0; Index < CertCount; Index++) {
|
for (Index = 0; Index < CertCount; Index++) {
|
||||||
//
|
//
|
||||||
// Iterate each Signature Data Node within this CertList for a verify
|
// Iterate each Signature Data Node within this CertList for verify.
|
||||||
//
|
//
|
||||||
RootCert = Cert->SignatureData;
|
RootCert = Cert->SignatureData;
|
||||||
RootCertSize = CertList->SignatureSize;
|
RootCertSize = CertList->SignatureSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Call AuthenticodeVerify library to Verify Authenticode struct.
|
// Call AuthenticodeVerify library to Verify Authenticode struct.
|
||||||
//
|
//
|
||||||
VerifyStatus = AuthenticodeVerify (
|
VerifyStatus = AuthenticodeVerify (
|
||||||
PkcsCertData->CertData,
|
PkcsCertData->CertData,
|
||||||
|
@ -862,68 +861,11 @@ VerifyCertPkcsSignedData (
|
||||||
mImageDigest,
|
mImageDigest,
|
||||||
mImageDigestSize
|
mImageDigestSize
|
||||||
);
|
);
|
||||||
|
|
||||||
if (VerifyStatus) {
|
if (VerifyStatus) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
DataSize -= CertList->SignatureListSize;
|
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 2: Find certificate from DB database and try to verify authenticode struct.
|
|
||||||
//
|
|
||||||
DataSize = 0;
|
|
||||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
|
|
||||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
||||||
DbData = (UINT8 *)AllocateZeroPool (DataSize);
|
|
||||||
if (DbData == NULL) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)DbData);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find Cert Enrolled in DB database to verify the signature in pkcs7 signed data.
|
|
||||||
//
|
|
||||||
CertList = (EFI_SIGNATURE_LIST *) DbData;
|
|
||||||
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
|
|
||||||
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
|
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
|
||||||
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
|
||||||
for (Index = 0; Index < CertCount; Index++) {
|
|
||||||
//
|
|
||||||
// Iterate each Signature Data Node within this CertList for a verify
|
|
||||||
//
|
|
||||||
RootCert = Cert->SignatureData;
|
|
||||||
RootCertSize = CertList->SignatureSize;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call AuthenticodeVerify library to Verify Authenticode struct.
|
|
||||||
//
|
|
||||||
VerifyStatus = AuthenticodeVerify (
|
|
||||||
PkcsCertData->CertData,
|
|
||||||
mSecDataDir->Size - sizeof(PkcsCertData->Hdr),
|
|
||||||
RootCert,
|
|
||||||
RootCertSize,
|
|
||||||
mImageDigest,
|
|
||||||
mImageDigestSize
|
|
||||||
);
|
|
||||||
|
|
||||||
if (VerifyStatus) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DataSize -= CertList->SignatureListSize;
|
DataSize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||||
|
@ -931,15 +873,47 @@ VerifyCertPkcsSignedData (
|
||||||
}
|
}
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
if (KekData != NULL) {
|
if (Data != NULL) {
|
||||||
FreePool (KekData);
|
FreePool (Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DbData != NULL) {
|
return VerifyStatus;
|
||||||
FreePool (DbData);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Image pass verification.
|
||||||
|
@retval EFI_SECURITY_VIOLATION Image fail verification.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
VerifyCertPkcsSignedData (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// 1: Find certificate from DBX forbidden database for revoked certificate.
|
||||||
|
//
|
||||||
|
if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
|
||||||
|
//
|
||||||
|
// DBX is forbidden database, if Authenticode verification pass with
|
||||||
|
// one of the certificate in DBX, this image should be rejected.
|
||||||
|
//
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VerifyStatus) {
|
//
|
||||||
|
// 2: Find certificate from KEK database and try to verify authenticode struct.
|
||||||
|
//
|
||||||
|
if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid)) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 3: Find certificate from DB database and try to verify authenticode struct.
|
||||||
|
//
|
||||||
|
if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return EFI_SECURITY_VIOLATION;
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
@ -947,14 +921,14 @@ Done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
|
Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.
|
||||||
|
|
||||||
@retval EFI_SUCCESS Image pass verification.
|
@retval EFI_SUCCESS Image pass verification.
|
||||||
@retval EFI_SECURITY_VIOLATION Image fail verification.
|
@retval EFI_SECURITY_VIOLATION Image fail verification.
|
||||||
@retval other error value
|
@retval other error value
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
VerifyCertUefiGuid (
|
VerifyCertUefiGuid (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
|
@ -1004,7 +978,7 @@ VerifyCertUefiGuid (
|
||||||
if (KekList == NULL) {
|
if (KekList == NULL) {
|
||||||
return EFI_SECURITY_VIOLATION;
|
return EFI_SECURITY_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enumerate all Kek items in this list to verify the variable certificate data.
|
// Enumerate all Kek items in this list to verify the variable certificate data.
|
||||||
// If anyone is authenticated successfully, it means the variable is correct!
|
// If anyone is authenticated successfully, it means the variable is correct!
|
||||||
|
@ -1024,7 +998,7 @@ VerifyCertUefiGuid (
|
||||||
KekDataSize -= KekList->SignatureListSize;
|
KekDataSize -= KekList->SignatureListSize;
|
||||||
KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
|
KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsFound) {
|
if (!IsFound) {
|
||||||
//
|
//
|
||||||
// Signed key is not a trust one.
|
// Signed key is not a trust one.
|
||||||
|
@ -1041,8 +1015,8 @@ VerifyCertUefiGuid (
|
||||||
Status = FALSE;
|
Status = FALSE;
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set RSA Key Components.
|
// Set RSA Key Components.
|
||||||
// NOTE: Only N and E are needed to be set as RSA public key for signature verification.
|
// NOTE: Only N and E are needed to be set as RSA public key for signature verification.
|
||||||
//
|
//
|
||||||
|
@ -1058,13 +1032,13 @@ VerifyCertUefiGuid (
|
||||||
// Verify the signature.
|
// Verify the signature.
|
||||||
//
|
//
|
||||||
Status = RsaPkcs1Verify (
|
Status = RsaPkcs1Verify (
|
||||||
Rsa,
|
Rsa,
|
||||||
mImageDigest,
|
mImageDigest,
|
||||||
mImageDigestSize,
|
mImageDigestSize,
|
||||||
CertBlock->Signature,
|
CertBlock->Signature,
|
||||||
EFI_CERT_TYPE_RSA2048_SHA256_SIZE
|
EFI_CERT_TYPE_RSA2048_SHA256_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
if (KekList != NULL) {
|
if (KekList != NULL) {
|
||||||
FreePool (KekList);
|
FreePool (KekList);
|
||||||
|
@ -1081,13 +1055,31 @@ Done:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Provide verification service for signed images, which include both signature validation
|
Provide verification service for signed images, which include both signature validation
|
||||||
and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
|
and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
|
||||||
MSFT Authenticode type signatures are supported.
|
MSFT Authenticode type signatures are supported.
|
||||||
|
|
||||||
In this implementation, only verify external executables when in USER MODE.
|
|
||||||
Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
|
|
||||||
|
|
||||||
@param[in] AuthenticationStatus
|
In this implementation, only verify external executables when in USER MODE.
|
||||||
|
Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
|
||||||
|
|
||||||
|
The image verification process is:
|
||||||
|
Is the Image signed?
|
||||||
|
If yes,
|
||||||
|
Does the image verify against a certificate (root or intermediate) in the allowed db?
|
||||||
|
Run it
|
||||||
|
Image verification fail
|
||||||
|
Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?
|
||||||
|
Run it
|
||||||
|
If no,
|
||||||
|
Is the Image's Hash in the forbidden database (DBX)?
|
||||||
|
if yes,
|
||||||
|
Error out
|
||||||
|
Is the Image's Hash in the allowed database (DB)?
|
||||||
|
If yes,
|
||||||
|
Run it
|
||||||
|
If no,
|
||||||
|
Error out
|
||||||
|
|
||||||
|
@param[in] AuthenticationStatus
|
||||||
This is the authentication status returned from the security
|
This is the authentication status returned from the security
|
||||||
measurement services for the input file.
|
measurement services for the input file.
|
||||||
@param[in] File This is a pointer to the device path of the file that is
|
@param[in] File This is a pointer to the device path of the file that is
|
||||||
|
@ -1144,7 +1136,7 @@ DxeImageVerificationHandler (
|
||||||
// Check the image type and get policy setting.
|
// Check the image type and get policy setting.
|
||||||
//
|
//
|
||||||
switch (GetImageType (File)) {
|
switch (GetImageType (File)) {
|
||||||
|
|
||||||
case IMAGE_FROM_FV:
|
case IMAGE_FROM_FV:
|
||||||
Policy = ALWAYS_EXECUTE;
|
Policy = ALWAYS_EXECUTE;
|
||||||
break;
|
break;
|
||||||
|
@ -1162,7 +1154,7 @@ DxeImageVerificationHandler (
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
|
Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -1188,8 +1180,8 @@ DxeImageVerificationHandler (
|
||||||
if (*SecureBootEnable == SECURE_BOOT_DISABLE) {
|
if (*SecureBootEnable == SECURE_BOOT_DISABLE) {
|
||||||
FreePool (SecureBootEnable);
|
FreePool (SecureBootEnable);
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);
|
SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1216,10 +1208,10 @@ DxeImageVerificationHandler (
|
||||||
}
|
}
|
||||||
mImageBase = (UINT8 *) FileBuffer;
|
mImageBase = (UINT8 *) FileBuffer;
|
||||||
mImageSize = FileSize;
|
mImageSize = FileSize;
|
||||||
DosHdr = (EFI_IMAGE_DOS_HEADER *) (mImageBase);
|
DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
|
||||||
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
|
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
|
||||||
//
|
//
|
||||||
// DOS image header is present,
|
// DOS image header is present,
|
||||||
// so read the PE header after the DOS image header.
|
// so read the PE header after the DOS image header.
|
||||||
//
|
//
|
||||||
mPeCoffHeaderOffset = DosHdr->e_lfanew;
|
mPeCoffHeaderOffset = DosHdr->e_lfanew;
|
||||||
|
@ -1242,12 +1234,12 @@ DxeImageVerificationHandler (
|
||||||
//
|
//
|
||||||
// Use PE32 offset.
|
// Use PE32 offset.
|
||||||
//
|
//
|
||||||
mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||||
} else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
} else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||||
//
|
//
|
||||||
// Use PE32+ offset.
|
// Use PE32+ offset.
|
||||||
//
|
//
|
||||||
mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Invalid header magic number.
|
// Invalid header magic number.
|
||||||
|
@ -1268,21 +1260,45 @@ DxeImageVerificationHandler (
|
||||||
//
|
//
|
||||||
// This image is not signed.
|
// This image is not signed.
|
||||||
//
|
//
|
||||||
|
if (!HashPeImage (HASHALG_SHA256)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
|
||||||
|
//
|
||||||
|
// Image Hash is in forbidden database (DBX).
|
||||||
|
//
|
||||||
|
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
|
||||||
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
|
||||||
|
//
|
||||||
|
// Image Hash is in allowed database (DB).
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Image Hash is not found in both forbidden and allowed database.
|
||||||
|
//
|
||||||
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
|
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
|
||||||
Status = EFI_ACCESS_DENIED;
|
Status = EFI_ACCESS_DENIED;
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Verify signature of executables.
|
// Verify signature of executables.
|
||||||
//
|
//
|
||||||
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);
|
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);
|
||||||
|
|
||||||
switch (WinCertificate->wCertificateType) {
|
switch (WinCertificate->wCertificateType) {
|
||||||
|
|
||||||
case WIN_CERT_TYPE_EFI_GUID:
|
case WIN_CERT_TYPE_EFI_GUID:
|
||||||
//
|
//
|
||||||
// Verify UEFI GUID type.
|
// Verify UEFI GUID type.
|
||||||
//
|
//
|
||||||
if (!HashPeImage (HASHALG_SHA256)) {
|
if (!HashPeImage (HASHALG_SHA256)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -1295,7 +1311,7 @@ DxeImageVerificationHandler (
|
||||||
// Verify Pkcs signed data type.
|
// Verify Pkcs signed data type.
|
||||||
//
|
//
|
||||||
Status = HashPeImageByType();
|
Status = HashPeImageByType();
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1306,11 +1322,15 @@ DxeImageVerificationHandler (
|
||||||
// no need to check image's hash in the allowed database.
|
// no need to check image's hash in the allowed database.
|
||||||
//
|
//
|
||||||
if (!EFI_ERROR (VerifyStatus)) {
|
if (!EFI_ERROR (VerifyStatus)) {
|
||||||
return EFI_SUCCESS;
|
if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return EFI_ACCESS_DENIED;
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
goto Done;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Get image hash value as executable's signature.
|
// Get image hash value as executable's signature.
|
||||||
|
@ -1334,8 +1354,17 @@ DxeImageVerificationHandler (
|
||||||
//
|
//
|
||||||
// Verification failure.
|
// Verification failure.
|
||||||
//
|
//
|
||||||
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
|
if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize) &&
|
||||||
Status = EFI_ACCESS_DENIED;
|
IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
|
||||||
|
//
|
||||||
|
// Verification fail, Image Hash is not in forbidden database (DBX),
|
||||||
|
// and Image Hash is in allowed database (DB).
|
||||||
|
//
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
} else {
|
||||||
|
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
|
||||||
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
} else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Signature->SignatureData, &mCertType, mImageDigestSize)) {
|
} else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Signature->SignatureData, &mCertType, mImageDigestSize)) {
|
||||||
//
|
//
|
||||||
// Executable signature verification passes, but is found in forbidden signature database.
|
// Executable signature verification passes, but is found in forbidden signature database.
|
||||||
|
@ -1375,10 +1404,10 @@ Done:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
When VariableWriteArchProtocol install, create "SecureBoot" variable.
|
When VariableWriteArchProtocol install, create "SecureBoot" variable.
|
||||||
|
|
||||||
@param[in] Event Event whose notification function is being invoked.
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
@param[in] Context Pointer to the notification function's context.
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
VOID
|
VOID
|
||||||
EFIAPI
|
EFIAPI
|
||||||
|
@ -1396,7 +1425,7 @@ VariableWriteCallBack (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check whether "SecureBoot" variable exists.
|
// Check whether "SecureBoot" variable exists.
|
||||||
// If this library is built-in, it means firmware has capability to perform
|
// If this library is built-in, it means firmware has capability to perform
|
||||||
|
@ -1418,7 +1447,7 @@ VariableWriteCallBack (
|
||||||
} else {
|
} else {
|
||||||
FreePool (SecureBootModePtr);
|
FreePool (SecureBootModePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Register security measurement handler.
|
Register security measurement handler.
|
||||||
|
@ -1439,7 +1468,7 @@ DxeImageVerificationLibConstructor (
|
||||||
|
|
||||||
//
|
//
|
||||||
// Register callback function upon VariableWriteArchProtocol.
|
// Register callback function upon VariableWriteArchProtocol.
|
||||||
//
|
//
|
||||||
EfiCreateProtocolNotifyEvent (
|
EfiCreateProtocolNotifyEvent (
|
||||||
&gEfiVariableWriteArchProtocolGuid,
|
&gEfiVariableWriteArchProtocolGuid,
|
||||||
TPL_CALLBACK,
|
TPL_CALLBACK,
|
||||||
|
@ -1451,5 +1480,5 @@ DxeImageVerificationLibConstructor (
|
||||||
return RegisterSecurityHandler (
|
return RegisterSecurityHandler (
|
||||||
DxeImageVerificationHandler,
|
DxeImageVerificationHandler,
|
||||||
EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
|
EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue