]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
SecurityPkg/DxeImageVerificationLib: Differentiate error/search result (2) (CVE-2019...
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 8cedb1bfb0a3e04ac3944ec4d837a4c9d1abfcc5..0e1587bc3c3c3ca8c0b5f7860e33aaeaa73687e7 100644 (file)
   DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept\r
   untrusted PE/COFF image and validate its data structure within this image buffer before use.\r
 \r
-Copyright (c) 2009 - 2016, 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
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -71,6 +66,8 @@ HASH_TABLE mHash[] = {
   { L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
 };\r
 \r
+EFI_STRING mHashTypeStr;\r
+\r
 /**\r
   SecureBoot Hook for processing image verification.\r
 \r
@@ -277,6 +274,9 @@ GetImageType (
   PE/COFF image is external input, so this function will validate its data structure\r
   within this image buffer before use.\r
 \r
+  Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in\r
+  its caller function DxeImageVerificationHandler().\r
+\r
   @param[in]    HashAlg   Hash algorithm type.\r
 \r
   @retval TRUE            Successfully hash image.\r
@@ -289,7 +289,6 @@ HashPeImage (
   )\r
 {\r
   BOOLEAN                   Status;\r
-  UINT16                    Magic;\r
   EFI_IMAGE_SECTION_HEADER  *Section;\r
   VOID                      *HashCtx;\r
   UINTN                     CtxSize;\r
@@ -340,6 +339,7 @@ HashPeImage (
     return FALSE;\r
   }\r
 \r
+  mHashTypeStr = mHash[HashAlg].Name;\r
   CtxSize   = mHash[HashAlg].GetContextSize();\r
 \r
   HashCtx = AllocatePool (CtxSize);\r
@@ -360,37 +360,23 @@ HashPeImage (
   // Measuring PE/COFF Image Header;\r
   // But CheckSum field and SECURITY data directory (certificate) are excluded\r
   //\r
-  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
-    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
-    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
-    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
-    //\r
-    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-  } else {\r
-    //\r
-    // Get the magic value from the PE/COFF Optional Header\r
-    //\r
-    Magic =  mNtHeader.Pe32->OptionalHeader.Magic;\r
-  }\r
 \r
   //\r
   // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
   // 4.  Hash the image header from its base to beginning of the image checksum.\r
   //\r
   HashBase = mImageBase;\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset.\r
     //\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+    HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
     NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
-  } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+  } else if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
     //\r
     // Use PE32+ offset.\r
     //\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+    HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
     NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
   } else {\r
     //\r
@@ -413,18 +399,18 @@ HashPeImage (
     // 6.  Since there is no Cert Directory in optional header, hash everything\r
     //     from the end of the checksum to the end of image header.\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset.\r
       //\r
       HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
     } else {\r
       //\r
       // Use PE32+ offset.\r
       //\r
       HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
     }\r
 \r
     if (HashSize != 0) {\r
@@ -437,18 +423,18 @@ HashPeImage (
     //\r
     // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset.\r
       //\r
       HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+      HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
     } else {\r
       //\r
       // Use PE32+ offset.\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
+      HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
     }\r
 \r
     if (HashSize != 0) {\r
@@ -462,18 +448,18 @@ HashPeImage (
     // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
     // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
       HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
     } else {\r
       //\r
       // Use PE32+ offset.\r
       //\r
       HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
     }\r
 \r
     if (HashSize != 0) {\r
@@ -487,7 +473,7 @@ HashPeImage (
   //\r
   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
   //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset.\r
     //\r
@@ -570,7 +556,7 @@ HashPeImage (
     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
       CertSize = 0;\r
     } else {\r
-      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
         //\r
         // Use PE32 offset.\r
         //\r
@@ -711,58 +697,6 @@ GetImageExeInfoTableSize (
   return TotalSize;\r
 }\r
 \r
-/**\r
-  Create signature list based on input signature data and certificate type GUID. Caller is reposible \r
-  to free new created SignatureList.\r
-\r
-  @param[in]   SignatureData           Signature data in SignatureList.\r
-  @param[in]   SignatureDataSize       Signature data size.\r
-  @param[in]   CertType                Certificate Type.\r
-  @param[out]  SignatureList           Created SignatureList.\r
-  @param[out]  SignatureListSize       Created SignatureListSize.\r
-\r
-  @return EFI_OUT_OF_RESOURCES         The operation is failed due to lack of resources.\r
-  @retval EFI_SUCCESS          Successfully create signature list.\r
-\r
-**/\r
-EFI_STATUS\r
-CreateSignatureList(\r
-  IN UINT8                *SignatureData,\r
-  IN UINTN                SignatureDataSize,\r
-  IN EFI_GUID             *CertType,\r
-  OUT EFI_SIGNATURE_LIST  **SignatureList,\r
-  OUT UINTN               *SignatureListSize\r
-  )\r
-{\r
-  EFI_SIGNATURE_LIST   *SignList;\r
-  UINTN                SignListSize;\r
-  EFI_SIGNATURE_DATA   *Signature;\r
-\r
-  SignList       = NULL;\r
-  *SignatureList = NULL;\r
-\r
-  SignListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureDataSize;\r
-  SignList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignListSize);\r
-  if (SignList == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  SignList->SignatureHeaderSize = 0;\r
-  SignList->SignatureListSize   = (UINT32) SignListSize;\r
-  SignList->SignatureSize       = (UINT32) SignatureDataSize + sizeof (EFI_SIGNATURE_DATA) - 1;\r
-  CopyMem (&SignList->SignatureType, CertType, sizeof (EFI_GUID));\r
-\r
-  DEBUG((EFI_D_INFO, "SignatureDataSize %x\n", SignatureDataSize));\r
-  Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignList + sizeof (EFI_SIGNATURE_LIST));\r
-  CopyMem (Signature->SignatureData, SignatureData, SignatureDataSize);\r
-\r
-  *SignatureList     = SignList;\r
-  *SignatureListSize = SignListSize;\r
-\r
-  return EFI_SUCCESS;\r
-\r
-}\r
-\r
 /**\r
   Create an Image Execution Information Table entry and add it to system configuration table.\r
 \r
@@ -770,7 +704,7 @@ CreateSignatureList(
   @param[in]  Name            Input a null-terminated, user-friendly name.\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
+  @param[in]  SignatureSize   Size of signature. Must be zero if Signature is NULL.\r
 \r
 **/\r
 VOID\r
@@ -811,7 +745,7 @@ AddImageExeInfo (
   if (ImageExeInfoTable != NULL) {\r
     //\r
     // The table has been found!\r
-    // We must enlarge the table to accomodate the new exe info entry.\r
+    // We must enlarge the table to accommodate the new exe info entry.\r
     //\r
     ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);\r
   } else {\r
@@ -827,6 +761,7 @@ AddImageExeInfo (
   //\r
   // Signature size can be odd. Pad after signature to ensure next EXECUTION_INFO entry align\r
   //\r
+  ASSERT (Signature != NULL || SignatureSize == 0);\r
   NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
 \r
   NewImageExeInfoTable      = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);\r
@@ -887,22 +822,23 @@ AddImageExeInfo (
   @param[in]  SignatureList     Pointer to the Signature List in forbidden database.\r
   @param[in]  SignatureListSize Size of Signature List.\r
   @param[out] RevocationTime    Return the time that the certificate was revoked.\r
+  @param[out] IsFound           Search result. Only valid if EFI_SUCCESS returned.\r
 \r
-  @return TRUE   The certificate hash is found in the forbidden database.\r
-  @return FALSE  The certificate hash is not found in the forbidden database.\r
+  @retval EFI_SUCCESS           Finished the search without any error.\r
+  @retval Others                Error occurred in the search of database.\r
 \r
 **/\r
-BOOLEAN\r
+EFI_STATUS\r
 IsCertHashFoundInDatabase (\r
   IN  UINT8               *Certificate,\r
   IN  UINTN               CertSize,\r
   IN  EFI_SIGNATURE_LIST  *SignatureList,\r
   IN  UINTN               SignatureListSize,\r
-  OUT EFI_TIME            *RevocationTime\r
+  OUT EFI_TIME            *RevocationTime,\r
+  OUT BOOLEAN             *IsFound\r
   )\r
 {\r
-  BOOLEAN             IsFound;\r
-  BOOLEAN             Status;\r
+  EFI_STATUS          Status;\r
   EFI_SIGNATURE_LIST  *DbxList;\r
   UINTN               DbxSize;\r
   EFI_SIGNATURE_DATA  *CertHash;\r
@@ -916,21 +852,22 @@ IsCertHashFoundInDatabase (
   UINT8               *TBSCert;\r
   UINTN               TBSCertSize;\r
 \r
-  IsFound  = FALSE;\r
+  Status   = EFI_ABORTED;\r
+  *IsFound = FALSE;\r
   DbxList  = SignatureList;\r
   DbxSize  = SignatureListSize;\r
   HashCtx  = NULL;\r
   HashAlg  = HASHALG_MAX;\r
 \r
   if ((RevocationTime == NULL) || (DbxList == NULL)) {\r
-    return FALSE;\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
   // Retrieve the TBSCertificate from the X.509 Certificate.\r
   //\r
   if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {\r
-    return FALSE;\r
+    return Status;\r
   }\r
 \r
   while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
@@ -960,19 +897,19 @@ IsCertHashFoundInDatabase (
     if (HashCtx == NULL) {\r
       goto Done;\r
     }\r
-    Status = mHash[HashAlg].HashInit (HashCtx);\r
-    if (!Status) {\r
+    if (!mHash[HashAlg].HashInit (HashCtx)) {\r
       goto Done;\r
     }\r
-    Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
-    if (!Status) {\r
+    if (!mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize)) {\r
       goto Done;\r
     }\r
-    Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);\r
-    if (!Status) {\r
+    if (!mHash[HashAlg].HashFinal (HashCtx, CertDigest)) {\r
       goto Done;\r
     }\r
 \r
+    FreePool (HashCtx);\r
+    HashCtx = NULL;\r
+\r
     SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;\r
     CertHash          = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);\r
     CertHashCount     = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;\r
@@ -985,7 +922,8 @@ IsCertHashFoundInDatabase (
         //\r
         // Hash of Certificate is found in forbidden database.\r
         //\r
-        IsFound = TRUE;\r
+        Status   = EFI_SUCCESS;\r
+        *IsFound = TRUE;\r
 \r
         //\r
         // Return the revocation time.\r
@@ -1000,12 +938,14 @@ IsCertHashFoundInDatabase (
     DbxList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
   }\r
 \r
+  Status = EFI_SUCCESS;\r
+\r
 Done:\r
   if (HashCtx != NULL) {\r
     FreePool (HashCtx);\r
   }\r
 \r
-  return IsFound;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1013,19 +953,21 @@ Done:
 \r
   @param[in]  VariableName        Name of database variable that is searched in.\r
   @param[in]  Signature           Pointer to signature that is searched for.\r
-  @param[in]  CertType            Pointer to hash algrithom.\r
+  @param[in]  CertType            Pointer to hash algorithm.\r
   @param[in]  SignatureSize       Size of Signature.\r
+  @param[out] IsFound             Search result. Only valid if EFI_SUCCESS returned\r
 \r
-  @return TRUE                    Found the signature in the variable database.\r
-  @return FALSE                   Not found the signature in the variable database.\r
+  @retval EFI_SUCCESS             Finished the search without any error.\r
+  @retval Others                  Error occurred in the search of database.\r
 \r
 **/\r
-BOOLEAN\r
+EFI_STATUS\r
 IsSignatureFoundInDatabase (\r
-  IN CHAR16             *VariableName,\r
-  IN UINT8              *Signature,\r
-  IN EFI_GUID           *CertType,\r
-  IN UINTN              SignatureSize\r
+  IN  CHAR16            *VariableName,\r
+  IN  UINT8             *Signature,\r
+  IN  EFI_GUID          *CertType,\r
+  IN  UINTN             SignatureSize,\r
+  OUT BOOLEAN           *IsFound\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1035,22 +977,28 @@ IsSignatureFoundInDatabase (
   UINT8               *Data;\r
   UINTN               Index;\r
   UINTN               CertCount;\r
-  BOOLEAN             IsFound;\r
 \r
   //\r
   // Read signature database variable.\r
   //\r
-  IsFound   = FALSE;\r
+  *IsFound  = FALSE;\r
   Data      = NULL;\r
   DataSize  = 0;\r
   Status    = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
   if (Status != EFI_BUFFER_TOO_SMALL) {\r
-    return FALSE;\r
+    if (Status == EFI_NOT_FOUND) {\r
+      //\r
+      // No database, no need to search.\r
+      //\r
+      Status = EFI_SUCCESS;\r
+    }\r
+\r
+    return Status;\r
   }\r
 \r
   Data = (UINT8 *) AllocateZeroPool (DataSize);\r
   if (Data == NULL) {\r
-    return FALSE;\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
@@ -1058,7 +1006,7 @@ IsSignatureFoundInDatabase (
     goto Done;\r
   }\r
   //\r
-  // Enumerate all signature data in SigDB to check if executable's signature exists.\r
+  // Enumerate all signature data in SigDB to check if signature exists for executable.\r
   //\r
   CertList = (EFI_SIGNATURE_LIST *) Data;\r
   while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
@@ -1070,15 +1018,20 @@ IsSignatureFoundInDatabase (
           //\r
           // Find the signature in database.\r
           //\r
-          IsFound = TRUE;\r
-          SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+          *IsFound = TRUE;\r
+          //\r
+          // Entries in UEFI_IMAGE_SECURITY_DATABASE that are used to validate image should be measured\r
+          //\r
+          if (StrCmp(VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) {\r
+            SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+          }\r
           break;\r
         }\r
 \r
         Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
       }\r
 \r
-      if (IsFound) {\r
+      if (*IsFound) {\r
         break;\r
       }\r
     }\r
@@ -1092,7 +1045,7 @@ Done:
     FreePool (Data);\r
   }\r
 \r
-  return IsFound;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1149,61 +1102,14 @@ IsTimeZero (
 }\r
 \r
 /**\r
-  Record multiple certificate list & verification state of a verified image to \r
-  IMAGE_EXECUTION_TABLE.\r
-\r
-  @param[in]  CertBuf              Certificate list buffer.\r
-  @param[in]  CertBufLength        Certificate list buffer.\r
-  @param[in]  Action               Certificate list action to be record.\r
-  @param[in]  ImageName            Image name.\r
-  @param[in]  ImageDevicePath      Image device path.\r
-\r
-**/\r
-VOID \r
-RecordCertListToImageExeuctionTable(\r
-  IN UINT8                          *CertBuf,\r
-  IN UINTN                           CertBufLength,\r
-  IN EFI_IMAGE_EXECUTION_ACTION      Action,\r
-  IN CHAR16                         *ImageName OPTIONAL,\r
-  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL\r
-  )\r
-{\r
-  UINT8               CertNumber;\r
-  UINT8               *CertPtr;\r
-  UINTN               Index;\r
-  UINT8               *Cert;\r
-  UINTN               CertSize;\r
-  EFI_STATUS          Status;\r
-  EFI_SIGNATURE_LIST  *SignatureList;\r
-  UINTN               SignatureListSize;\r
-\r
-  CertNumber = (UINT8) (*CertBuf);\r
-  CertPtr    = CertBuf + 1;\r
-  for (Index = 0; Index < CertNumber; Index++) {\r
-    CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);\r
-    Cert     = (UINT8 *)CertPtr + sizeof (UINT32);\r
-\r
-    //\r
-    // Record all cert in cert chain to be passed\r
-    //\r
-    Status = CreateSignatureList(Cert, CertSize, &gEfiCertX509Guid, &SignatureList, &SignatureListSize);\r
-    if (!EFI_ERROR(Status)) {\r
-      AddImageExeInfo (Action, ImageName, ImageDevicePath, SignatureList, SignatureListSize);\r
-      FreePool (SignatureList);\r
-    }\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Check whether the timestamp signature is valid and the signing time is also earlier than \r
+  Check whether the timestamp signature is valid and the signing time is also earlier than\r
   the revocation time.\r
 \r
   @param[in]  AuthData        Pointer to the Authenticode signature retrieved from signed image.\r
   @param[in]  AuthDataSize    Size of the Authenticode signature in bytes.\r
   @param[in]  RevocationTime  The time that the certificate was revoked.\r
 \r
-  @retval TRUE      Timestamp signature is valid and signing time is no later than the \r
+  @retval TRUE      Timestamp signature is valid and signing time is no later than the\r
                     revocation time.\r
   @retval FALSE     Timestamp signature is not valid or the signing time is later than the\r
                     revocation time.\r
@@ -1305,11 +1211,8 @@ Done:
   Check whether the image signature is forbidden by the forbidden database (dbx).\r
   The image is forbidden to load if any certificates for signing are revoked before signing time.\r
 \r
-  @param[in]  AuthData             Pointer to the Authenticode signature retrieved from the signed image.\r
-  @param[in]  AuthDataSize         Size of the Authenticode signature in bytes.\r
-  @param[in]  IsAuditMode          Whether system Secure Boot Mode is in AuditMode.\r
-  @param[in]  ImageName            Name of the image to verify.\r
-  @param[in]  ImageDevicePath      DevicePath of the image to verify.\r
+  @param[in]  AuthData      Pointer to the Authenticode signature retrieved from the signed image.\r
+  @param[in]  AuthDataSize  Size of the Authenticode signature in bytes.\r
 \r
   @retval TRUE              Image is forbidden by dbx.\r
   @retval FALSE             Image is not forbidden by dbx.\r
@@ -1317,15 +1220,13 @@ Done:
 **/\r
 BOOLEAN\r
 IsForbiddenByDbx (\r
-  IN UINT8                          *AuthData,\r
-  IN UINTN                          AuthDataSize,\r
-  IN BOOLEAN                        IsAuditMode,\r
-  IN CHAR16                         *ImageName OPTIONAL,\r
-  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL\r
+  IN UINT8                  *AuthData,\r
+  IN UINTN                  AuthDataSize\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   BOOLEAN                   IsForbidden;\r
+  BOOLEAN                   IsFound;\r
   UINT8                     *Data;\r
   UINTN                     DataSize;\r
   EFI_SIGNATURE_LIST        *CertList;\r
@@ -1344,14 +1245,10 @@ IsForbiddenByDbx (
   UINT8                     *Cert;\r
   UINTN                     CertSize;\r
   EFI_TIME                  RevocationTime;\r
-  UINT8                     *SignerCert;\r
-  UINTN                     SignerCertLength;\r
-  UINT8                     *UnchainCert;\r
-  UINTN                     UnchainCertLength;\r
   //\r
   // Variable Initialization\r
   //\r
-  IsForbidden       = FALSE;\r
+  IsForbidden       = TRUE;\r
   Data              = NULL;\r
   CertList          = NULL;\r
   CertData          = NULL;\r
@@ -1362,17 +1259,20 @@ IsForbiddenByDbx (
   BufferLength      = 0;\r
   TrustedCert       = NULL;\r
   TrustedCertLength = 0;\r
-  SignerCert        = NULL;\r
-  SignerCertLength  = 0;\r
-  UnchainCert       = NULL;\r
-  UnchainCertLength = 0;\r
 \r
   //\r
   // The image will not be forbidden if dbx can't be got.\r
   //\r
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+  ASSERT (EFI_ERROR (Status));\r
   if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      //\r
+      // Evidently not in dbx if the database doesn't exist.\r
+      //\r
+      IsForbidden = FALSE;\r
+    }\r
     return IsForbidden;\r
   }\r
   Data = (UINT8 *) AllocateZeroPool (DataSize);\r
@@ -1382,7 +1282,7 @@ IsForbiddenByDbx (
 \r
   Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
   if (EFI_ERROR (Status)) {\r
-    return IsForbidden;\r
+    goto Done;\r
   }\r
 \r
   //\r
@@ -1415,7 +1315,7 @@ IsForbiddenByDbx (
                         mImageDigestSize\r
                         );\r
         if (IsForbidden) {\r
-          SecureBootHook (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);\r
+          DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is forbidden by DBX.\n"));\r
           goto Done;\r
         }\r
 \r
@@ -1444,7 +1344,7 @@ IsForbiddenByDbx (
   //       UINT8  Certn[];\r
   //\r
   Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);\r
-  if ((BufferLength == 0) || (CertBuffer == NULL)) {\r
+  if ((BufferLength == 0) || (CertBuffer == NULL) || (*CertBuffer) == 0) {\r
     IsForbidden = TRUE;\r
     goto Done;\r
   }\r
@@ -1462,59 +1362,42 @@ IsForbiddenByDbx (
     //\r
     CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
 \r
-    if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
+    Status = IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime, &IsFound);\r
+    if (EFI_ERROR (Status)) {\r
       //\r
-      // Check the timestamp signature and signing time to determine if the image can be trusted.\r
+      // Error in searching dbx. Consider it as 'found'. RevocationTime might\r
+      // not be valid in such situation.\r
       //\r
       IsForbidden = TRUE;\r
+    } else if (IsFound) {\r
+      //\r
+      // Found Cert in dbx successfully. Check the timestamp signature and\r
+      // signing time to determine if the image can be trusted.\r
+      //\r
       if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {\r
         IsForbidden = FALSE;\r
         //\r
         // Pass DBT check. Continue to check other certs in image signer's cert list against DBX, DBT\r
         //\r
         continue;\r
+      } else {\r
+        IsForbidden = TRUE;\r
+        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
+        goto Done;\r
       }\r
-      goto Done;\r
     }\r
 \r
   }\r
 \r
-Done:\r
-  if (IsForbidden && IsAuditMode) {\r
-    Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength);\r
-\r
-    //\r
-    // Record all certs in image to be failed\r
-    //\r
-    if ((SignerCertLength != 0) && (SignerCert != NULL)) {\r
-      RecordCertListToImageExeuctionTable(\r
-        SignerCert,\r
-        SignerCertLength,\r
-        EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
-        ImageName,\r
-        ImageDevicePath\r
-        );\r
-    }\r
-\r
-    if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {\r
-      RecordCertListToImageExeuctionTable(\r
-        UnchainCert,\r
-        UnchainCertLength,\r
-        EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
-        ImageName,\r
-        ImageDevicePath\r
-        );\r
-    }\r
-  }\r
+  IsForbidden = FALSE;\r
 \r
+Done:\r
   if (Data != NULL) {\r
     FreePool (Data);\r
   }\r
 \r
   Pkcs7FreeSigners (CertBuffer);\r
   Pkcs7FreeSigners (TrustedCert);\r
-  Pkcs7FreeSigners (SignerCert);\r
-  Pkcs7FreeSigners (UnchainCert);\r
 \r
   return IsForbidden;\r
 }\r
@@ -1523,11 +1406,8 @@ Done:
 /**\r
   Check whether the image signature can be verified by the trusted certificates in DB database.\r
 \r
-  @param[in]  AuthData              Pointer to the Authenticode signature retrieved from signed image.\r
-  @param[in]  AuthDataSize          Size of the Authenticode signature in bytes.\r
-  @param[in]  IsAuditMode           Whether system Secure Boot Mode is in AuditMode.\r
-  @param[in]  ImageName             Name of the image to verify.\r
-  @param[in]  ImageDevicePath       DevicePath of the image to verify.\r
+  @param[in]  AuthData      Pointer to the Authenticode signature retrieved from signed image.\r
+  @param[in]  AuthDataSize  Size of the Authenticode signature in bytes.\r
 \r
   @retval TRUE         Image passed verification using certificate in db.\r
   @retval FALSE        Image didn't pass verification using certificate in db.\r
@@ -1535,15 +1415,13 @@ Done:
 **/\r
 BOOLEAN\r
 IsAllowedByDb (\r
-  IN UINT8                          *AuthData,\r
-  IN UINTN                          AuthDataSize,\r
-  IN BOOLEAN                        IsAuditMode,\r
-  IN CHAR16                         *ImageName OPTIONAL,\r
-  IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath OPTIONAL\r
+  IN UINT8              *AuthData,\r
+  IN UINTN              AuthDataSize\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   BOOLEAN                   VerifyStatus;\r
+  BOOLEAN                   IsFound;\r
   EFI_SIGNATURE_LIST        *CertList;\r
   EFI_SIGNATURE_DATA        *CertData;\r
   UINTN                     DataSize;\r
@@ -1555,10 +1433,6 @@ IsAllowedByDb (
   UINTN                     DbxDataSize;\r
   UINT8                     *DbxData;\r
   EFI_TIME                  RevocationTime;\r
-  UINT8                     *SignerCert;\r
-  UINTN                     SignerCertLength;\r
-  UINT8                     *UnchainCert;\r
-  UINTN                     UnchainCertLength;\r
 \r
   Data              = NULL;\r
   CertList          = NULL;\r
@@ -1567,86 +1441,126 @@ IsAllowedByDb (
   DbxData           = NULL;\r
   RootCertSize      = 0;\r
   VerifyStatus      = FALSE;\r
-  SignerCert        = NULL;\r
-  SignerCertLength  = 0;\r
-  UnchainCert       = NULL;\r
-  UnchainCertLength = 0;\r
 \r
+  //\r
+  // Fetch 'db' content. If 'db' doesn't exist or encounters problem to get the\r
+  // data, return not-allowed-by-db (FALSE).\r
+  //\r
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    Data = (UINT8 *) AllocateZeroPool (DataSize);\r
-    if (Data == NULL) {\r
-      return VerifyStatus;\r
+  ASSERT (EFI_ERROR (Status));\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return VerifyStatus;\r
+  }\r
+\r
+  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    return VerifyStatus;\r
+  }\r
+\r
+  Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'.\r
+  // If any other errors occured, no need to check 'db' but just return\r
+  // not-allowed-by-db (FALSE) to avoid bypass.\r
+  //\r
+  DbxDataSize = 0;\r
+  Status      = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);\r
+  ASSERT (EFI_ERROR (Status));\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    if (Status != EFI_NOT_FOUND) {\r
+      goto Done;\r
+    }\r
+    //\r
+    // 'dbx' does not exist. Continue to check 'db'.\r
+    //\r
+  } else {\r
+    //\r
+    // 'dbx' exists. Get its content.\r
+    //\r
+    DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize);\r
+    if (DbxData == NULL) {\r
+      goto Done;\r
     }\r
 \r
-    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);\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
-    CertList = (EFI_SIGNATURE_LIST *) Data;\r
-    while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
-      if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
-        CertData  = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-        CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+  //\r
+  // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.\r
+  //\r
+  CertList = (EFI_SIGNATURE_LIST *) Data;\r
+  while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+      CertData  = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+      CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
 \r
-        for (Index = 0; Index < CertCount; Index++) {\r
-          //\r
-          // Iterate each Signature Data Node within this CertList for verify.\r
-          //\r
-          RootCert     = CertData->SignatureData;\r
-          RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
+      for (Index = 0; Index < CertCount; Index++) {\r
+        //\r
+        // Iterate each Signature Data Node within this CertList for verify.\r
+        //\r
+        RootCert     = CertData->SignatureData;\r
+        RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
 \r
+        //\r
+        // Call AuthenticodeVerify library to Verify Authenticode struct.\r
+        //\r
+        VerifyStatus = AuthenticodeVerify (\r
+                         AuthData,\r
+                         AuthDataSize,\r
+                         RootCert,\r
+                         RootCertSize,\r
+                         mImageDigest,\r
+                         mImageDigestSize\r
+                         );\r
+        if (VerifyStatus) {\r
           //\r
-          // Call AuthenticodeVerify library to Verify Authenticode struct.\r
+          // The image is signed and its signature is found in 'db'.\r
           //\r
-          VerifyStatus = AuthenticodeVerify (\r
-                           AuthData,\r
-                           AuthDataSize,\r
-                           RootCert,\r
-                           RootCertSize,\r
-                           mImageDigest,\r
-                           mImageDigestSize\r
-                           );\r
-          if (VerifyStatus) {\r
+          if (DbxData != NULL) {\r
             //\r
             // Here We still need to check if this RootCert's Hash is revoked\r
             //\r
-            Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);\r
-            if (Status == EFI_BUFFER_TOO_SMALL) {\r
-              goto Done;\r
-            }\r
-            DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize);\r
-            if (DbxData == NULL) {\r
-              goto Done;\r
-            }\r
-\r
-            Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);\r
+            Status = IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime, &IsFound);\r
             if (EFI_ERROR (Status)) {\r
-              goto Done;\r
-            }\r
-\r
-            if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {\r
               //\r
-              // Check the timestamp signature and signing time to determine if the image can be trusted.\r
+              // Error in searching dbx. Consider it as 'found'. RevocationTime might\r
+              // not be valid in such situation.\r
+              //\r
+              VerifyStatus = FALSE;\r
+            } else if (IsFound) {\r
+              //\r
+              // Check the timestamp signature and signing time to determine if the RootCert can be trusted.\r
               //\r
               VerifyStatus = PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime);\r
+              if (!VerifyStatus) {\r
+                DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed and signature is accepted by DB, but its root cert failed the timestamp check.\n"));\r
+              }\r
             }\r
-\r
-            goto Done;\r
           }\r
 \r
-          CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+          //\r
+          // There's no 'dbx' to check revocation time against (must-be pass),\r
+          // or, there's revocation time found in 'dbx' and checked againt 'dbt'\r
+          // (maybe pass or fail, depending on timestamp compare result). Either\r
+          // way the verification job has been completed at this point.\r
+          //\r
+          goto Done;\r
         }\r
-      }\r
 \r
-      DataSize -= CertList->SignatureListSize;\r
-      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+        CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+      }\r
     }\r
+\r
+    DataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
   }\r
 \r
 Done:\r
@@ -1655,62 +1569,6 @@ Done:
     SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);\r
   }\r
 \r
-  if (IsAuditMode) {\r
-\r
-    Pkcs7GetCertificatesList(AuthData, AuthDataSize, &SignerCert, &SignerCertLength, &UnchainCert, &UnchainCertLength);\r
-    if (VerifyStatus) {\r
-      if ((SignerCertLength != 0) && (SignerCert != NULL)) {\r
-        //\r
-        // Record all cert in signer's cert chain to be passed\r
-        //\r
-        RecordCertListToImageExeuctionTable(\r
-          SignerCert,\r
-          SignerCertLength,\r
-          EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
-          ImageName,\r
-          ImageDevicePath\r
-          );\r
-      }\r
-\r
-      if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {\r
-        //\r
-        // Record all certs in unchained certificates lists to be failed\r
-        //\r
-        RecordCertListToImageExeuctionTable(\r
-          UnchainCert,\r
-          UnchainCertLength,\r
-          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
-          ImageName,\r
-          ImageDevicePath\r
-          );\r
-      }\r
-    } else {\r
-      //\r
-      // Record all certs in image to be failed\r
-      //\r
-      if ((SignerCertLength != 0) && (SignerCert != NULL)) {\r
-        RecordCertListToImageExeuctionTable(\r
-          SignerCert,\r
-          SignerCertLength,\r
-          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
-          ImageName,\r
-          ImageDevicePath\r
-          );\r
-      }\r
-\r
-      if ((UnchainCertLength != 0) && (UnchainCert != NULL)) {\r
-        RecordCertListToImageExeuctionTable(\r
-          UnchainCert,\r
-          UnchainCertLength,\r
-          EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED,\r
-          ImageName,\r
-          ImageDevicePath\r
-          );\r
-      }\r
-    }\r
-  }\r
-\r
-\r
   if (Data != NULL) {\r
     FreePool (Data);\r
   }\r
@@ -1718,20 +1576,16 @@ Done:
     FreePool (DbxData);\r
   }\r
 \r
-  Pkcs7FreeSigners (SignerCert);\r
-  Pkcs7FreeSigners (UnchainCert);\r
-\r
   return VerifyStatus;\r
 }\r
 \r
 /**\r
-  Provide verification service for signed images in AuditMode, which include both signature validation\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
-  MSFT Authenticode type signatures are supported. \r
+  MSFT Authenticode type signatures are supported.\r
 \r
-  In this implementation, only verify external executables when in AuditMode.\r
-  Executables from FV is bypass, so pass in AuthenticationStatus is ignored. Other authentication status\r
-  are record into IMAGE_EXECUTION_TABLE.\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 policy is:\r
     If the image is signed,\r
@@ -1755,16 +1609,26 @@ Done:
   @param[in]    FileSize   Size of File buffer matches the input file device path.\r
   @param[in]    BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
 \r
-  @retval EFI_SUCCESS            The authenticate info is sucessfully stored for the file \r
-                                 specified by DevicePath and non-NULL FileBuffer \r
+  @retval EFI_SUCCESS            The file specified by DevicePath and non-NULL\r
+                                 FileBuffer did authenticate, and the platform policy dictates\r
+                                 that the DXE Foundation may use the file.\r
+  @retval EFI_SUCCESS            The device path specified by NULL device path DevicePath\r
+                                 and non-NULL FileBuffer did authenticate, and the platform\r
+                                 policy dictates that the DXE Foundation may execute the image in\r
+                                 FileBuffer.\r
+  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
+                                 the platform policy dictates that File should be placed\r
+                                 in the untrusted state. The image has been added to the file\r
+                                 execution table.\r
   @retval EFI_ACCESS_DENIED      The file specified by File and FileBuffer did not\r
                                  authenticate, and the platform policy dictates that the DXE\r
-                                 Foundation many not use File.\r
+                                 Foundation may not use File. The image has\r
+                                 been added to the file execution table.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-ImageVerificationInAuditMode (\r
+DxeImageVerificationHandler (\r
   IN  UINT32                           AuthenticationStatus,\r
   IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
   IN  VOID                             *FileBuffer,\r
@@ -1772,13 +1636,15 @@ ImageVerificationInAuditMode (
   IN  BOOLEAN                          BootPolicy\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
-  UINT16                               Magic;\r
   EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  BOOLEAN                              IsVerified;\r
   EFI_SIGNATURE_LIST                   *SignatureList;\r
+  UINTN                                SignatureListSize;\r
+  EFI_SIGNATURE_DATA                   *Signature;\r
   EFI_IMAGE_EXECUTION_ACTION           Action;\r
   WIN_CERTIFICATE                      *WinCertificate;\r
   UINT32                               Policy;\r
+  UINT8                                *SecureBoot;\r
   PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
   UINT32                               NumberOfRvaAndSizes;\r
   WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;\r
@@ -1787,17 +1653,20 @@ ImageVerificationInAuditMode (
   UINTN                                AuthDataSize;\r
   EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;\r
   UINT32                               OffSet;\r
-  CHAR16                               *FilePathStr;\r
-  UINTN                                SignatureListSize;\r
+  CHAR16                               *NameStr;\r
+  RETURN_STATUS                        PeCoffStatus;\r
+  EFI_STATUS                           HashStatus;\r
+  EFI_STATUS                           DbStatus;\r
+  BOOLEAN                              IsFound;\r
 \r
   SignatureList     = NULL;\r
+  SignatureListSize = 0;\r
   WinCertificate    = NULL;\r
   SecDataDir        = NULL;\r
   PkcsCertData      = NULL;\r
-  FilePathStr       = NULL;\r
-  Action            = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED;\r
-  Status            = EFI_ACCESS_DENIED;\r
-\r
+  Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
+  IsVerified        = FALSE;\r
+  IsFound           = FALSE;\r
 \r
   //\r
   // Check the image type and get policy setting.\r
@@ -1824,28 +1693,14 @@ ImageVerificationInAuditMode (
     Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;\r
     break;\r
   }\r
-\r
   //\r
   // If policy is always/never execute, return directly.\r
   //\r
   if (Policy == ALWAYS_EXECUTE) {\r
     return EFI_SUCCESS;\r
   }\r
-\r
-  //\r
-  // Get Image Device Path Str\r
-  //\r
-  FilePathStr = ConvertDevicePathToText (File, FALSE, TRUE);\r
-\r
-  //\r
-  // Authentication failed because of (unspecified) firmware security policy\r
-  //\r
   if (Policy == NEVER_EXECUTE) {\r
-    //\r
-    // No signature, record FilePath/FilePathStr only\r
-    //\r
-    AddImageExeInfo (EFI_IMAGE_EXECUTION_POLICY_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED, FilePathStr, File, NULL, 0);\r
-    goto END;\r
+    return EFI_ACCESS_DENIED;\r
   }\r
 \r
   //\r
@@ -1857,12 +1712,28 @@ ImageVerificationInAuditMode (
     CpuDeadLoop ();\r
   }\r
 \r
+  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);\r
+  //\r
+  // Skip verification if SecureBoot variable doesn't exist.\r
+  //\r
+  if (SecureBoot == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Skip verification if SecureBoot is disabled but not AuditMode\r
+  //\r
+  if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
+    FreePool (SecureBoot);\r
+    return EFI_SUCCESS;\r
+  }\r
+  FreePool (SecureBoot);\r
+\r
   //\r
   // Read the Dos header.\r
   //\r
   if (FileBuffer == NULL) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto END;\r
+    return EFI_ACCESS_DENIED;\r
   }\r
 \r
   mImageBase  = (UINT8 *) FileBuffer;\r
@@ -1875,15 +1746,15 @@ ImageVerificationInAuditMode (
   //\r
   // Get information about the image being loaded\r
   //\r
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
-  if (EFI_ERROR (Status)) {\r
+  PeCoffStatus = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (RETURN_ERROR (PeCoffStatus)) {\r
     //\r
     // The information can't be got from the invalid PeImage\r
     //\r
-    goto END;\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: PeImage invalid. Cannot retrieve image information.\n"));\r
+    goto Failed;\r
   }\r
 \r
-\r
   DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;\r
   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
     //\r
@@ -1894,7 +1765,6 @@ ImageVerificationInAuditMode (
   } else {\r
     mPeCoffHeaderOffset = 0;\r
   }\r
-\r
   //\r
   // Check PE/COFF image.\r
   //\r
@@ -1903,26 +1773,11 @@ ImageVerificationInAuditMode (
     //\r
     // It is not a valid Pe/Coff file.\r
     //\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto END;\r
-  }\r
-\r
-  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
-    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
-    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
-    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
-    //\r
-    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-  } else {\r
-    //\r
-    // Get the magic value from the PE/COFF Optional Header\r
-    //\r
-    Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Not a valid PE/COFF image.\n"));\r
+    goto Failed;\r
   }\r
 \r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset.\r
     //\r
@@ -1949,31 +1804,44 @@ ImageVerificationInAuditMode (
     // and not be reflected in the security data base "dbx".\r
     //\r
     if (!HashPeImage (HASHALG_SHA256)) {\r
-      Status = EFI_ACCESS_DENIED;\r
-      goto END;\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHashTypeStr));\r
+      goto Failed;\r
     }\r
 \r
-    //\r
-    // Image Hash is in forbidden database (DBX).\r
-    //\r
-    if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+    DbStatus = IsSignatureFoundInDatabase (\r
+                 EFI_IMAGE_SECURITY_DATABASE1,\r
+                 mImageDigest,\r
+                 &mCertType,\r
+                 mImageDigestSize,\r
+                 &IsFound\r
+                 );\r
+    if (EFI_ERROR (DbStatus) || IsFound) {\r
+      //\r
+      // Image Hash is in forbidden database (DBX).\r
+      //\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));\r
+      goto Failed;\r
+    }\r
+\r
+    DbStatus = IsSignatureFoundInDatabase (\r
+                 EFI_IMAGE_SECURITY_DATABASE,\r
+                 mImageDigest,\r
+                 &mCertType,\r
+                 mImageDigestSize,\r
+                 &IsFound\r
+                 );\r
+    if (!EFI_ERROR (DbStatus) && IsFound) {\r
       //\r
       // Image Hash is in allowed database (DB).\r
       //\r
-      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
-        Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED;\r
-      }\r
+      return EFI_SUCCESS;\r
     }\r
 \r
     //\r
-    // Add HASH digest for image without signature\r
+    // Image Hash is not found in both forbidden and allowed database.\r
     //\r
-    Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize);\r
-    if (!EFI_ERROR(Status)) {\r
-      AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize);\r
-      FreePool (SignatureList);\r
-    }\r
-    goto END;\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));\r
+    goto Failed;\r
   }\r
 \r
   //\r
@@ -2024,473 +1892,110 @@ ImageVerificationInAuditMode (
       continue;\r
     }\r
 \r
-    Status = HashPeImageByType (AuthData, AuthDataSize);\r
-    if (EFI_ERROR (Status)) {\r
+    HashStatus = HashPeImageByType (AuthData, AuthDataSize);\r
+    if (EFI_ERROR (HashStatus)) {\r
       continue;\r
     }\r
 \r
-    Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED | EFI_IMAGE_EXECUTION_INITIALIZED;\r
-\r
     //\r
     // Check the digital signature against the revoked certificate in forbidden database (dbx).\r
-    // Check the digital signature against the valid certificate in allowed database (db).\r
     //\r
-    if (!IsForbiddenByDbx (AuthData, AuthDataSize, TRUE, FilePathStr, File)) {\r
-      IsAllowedByDb (AuthData, AuthDataSize, TRUE, FilePathStr, File);\r
-    }\r
-\r
-    //\r
-    // Check the image's hash value.\r
-    //\r
-    if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
-      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
-        Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED | EFI_IMAGE_EXECUTION_INITIALIZED; \r
-      }\r
-    }\r
-\r
-    //\r
-    // Add HASH digest for image with signature\r
-    //\r
-    Status = CreateSignatureList(mImageDigest, mImageDigestSize, &mCertType, &SignatureList, &SignatureListSize);\r
-\r
-    if (!EFI_ERROR(Status)) {\r
-      AddImageExeInfo (Action, FilePathStr, File, SignatureList, SignatureListSize);\r
-      FreePool (SignatureList);\r
-    } else {\r
-      goto END;\r
-    }\r
-  }\r
-\r
-\r
-  if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {\r
-    //\r
-    // The Size in Certificate Table or the attribute certicate table is corrupted.\r
-    //\r
-    Status = EFI_ACCESS_DENIED;\r
-  } else {\r
-    Status = EFI_SUCCESS;\r
-  }\r
-\r
-END:\r
-\r
-  if (FilePathStr != NULL) {\r
-    FreePool(FilePathStr);\r
-    FilePathStr = NULL;\r
-  }\r
-\r
-  return Status;\r
-}\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
-  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
-  The image verification policy is:\r
-    If the image is signed,\r
-      At least one valid signature or at least one hash value of the image must match a record\r
-      in the security database "db", and no valid signature nor any hash value of the image may\r
-      be reflected in the security database "dbx".\r
-    Otherwise, the image is not signed,\r
-      The SHA256 hash value of the image must match a record in the security database "db", and\r
-      not be reflected in the security data base "dbx".\r
-\r
-  Caution: This function may receive untrusted input.\r
-  PE/COFF image is external input, so this function will validate its data structure\r
-  within this image buffer before use.\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
-                           being dispatched. This will optionally be used for logging.\r
-  @param[in]    FileBuffer File buffer matches the input file device path.\r
-  @param[in]    FileSize   Size of File buffer matches the input file device path.\r
-  @param[in]    BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
-\r
-  @retval EFI_SUCCESS            The file specified by DevicePath and non-NULL\r
-                                 FileBuffer did authenticate, and the platform policy dictates\r
-                                 that the DXE Foundation may use the file.\r
-  @retval EFI_SUCCESS            The device path specified by NULL device path DevicePath\r
-                                 and non-NULL FileBuffer did authenticate, and the platform\r
-                                 policy dictates that the DXE Foundation may execute the image in\r
-                                 FileBuffer.\r
-  @retval EFI_OUT_RESOURCE       Fail to allocate memory.\r
-  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
-                                 the platform policy dictates that File should be placed\r
-                                 in the untrusted state. The image has been added to the file\r
-                                 execution table.\r
-  @retval EFI_ACCESS_DENIED      The file specified by File and FileBuffer did not\r
-                                 authenticate, and the platform policy dictates that the DXE\r
-                                 Foundation many not use File.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-DxeImageVerificationHandler (\r
-  IN  UINT32                           AuthenticationStatus,\r
-  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
-  IN  VOID                             *FileBuffer,\r
-  IN  UINTN                            FileSize,\r
-  IN  BOOLEAN                          BootPolicy\r
-  )\r
-{\r
-  EFI_STATUS                           Status;\r
-  UINT16                               Magic;\r
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
-  EFI_STATUS                           VerifyStatus;\r
-  EFI_SIGNATURE_LIST                   *SignatureList;\r
-  UINTN                                SignatureListSize;\r
-  EFI_SIGNATURE_DATA                   *Signature;\r
-  EFI_IMAGE_EXECUTION_ACTION           Action;\r
-  WIN_CERTIFICATE                      *WinCertificate;\r
-  UINT32                               Policy;\r
-  UINT8                                *VarData;\r
-  UINT8                                SecureBoot;\r
-  UINT8                                AuditMode;\r
-  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
-  UINT32                               NumberOfRvaAndSizes;\r
-  WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;\r
-  WIN_CERTIFICATE_UEFI_GUID            *WinCertUefiGuid;\r
-  UINT8                                *AuthData;\r
-  UINTN                                AuthDataSize;\r
-  EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;\r
-  UINT32                               OffSet;\r
-  CHAR16                               *NameStr;\r
-\r
-  SignatureList     = NULL;\r
-  SignatureListSize = 0;\r
-  WinCertificate    = NULL;\r
-  SecDataDir        = NULL;\r
-  PkcsCertData      = NULL;\r
-  Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
-  Status            = EFI_ACCESS_DENIED;\r
-  VerifyStatus      = EFI_ACCESS_DENIED;\r
-\r
-  GetEfiGlobalVariable2 (EFI_AUDIT_MODE_NAME, (VOID**)&VarData, NULL);\r
-  //\r
-  // Skip verification if AuditMode variable doesn't exist. AuditMode should always exist\r
-  //\r
-  if (VarData == NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-  AuditMode = *VarData;\r
-  FreePool(VarData);\r
-\r
-  if (AuditMode == AUDIT_MODE_ENABLE) {\r
-    return ImageVerificationInAuditMode(AuthenticationStatus, File, FileBuffer, FileSize, BootPolicy);\r
-  }\r
-\r
-  //\r
-  // Check the image type and get policy setting.\r
-  //\r
-  switch (GetImageType (File)) {\r
-\r
-  case IMAGE_FROM_FV:\r
-    Policy = ALWAYS_EXECUTE;\r
-    break;\r
-\r
-  case IMAGE_FROM_OPTION_ROM:\r
-    Policy = PcdGet32 (PcdOptionRomImageVerificationPolicy);\r
-    break;\r
-\r
-  case IMAGE_FROM_REMOVABLE_MEDIA:\r
-    Policy = PcdGet32 (PcdRemovableMediaImageVerificationPolicy);\r
-    break;\r
-\r
-  case IMAGE_FROM_FIXED_MEDIA:\r
-    Policy = PcdGet32 (PcdFixedMediaImageVerificationPolicy);\r
-    break;\r
-\r
-  default:\r
-    Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;\r
-    break;\r
-  }\r
-  //\r
-  // If policy is always/never execute, return directly.\r
-  //\r
-  if (Policy == ALWAYS_EXECUTE) {\r
-    return EFI_SUCCESS;\r
-  } else if (Policy == NEVER_EXECUTE) {\r
-    return EFI_ACCESS_DENIED;\r
-  }\r
-\r
-  //\r
-  // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION\r
-  // violates the UEFI spec and has been removed.\r
-  //\r
-  ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);\r
-  if (Policy == QUERY_USER_ON_SECURITY_VIOLATION || Policy == ALLOW_EXECUTE_ON_SECURITY_VIOLATION) {\r
-    CpuDeadLoop ();\r
-  }\r
-\r
-  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&VarData, NULL);\r
-  //\r
-  // Skip verification if SecureBoot variable doesn't exist.\r
-  //\r
-  if (VarData == NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-  SecureBoot = *VarData;\r
-  FreePool(VarData);\r
-\r
-  //\r
-  // Skip verification if SecureBoot is disabled but not AuditMode\r
-  //\r
-  if (SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // Read the Dos header.\r
-  //\r
-  if (FileBuffer == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  mImageBase  = (UINT8 *) FileBuffer;\r
-  mImageSize  = FileSize;\r
-\r
-  ZeroMem (&ImageContext, sizeof (ImageContext));\r
-  ImageContext.Handle    = (VOID *) FileBuffer;\r
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;\r
-\r
-  //\r
-  // Get information about the image being loaded\r
-  //\r
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // The information can't be got from the invalid PeImage\r
-    //\r
-    goto Done;\r
-  }\r
-\r
-  Status = EFI_ACCESS_DENIED;\r
-\r
-  DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;\r
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
-    //\r
-    // DOS image header is present,\r
-    // so read the PE header after the DOS image header.\r
-    //\r
-    mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
-  } else {\r
-    mPeCoffHeaderOffset = 0;\r
-  }\r
-  //\r
-  // Check PE/COFF image.\r
-  //\r
-  mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);\r
-  if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
-    //\r
-    // It is not a valid Pe/Coff file.\r
-    //\r
-    goto Done;\r
-  }\r
-\r
-  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
-    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
-    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
-    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
-    //\r
-    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-  } else {\r
-    //\r
-    // Get the magic value from the PE/COFF Optional Header\r
-    //\r
-    Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
-  }\r
-\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset.\r
-    //\r
-    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
-    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
-      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
-    }\r
-  } else {\r
-    //\r
-    // Use PE32+ offset.\r
-    //\r
-    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
-    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
-      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
-    }\r
-  }\r
-\r
-  //\r
-  // Start Image Validation.\r
-  //\r
-  if (SecDataDir == NULL || SecDataDir->Size == 0) {\r
-    //\r
-    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",\r
-    // and not be reflected in the security data base "dbx".\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
-      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
-    goto Done;\r
-  }\r
-\r
-  //\r
-  // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7\r
-  // "Attribute Certificate Table".\r
-  // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.\r
-  //\r
-  for (OffSet = SecDataDir->VirtualAddress;\r
-       OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);\r
-       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {\r
-    WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);\r
-    if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||\r
-        (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {\r
-      break;\r
-    }\r
-\r
-    //\r
-    // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.\r
-    //\r
-    if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
-      //\r
-      // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the\r
-      // Authenticode specification.\r
-      //\r
-      PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;\r
-      if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {\r
-        break;\r
-      }\r
-      AuthData   = PkcsCertData->CertData;\r
-      AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);\r
-    } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
-      //\r
-      // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.\r
-      //\r
-      WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;\r
-      if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {\r
-        break;\r
-      }\r
-      if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {\r
-        continue;\r
-      }\r
-      AuthData = WinCertUefiGuid->CertData;\r
-      AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);\r
-    } else {\r
-      if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {\r
-        break;\r
-      }\r
-      continue;\r
-    }\r
-\r
-    Status = HashPeImageByType (AuthData, AuthDataSize);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    //\r
-    // Check the digital signature against the revoked certificate in forbidden database (dbx).\r
-    //\r
-    if (IsForbiddenByDbx (AuthData, AuthDataSize, FALSE, NULL, NULL)) {\r
-      Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
-      VerifyStatus = EFI_ACCESS_DENIED;\r
-      break;\r
+    if (IsForbiddenByDbx (AuthData, AuthDataSize)) {\r
+      Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
+      IsVerified = FALSE;\r
+      break;\r
     }\r
 \r
     //\r
     // Check the digital signature against the valid certificate in allowed database (db).\r
     //\r
-    if (EFI_ERROR (VerifyStatus)) {\r
-      if (IsAllowedByDb (AuthData, AuthDataSize, FALSE, NULL, NULL)) {\r
-        VerifyStatus = EFI_SUCCESS;\r
+    if (!IsVerified) {\r
+      if (IsAllowedByDb (AuthData, AuthDataSize)) {\r
+        IsVerified = TRUE;\r
       }\r
     }\r
 \r
     //\r
     // Check the image's hash value.\r
     //\r
-    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+    DbStatus = IsSignatureFoundInDatabase (\r
+                 EFI_IMAGE_SECURITY_DATABASE1,\r
+                 mImageDigest,\r
+                 &mCertType,\r
+                 mImageDigestSize,\r
+                 &IsFound\r
+                 );\r
+    if (EFI_ERROR (DbStatus) || IsFound) {\r
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;\r
-      VerifyStatus = EFI_ACCESS_DENIED;\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s hash of image is found in DBX.\n", mHashTypeStr));\r
+      IsVerified = FALSE;\r
       break;\r
-    } else if (EFI_ERROR (VerifyStatus)) {\r
-      if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
-        VerifyStatus = EFI_SUCCESS;\r
+    }\r
+\r
+    if (!IsVerified) {\r
+      DbStatus = IsSignatureFoundInDatabase (\r
+                   EFI_IMAGE_SECURITY_DATABASE,\r
+                   mImageDigest,\r
+                   &mCertType,\r
+                   mImageDigestSize,\r
+                   &IsFound\r
+                   );\r
+      if (!EFI_ERROR (DbStatus) && IsFound) {\r
+        IsVerified = TRUE;\r
+      } else {\r
+        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is not allowed by DB and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));\r
       }\r
     }\r
   }\r
 \r
   if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {\r
     //\r
-    // The Size in Certificate Table or the attribute certicate table is corrupted.\r
+    // The Size in Certificate Table or the attribute certificate table is corrupted.\r
     //\r
-    VerifyStatus = EFI_ACCESS_DENIED;\r
+    IsVerified = FALSE;\r
   }\r
 \r
-  if (!EFI_ERROR (VerifyStatus)) {\r
+  if (IsVerified) {\r
     return EFI_SUCCESS;\r
-  } else {\r
-    Status = EFI_ACCESS_DENIED;\r
-    if (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED || Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {\r
-      //\r
-      // Get image hash value as executable's signature.\r
-      //\r
-      SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
-      SignatureList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
-      if (SignatureList == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto Done;\r
-      }\r
-      SignatureList->SignatureHeaderSize  = 0;\r
-      SignatureList->SignatureListSize    = (UINT32) SignatureListSize;\r
-      SignatureList->SignatureSize        = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize);\r
-      CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));\r
-      Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));\r
-      CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);\r
-    }\r
   }\r
-\r
-Done:\r
-  if (Status != EFI_SUCCESS) {\r
+  if (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED || Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {\r
     //\r
-    // Policy decides to defer or reject the image; add its information in image executable information table.\r
+    // Get image hash value as signature of executable.\r
     //\r
-    NameStr = ConvertDevicePathToText (File, FALSE, TRUE);\r
-    AddImageExeInfo (Action, NameStr, File, SignatureList, SignatureListSize);\r
-    if (NameStr != NULL) {\r
-      DEBUG((EFI_D_INFO, "The image doesn't pass verification: %s\n", NameStr));\r
-      FreePool(NameStr);\r
+    SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
+    SignatureList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
+    if (SignatureList == NULL) {\r
+      SignatureListSize = 0;\r
+      goto Failed;\r
     }\r
-    Status = EFI_SECURITY_VIOLATION;\r
+    SignatureList->SignatureHeaderSize  = 0;\r
+    SignatureList->SignatureListSize    = (UINT32) SignatureListSize;\r
+    SignatureList->SignatureSize        = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize);\r
+    CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));\r
+    Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));\r
+    CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);\r
+  }\r
+\r
+Failed:\r
+  //\r
+  // Policy decides to defer or reject the image; add its information in image\r
+  // executable information table in either case.\r
+  //\r
+  NameStr = ConvertDevicePathToText (File, FALSE, TRUE);\r
+  AddImageExeInfo (Action, NameStr, File, SignatureList, SignatureListSize);\r
+  if (NameStr != NULL) {\r
+    DEBUG ((DEBUG_INFO, "The image doesn't pass verification: %s\n", NameStr));\r
+    FreePool(NameStr);\r
   }\r
 \r
   if (SignatureList != NULL) {\r
     FreePool (SignatureList);\r
   }\r
 \r
-  return Status;\r
+  if (Policy == DEFER_EXECUTE_ON_SECURITY_VIOLATION) {\r
+    return EFI_SECURITY_VIOLATION;\r
+  }\r
+  return EFI_ACCESS_DENIED;\r
 }\r
 \r
 /**\r