/** @file\r
Implement image verification services for secure boot service in UEFI2.3.1.\r
\r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
UINTN mImageSize;\r
-UINT32 mPeCoffHeaderOffset; \r
+UINT32 mPeCoffHeaderOffset;\r
UINT8 mImageDigest[MAX_DIGEST_SIZE];\r
UINTN mImageDigestSize;\r
EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;\r
Get the image type.\r
\r
@param[in] File This is a pointer to the device path of the file that is\r
- being dispatched. \r
+ being dispatched.\r
\r
- @return UINT32 Image Type \r
+ @return UINT32 Image Type\r
\r
**/\r
UINT32\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_HANDLE DeviceHandle; \r
+ EFI_HANDLE DeviceHandle;\r
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
\r
// First check to see if File is from a Firmware Volume\r
//\r
DeviceHandle = NULL;\r
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;\r
Status = gBS->LocateDevicePath (\r
&gEfiFirmwareVolume2ProtocolGuid,\r
&TempDevicePath,\r
// Next check to see if File is from a Block I/O device\r
//\r
DeviceHandle = NULL;\r
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;\r
Status = gBS->LocateDevicePath (\r
&gEfiBlockIoProtocolGuid,\r
&TempDevicePath,\r
}\r
\r
//\r
- // File is not in a Firmware Volume or on a Block I/O device, so check to see if \r
+ // File is not in a Firmware Volume or on a Block I/O device, so check to see if\r
// the device path supports the Simple File System Protocol.\r
//\r
DeviceHandle = NULL;\r
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;\r
Status = gBS->LocateDevicePath (\r
&gEfiSimpleFileSystemProtocolGuid,\r
&TempDevicePath,\r
\r
//\r
// File is not from an FV, Block I/O or Simple File System, so the only options\r
- // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC. \r
+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.\r
//\r
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) File;\r
while (!IsDevicePathEndType (TempDevicePath)) {\r
switch (DevicePathType (TempDevicePath)) {\r
- \r
+\r
case MEDIA_DEVICE_PATH:\r
if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {\r
return IMAGE_FROM_OPTION_ROM;\r
case MESSAGING_DEVICE_PATH:\r
if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {\r
return IMAGE_FROM_REMOVABLE_MEDIA;\r
- } \r
+ }\r
break;\r
\r
default:\r
}\r
TempDevicePath = NextDevicePathNode (TempDevicePath);\r
}\r
- return IMAGE_UNKNOWN; \r
+ return IMAGE_UNKNOWN;\r
}\r
\r
/**\r
PE/COFF Specification 8.0 Appendix A\r
\r
@param[in] HashAlg Hash algorithm type.\r
- \r
+\r
@retval TRUE Successfully hash image.\r
@retval FALSE Fail in hash image.\r
\r
**/\r
-BOOLEAN \r
+BOOLEAN\r
HashPeImage (\r
IN UINT32 HashAlg\r
)\r
UINTN Index;\r
UINTN Pos;\r
UINTN SumOfSectionBytes;\r
- EFI_IMAGE_SECTION_HEADER *SectionCache; \r
- \r
+ EFI_IMAGE_SECTION_HEADER *SectionCache;\r
+\r
HashCtx = NULL;\r
SectionHeader = NULL;\r
Status = FALSE;\r
if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
return FALSE;\r
}\r
- \r
+\r
//\r
// Initialize context of hash.\r
//\r
}\r
\r
CtxSize = mHash[HashAlg].GetContextSize();\r
- \r
+\r
HashCtx = AllocatePool (CtxSize);\r
if (HashCtx == NULL) {\r
return FALSE;\r
\r
// 2. Initialize a SHA hash context.\r
Status = mHash[HashAlg].HashInit(HashCtx);\r
- \r
+\r
if (!Status) {\r
goto Done;\r
}\r
} else {\r
//\r
// Use PE32+ offset.\r
- // \r
+ //\r
HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
}\r
for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) {\r
SumOfSectionBytes += SectionCache->SizeOfRawData;\r
}\r
- \r
+\r
//\r
// Sanity check for file corruption. Sections raw data size should be smaller\r
// than Image Size.\r
HashSize = (UINTN)(\r
mImageSize -\r
mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
- SumOfBytesHashed); \r
+ SumOfBytesHashed);\r
}\r
\r
Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
}\r
\r
/**\r
- Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of \r
- Pe/Coff image based on the authenticode image hashing in PE/COFF Specification \r
+ Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of\r
+ Pe/Coff image based on the authenticode image hashing in PE/COFF Specification\r
8.0 Appendix A\r
\r
@retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
@retval EFI_SUCCESS Hash successfully.\r
\r
**/\r
-EFI_STATUS \r
+EFI_STATUS\r
HashPeImageByType (\r
VOID\r
)\r
\r
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
\r
- for (Index = 0; Index < HASHALG_MAX; Index++) { \r
+ for (Index = 0; Index < HASHALG_MAX; Index++) {\r
//\r
// Check the Hash algorithm in PE/COFF Authenticode.\r
- // According to PKCS#7 Definition: \r
+ // According to PKCS#7 Definition:\r
// SignedData ::= SEQUENCE {\r
// version Version,\r
// digestAlgorithms DigestAlgorithmIdentifiers,\r
// .... }\r
// The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
// This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
- // \r
+ // Fixed offset (+32) is calculated based on two bytes of length encoding.\r
+ //\r
+ if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
+ //\r
+ // Only support two bytes of Long Form of Length Encoding.\r
+ //\r
+ continue;\r
+ }\r
+\r
if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
break;\r
}\r
ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.\r
\r
@param ImageExeInfoTable A pointer to a image execution info table structure.\r
- \r
+\r
@retval 0 If ImageExeInfoTable is NULL.\r
@retval Others The size of a image execution info table in bytes.\r
\r
@param[in] DevicePath Input device path pointer.\r
@param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.\r
@param[in] SignatureSize Size of signature.\r
- \r
+\r
**/\r
VOID\r
AddImageExeInfo (\r
- IN EFI_IMAGE_EXECUTION_ACTION Action, \r
- IN CHAR16 *Name OPTIONAL, \r
+ IN EFI_IMAGE_EXECUTION_ACTION Action,\r
+ IN CHAR16 *Name OPTIONAL,\r
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
IN EFI_SIGNATURE_LIST *Signature OPTIONAL,\r
IN UINTN SignatureSize\r
if (DevicePath == NULL) {\r
return ;\r
}\r
- \r
+\r
if (Name != NULL) {\r
NameStringLen = StrSize (Name);\r
}\r
\r
ImageExeInfoTable = NULL;\r
- EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID**)&ImageExeInfoTable);\r
+ EfiGetSystemConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID **) &ImageExeInfoTable);\r
if (ImageExeInfoTable != NULL) {\r
//\r
// The table has been found!\r
// Update/replace the image execution table.\r
//\r
gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);\r
- \r
+\r
//\r
// Free Old table data!\r
//\r
/**\r
Discover if the UEFI image is authorized by user's policy setting.\r
\r
- @param[in] Policy Specify platform's policy setting. \r
+ @param[in] Policy Specify platform's policy setting.\r
\r
@retval EFI_ACCESS_DENIED Image is not allowed to run.\r
@retval EFI_SECURITY_VIOLATION Image is deferred.\r
Status = EFI_ACCESS_DENIED;\r
\r
switch (Policy) {\r
- \r
+\r
case QUERY_USER_ON_SECURITY_VIOLATION:\r
do {\r
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, mNotifyString1, mNotifyString2, NULL);\r
BOOLEAN\r
IsSignatureFoundInDatabase (\r
IN CHAR16 *VariableName,\r
- IN UINT8 *Signature, \r
+ IN UINT8 *Signature,\r
IN EFI_GUID *CertType,\r
IN UINTN SignatureSize\r
)\r
}\r
\r
/**\r
- Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format .\r
+ Verify PKCS#7 SignedData using certificate found in Variable which formatted\r
+ as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.\r
\r
- @retval EFI_SUCCESS Image pass verification.\r
- @retval EFI_SECURITY_VIOLATION Image fail verification.\r
- @retval EFI_OUT_OF_RESOURCE Fail to allocate memory.\r
+ @param VariableName Name of Variable to search for Certificate.\r
+ @param VendorGuid Variable vendor GUID.\r
+\r
+ @retval TRUE Image pass verification.\r
+ @retval FALSE Image fail verification.\r
\r
**/\r
-EFI_STATUS \r
-VerifyCertPkcsSignedData (\r
- VOID\r
+BOOLEAN\r
+IsPkcsSignedDataVerifiedBySignatureList (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
)\r
{\r
EFI_STATUS Status;\r
EFI_SIGNATURE_LIST *CertList;\r
EFI_SIGNATURE_DATA *Cert;\r
UINTN DataSize;\r
- UINT8 *KekData;\r
- UINT8 *DbData;\r
+ UINT8 *Data;\r
UINT8 *RootCert;\r
UINTN RootCertSize;\r
UINTN Index;\r
UINTN CertCount;\r
\r
- KekData = NULL;\r
- DbData = NULL;\r
- CertList = NULL;\r
- Cert = NULL;\r
- RootCert = NULL;\r
- RootCertSize = 0;\r
- VerifyStatus = FALSE;\r
- PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
+ Data = NULL;\r
+ CertList = NULL;\r
+ Cert = NULL;\r
+ RootCert = NULL;\r
+ RootCertSize = 0;\r
+ VerifyStatus = FALSE;\r
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
\r
- //\r
- // 1: Find certificate from KEK database and try to verify authenticode struct.\r
- //\r
DataSize = 0;\r
- Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
+ Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
- KekData = (UINT8 *)AllocateZeroPool (DataSize);\r
- if (KekData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+ if (Data == NULL) {\r
+ return VerifyStatus;\r
}\r
\r
- Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, (VOID *)KekData);\r
+ Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
- \r
+\r
+ //\r
+ // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.\r
//\r
- // Find Cert Enrolled in KEK database to verify the signature in pkcs7 signed data.\r
- // \r
- CertList = (EFI_SIGNATURE_LIST *) KekData;\r
+ CertList = (EFI_SIGNATURE_LIST *) Data;\r
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
for (Index = 0; Index < CertCount; Index++) {\r
//\r
- // Iterate each Signature Data Node within this CertList for a verify\r
- // \r
+ // Iterate each Signature Data Node within this CertList for verify.\r
+ //\r
RootCert = Cert->SignatureData;\r
RootCertSize = CertList->SignatureSize;\r
- \r
+\r
//\r
- // Call AuthenticodeVerify library to Verify Authenticode struct. \r
+ // Call AuthenticodeVerify library to Verify Authenticode struct.\r
//\r
VerifyStatus = AuthenticodeVerify (\r
PkcsCertData->CertData,\r
mImageDigest,\r
mImageDigestSize\r
);\r
- \r
if (VerifyStatus) {\r
goto Done;\r
}\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
- } \r
+ }\r
}\r
DataSize -= CertList->SignatureListSize;\r
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
}\r
}\r
\r
- \r
+Done:\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
\r
- //\r
- // 2: Find certificate from DB database and try to verify authenticode struct.\r
- //\r
- DataSize = 0;\r
- Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- DbData = (UINT8 *)AllocateZeroPool (DataSize);\r
- if (DbData == NULL) {\r
- goto Done;\r
- }\r
+ return VerifyStatus;\r
+}\r
\r
- Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)DbData);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
+/**\r
+ Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.\r
\r
- //\r
- // Find Cert Enrolled in DB database to verify the signature in pkcs7 signed data.\r
- // \r
- CertList = (EFI_SIGNATURE_LIST *) DbData;\r
- while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
- if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
- Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
- for (Index = 0; Index < CertCount; Index++) {\r
- //\r
- // Iterate each Signature Data Node within this CertList for a verify\r
- // \r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize;\r
- \r
- //\r
- // Call AuthenticodeVerify library to Verify Authenticode struct. \r
- //\r
- VerifyStatus = AuthenticodeVerify (\r
- PkcsCertData->CertData,\r
- mSecDataDir->Size - sizeof(PkcsCertData->Hdr),\r
- RootCert,\r
- RootCertSize,\r
- mImageDigest,\r
- mImageDigestSize\r
- );\r
- \r
- if (VerifyStatus) {\r
- goto Done;\r
- }\r
- Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
- } \r
- }\r
- DataSize -= CertList->SignatureListSize;\r
- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
- }\r
- }\r
+ @retval EFI_SUCCESS Image pass verification.\r
+ @retval EFI_SECURITY_VIOLATION Image fail verification.\r
\r
-Done:\r
- if (KekData != NULL) {\r
- FreePool (KekData);\r
+**/\r
+EFI_STATUS\r
+VerifyCertPkcsSignedData (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // 1: Find certificate from DBX forbidden database for revoked certificate.\r
+ //\r
+ if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
+ //\r
+ // DBX is forbidden database, if Authenticode verification pass with\r
+ // one of the certificate in DBX, this image should be rejected.\r
+ //\r
+ return EFI_SECURITY_VIOLATION;\r
}\r
\r
- if (DbData != NULL) {\r
- FreePool (DbData);\r
+ //\r
+ // 2: Find certificate from KEK database and try to verify authenticode struct.\r
+ //\r
+ if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid)) {\r
+ return EFI_SUCCESS;\r
}\r
\r
- if (VerifyStatus) {\r
+ //\r
+ // 3: Find certificate from DB database and try to verify authenticode struct.\r
+ //\r
+ if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
return EFI_SUCCESS;\r
} else {\r
return EFI_SECURITY_VIOLATION;\r
}\r
\r
/**\r
- Verify certificate in WIN_CERTIFICATE_UEFI_GUID format. \r
+ Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.\r
\r
@retval EFI_SUCCESS Image pass verification.\r
@retval EFI_SECURITY_VIOLATION Image fail verification.\r
@retval other error value\r
\r
**/\r
-EFI_STATUS \r
+EFI_STATUS\r
VerifyCertUefiGuid (\r
VOID\r
)\r
if (KekList == NULL) {\r
return EFI_SECURITY_VIOLATION;\r
}\r
- \r
+\r
//\r
// Enumerate all Kek items in this list to verify the variable certificate data.\r
// If anyone is authenticated successfully, it means the variable is correct!\r
KekDataSize -= KekList->SignatureListSize;\r
KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);\r
}\r
- \r
+\r
if (!IsFound) {\r
//\r
// Signed key is not a trust one.\r
Status = FALSE;\r
goto Done;\r
}\r
- \r
- // \r
+\r
+ //\r
// Set RSA Key Components.\r
// NOTE: Only N and E are needed to be set as RSA public key for signature verification.\r
//\r
// Verify the signature.\r
//\r
Status = RsaPkcs1Verify (\r
- Rsa, \r
- mImageDigest, \r
- mImageDigestSize, \r
- CertBlock->Signature, \r
+ Rsa,\r
+ mImageDigest,\r
+ mImageDigestSize,\r
+ CertBlock->Signature,\r
EFI_CERT_TYPE_RSA2048_SHA256_SIZE\r
);\r
- \r
+\r
Done:\r
if (KekList != NULL) {\r
FreePool (KekList);\r
\r
/**\r
Provide verification service for signed images, which include both signature validation\r
- and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and \r
+ and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and\r
MSFT Authenticode type signatures are supported.\r
- \r
- In this implementation, only verify external executables when in USER MODE.\r
- Executables from FV is bypass, so pass in AuthenticationStatus is ignored. \r
\r
- @param[in] AuthenticationStatus \r
+ In this implementation, only verify external executables when in USER MODE.\r
+ Executables from FV is bypass, so pass in AuthenticationStatus is ignored.\r
+\r
+ The image verification process is:\r
+ Is the Image signed?\r
+ If yes,\r
+ Does the image verify against a certificate (root or intermediate) in the allowed db?\r
+ Run it\r
+ Image verification fail\r
+ Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?\r
+ Run it\r
+ If no,\r
+ Is the Image's Hash in the forbidden database (DBX)?\r
+ if yes,\r
+ Error out\r
+ Is the Image's Hash in the allowed database (DB)?\r
+ If yes,\r
+ Run it\r
+ If no,\r
+ Error out\r
+\r
+ @param[in] AuthenticationStatus\r
This is the authentication status returned from the security\r
measurement services for the input file.\r
@param[in] File This is a pointer to the device path of the file that is\r
IN VOID *FileBuffer,\r
IN UINTN FileSize\r
)\r
-\r
{\r
EFI_STATUS Status;\r
UINT16 Magic;\r
EFI_IMAGE_EXECUTION_ACTION Action;\r
WIN_CERTIFICATE *WinCertificate;\r
UINT32 Policy;\r
+ UINT8 *SecureBootEnable;\r
\r
if (File == NULL) {\r
return EFI_INVALID_PARAMETER;\r
// Check the image type and get policy setting.\r
//\r
switch (GetImageType (File)) {\r
- \r
+\r
case IMAGE_FROM_FV:\r
Policy = ALWAYS_EXECUTE;\r
break;\r
break;\r
\r
default:\r
- Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION; \r
+ Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;\r
break;\r
}\r
//\r
} else if (Policy == NEVER_EXECUTE) {\r
return EFI_ACCESS_DENIED;\r
}\r
+\r
+ SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
+ //\r
+ // Skip verification if SecureBootEnable variable doesn't exist.\r
+ //\r
+ if (SecureBootEnable == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Skip verification if SecureBootEnable is disabled.\r
+ //\r
+ if (*SecureBootEnable == SECURE_BOOT_DISABLE) {\r
+ FreePool (SecureBootEnable);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);\r
\r
//\r
}\r
mImageBase = (UINT8 *) FileBuffer;\r
mImageSize = FileSize;\r
- DosHdr = (EFI_IMAGE_DOS_HEADER *) (mImageBase);\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;\r
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
//\r
- // DOS image header is present, \r
+ // DOS image header is present,\r
// so read the PE header after the DOS image header.\r
//\r
mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
//\r
// Use PE32 offset.\r
//\r
- mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+ mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
} else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
//\r
// Use PE32+ offset.\r
//\r
- mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+ mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
} else {\r
//\r
// Invalid header magic number.\r
//\r
// This image is not signed.\r
//\r
+ if (!HashPeImage (HASHALG_SHA256)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+ //\r
+ // Image Hash is in forbidden database (DBX).\r
+ //\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Done;\r
+ }\r
+\r
+ if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
+ //\r
+ // Image Hash is in allowed database (DB).\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Image Hash is not found in both forbidden and allowed database.\r
+ //\r
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
- Status = EFI_ACCESS_DENIED; \r
- goto Done; \r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Done;\r
}\r
+\r
//\r
// Verify signature of executables.\r
//\r
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
\r
switch (WinCertificate->wCertificateType) {\r
- \r
+\r
case WIN_CERT_TYPE_EFI_GUID:\r
//\r
// Verify UEFI GUID type.\r
- // \r
+ //\r
if (!HashPeImage (HASHALG_SHA256)) {\r
goto Done;\r
}\r
// Verify Pkcs signed data type.\r
//\r
Status = HashPeImageByType();\r
- if (EFI_ERROR(Status)) {\r
+ if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
\r
// no need to check image's hash in the allowed database.\r
//\r
if (!EFI_ERROR (VerifyStatus)) {\r
- return EFI_SUCCESS;\r
+ if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
+ break;\r
\r
default:\r
- return EFI_ACCESS_DENIED;\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Done;\r
}\r
//\r
// Get image hash value as executable's signature.\r
//\r
// Verification failure.\r
//\r
- Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
- Status = EFI_ACCESS_DENIED;\r
+ if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize) &&\r
+ IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
+ //\r
+ // Verification fail, Image Hash is not in forbidden database (DBX),\r
+ // and Image Hash is in allowed database (DB).\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
+ Status = EFI_ACCESS_DENIED;\r
+ }\r
} else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Signature->SignatureData, &mCertType, mImageDigestSize)) {\r
//\r
// Executable signature verification passes, but is found in forbidden signature database.\r
\r
/**\r
When VariableWriteArchProtocol install, create "SecureBoot" variable.\r
- \r
+\r
@param[in] Event Event whose notification function is being invoked.\r
@param[in] Context Pointer to the notification function's context.\r
- \r
+\r
**/\r
VOID\r
EFIAPI\r
if (EFI_ERROR (Status)) {\r
return;\r
}\r
- \r
+\r
//\r
// Check whether "SecureBoot" variable exists.\r
// If this library is built-in, it means firmware has capability to perform\r
} else {\r
FreePool (SecureBootModePtr);\r
}\r
-} \r
+}\r
\r
/**\r
Register security measurement handler.\r
\r
//\r
// Register callback function upon VariableWriteArchProtocol.\r
- // \r
+ //\r
EfiCreateProtocolNotifyEvent (\r
&gEfiVariableWriteArchProtocolGuid,\r
TPL_CALLBACK,\r
return RegisterSecurityHandler (\r
DxeImageVerificationHandler,\r
EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
- ); \r
+ );\r
}\r