]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
Removes redundant code and adds data size check for certificate data in DxeImageVerif...
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index dab35d5f6c2edfb4e0a6a36bbc2fd6f138d0edb4..3e0bbe1ee4c771092fc4c9afc898ab0ffa629128 100644 (file)
@@ -1,13 +1,13 @@
 /** @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
@@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \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
@@ -54,14 +54,58 @@ HASH_TABLE mHash[] = {
   { L"SHA512", 64, &mHashOidValue[40], 9, NULL,                NULL,       NULL,          NULL       }\r
 };\r
 \r
+/**\r
+  Reads contents of a PE/COFF image in memory buffer.\r
+\r
+  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.\r
+  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.\r
+  @param  ReadSize        On input, the size in bytes of the requested read operation.  \r
+                          On output, the number of bytes actually read.\r
+  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.\r
+  \r
+  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeImageVerificationLibImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  UINTN               EndPosition;\r
+\r
+  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;    \r
+  }\r
+\r
+  if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  EndPosition = FileOffset + *ReadSize;\r
+  if (EndPosition > mImageSize) {\r
+    *ReadSize = (UINT32)(mImageSize - FileOffset);\r
+  }\r
+\r
+  if (FileOffset >= mImageSize) {\r
+    *ReadSize = 0;\r
+  }\r
+\r
+  CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\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
@@ -70,7 +114,7 @@ GetImageType (
   )\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
@@ -78,7 +122,7 @@ GetImageType (
   // 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
@@ -102,7 +146,7 @@ GetImageType (
   // 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
@@ -136,11 +180,11 @@ GetImageType (
   }\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
@@ -155,12 +199,12 @@ GetImageType (
 \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
@@ -170,7 +214,7 @@ GetImageType (
     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
@@ -178,7 +222,7 @@ GetImageType (
     }\r
     TempDevicePath = NextDevicePathNode (TempDevicePath);\r
   }\r
-  return IMAGE_UNKNOWN; \r
+  return IMAGE_UNKNOWN;\r
 }\r
 \r
 /**\r
@@ -186,12 +230,12 @@ GetImageType (
   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
@@ -207,9 +251,9 @@ HashPeImage (
   EFI_IMAGE_SECTION_HEADER  *SectionHeader;\r
   UINTN                     Index;\r
   UINTN                     Pos;\r
-  UINTN                     SumOfSectionBytes;\r
-  EFI_IMAGE_SECTION_HEADER  *SectionCache;  \r
-  \r
+  UINT32                    CertSize;\r
+  UINT32                    NumberOfRvaAndSizes;\r
+\r
   HashCtx       = NULL;\r
   SectionHeader = NULL;\r
   Status        = FALSE;\r
@@ -217,7 +261,7 @@ HashPeImage (
   if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
     return FALSE;\r
   }\r
-  \r
+\r
   //\r
   // Initialize context of hash.\r
   //\r
@@ -234,7 +278,7 @@ HashPeImage (
   }\r
 \r
   CtxSize   = mHash[HashAlg].GetContextSize();\r
-  \r
+\r
   HashCtx = AllocatePool (CtxSize);\r
   if (HashCtx == NULL) {\r
     return FALSE;\r
@@ -244,10 +288,11 @@ HashPeImage (
 \r
   // 2.  Initialize a SHA hash context.\r
   Status = mHash[HashAlg].HashInit(HashCtx);\r
-  \r
+\r
   if (!Status) {\r
     goto Done;\r
   }\r
+\r
   //\r
   // Measuring PE/COFF Image Header;\r
   // But CheckSum field and SECURITY data directory (certificate) are excluded\r
@@ -263,11 +308,13 @@ HashPeImage (
     // Use PE32 offset.\r
     //\r
     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
   } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
     //\r
     // Use PE32+ offset.\r
     //\r
     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
   } else {\r
     //\r
     // Invalid header magic number.\r
@@ -280,51 +327,86 @@ HashPeImage (
   if (!Status) {\r
     goto Done;\r
   }\r
+\r
   //\r
   // 5.  Skip over the image checksum (it occupies a single ULONG).\r
-  // 6.  Get the address of the beginning of the Cert Directory.\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 (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
     //\r
-    // Use PE32 offset.\r
+    // 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
-    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - 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
-  }\r
+    if (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
+    } 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
+    }\r
 \r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // 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 (HashSize != 0) {\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    }\r
+  } else {\r
     //\r
-    // Use PE32 offset\r
+    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
     //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
-  } else {\r
+    if (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
+    } 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
+    }\r
+\r
+    if (HashSize != 0) {\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    }\r
+\r
     //\r
-    // Use PE32+ offset.\r
+    // 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
-    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
-  }\r
+    if (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
+    } 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
+    }\r
 \r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-  if (!Status) {\r
-    goto Done;\r
+    if (HashSize != 0) {\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    }    \r
   }\r
+\r
   //\r
   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
   //\r
@@ -349,20 +431,6 @@ HashPeImage (
                mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
                );\r
 \r
-  SectionCache = Section;\r
-  for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) {\r
-    SumOfSectionBytes += SectionCache->SizeOfRawData;\r
-  }\r
-  \r
-  //\r
-  // Sanity check for file corruption. Sections raw data size should be smaller\r
-  // than Image Size.\r
-  //\r
-  if (SumOfSectionBytes >= mImageSize) {\r
-    Status = FALSE;\r
-    goto Done;\r
-  }\r
-\r
   //\r
   // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
   //     structures in the image. The 'NumberOfSections' field of the image\r
@@ -421,29 +489,36 @@ HashPeImage (
   //\r
   if (mImageSize > SumOfBytesHashed) {\r
     HashBase = mImageBase + SumOfBytesHashed;\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-      //\r
-      // Use PE32 offset.\r
-      //\r
-      HashSize = (UINTN)(\r
-                 mImageSize -\r
-                 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);\r
+\r
+    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      CertSize = 0;\r
     } else {\r
-      //\r
-      // Use PE32+ offset.\r
-      //\r
-      HashSize = (UINTN)(\r
-                 mImageSize -\r
-                 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);      \r
+      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        //\r
+        // Use PE32 offset.\r
+        //\r
+        CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      } else {\r
+        //\r
+        // Use PE32+ offset.\r
+        //\r
+        CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      }\r
     }\r
 \r
-    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-    if (!Status) {\r
+    if (mImageSize > CertSize + SumOfBytesHashed) {\r
+      HashSize = (UINTN) (mImageSize - CertSize - SumOfBytesHashed);\r
+\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    } else if (mImageSize < CertSize + SumOfBytesHashed) {\r
+      Status = FALSE;\r
       goto Done;\r
     }\r
   }\r
+\r
   Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
 \r
 Done:\r
@@ -457,15 +532,15 @@ Done:
 }\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
@@ -475,10 +550,14 @@ HashPeImageByType (
 \r
   PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
-  for (Index = 0; Index < HASHALG_MAX; Index++) {  \r
+  if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\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
@@ -486,7 +565,19 @@ HashPeImageByType (
     //            .... }\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 (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + mHash[Index].OidLength) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
     if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
       break;\r
     }\r
@@ -514,7 +605,7 @@ HashPeImageByType (
   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
@@ -550,12 +641,12 @@ GetImageExeInfoTableSize (
   @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
@@ -577,13 +668,13 @@ AddImageExeInfo (
   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
@@ -637,7 +728,7 @@ AddImageExeInfo (
   // Update/replace the image execution table.\r
   //\r
   gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);\r
-  \r
+\r
   //\r
   // Free Old table data!\r
   //\r
@@ -649,7 +740,7 @@ AddImageExeInfo (
 /**\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
@@ -667,7 +758,7 @@ ImageAuthorization (
   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
@@ -715,7 +806,7 @@ ImageAuthorization (
 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
@@ -786,16 +877,20 @@ Done:
 }\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
@@ -804,55 +899,50 @@ VerifyCertPkcsSignedData (
   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
@@ -862,84 +952,59 @@ VerifyCertPkcsSignedData (
                            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
@@ -947,14 +1012,14 @@ Done:
 }\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
@@ -1004,7 +1069,7 @@ VerifyCertUefiGuid (
   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
@@ -1024,7 +1089,7 @@ VerifyCertUefiGuid (
     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
@@ -1041,8 +1106,8 @@ VerifyCertUefiGuid (
     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
@@ -1058,13 +1123,13 @@ VerifyCertUefiGuid (
   // 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
@@ -1081,13 +1146,31 @@ Done:
 \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
@@ -1117,19 +1200,22 @@ DxeImageVerificationHandler (
   IN  VOID                             *FileBuffer,\r
   IN  UINTN                            FileSize\r
   )\r
-\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINT16                      Magic;\r
-  EFI_IMAGE_DOS_HEADER        *DosHdr;\r
-  EFI_STATUS                  VerifyStatus;\r
-  UINT8                       *SetupMode;\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
+  EFI_STATUS                           Status;\r
+  UINT16                               Magic;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_STATUS                           VerifyStatus;\r
+  UINT8                                *SetupMode;\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                                *SecureBootEnable;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  UINT32                               CertSize;\r
 \r
   if (File == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1144,7 +1230,7 @@ DxeImageVerificationHandler (
   // 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
@@ -1162,7 +1248,7 @@ DxeImageVerificationHandler (
     break;\r
 \r
   default:\r
-    Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION; \r
+    Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;\r
     break;\r
   }\r
   //\r
@@ -1173,6 +1259,25 @@ DxeImageVerificationHandler (
   } 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
+  FreePool (SecureBootEnable);\r
+\r
   SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);\r
 \r
   //\r
@@ -1190,19 +1295,40 @@ DxeImageVerificationHandler (
     FreePool (SetupMode);\r
     return EFI_SUCCESS;\r
   }\r
+\r
+  FreePool (SetupMode);\r
+\r
   //\r
   // Read the Dos header.\r
   //\r
   if (FileBuffer == NULL) {\r
-    FreePool (SetupMode);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   mImageBase  = (UINT8 *) FileBuffer;\r
   mImageSize  = FileSize;\r
-  DosHdr      = (EFI_IMAGE_DOS_HEADER *) (mImageBase);\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
+    // DOS image header is present,\r
     // so read the PE header after the DOS image header.\r
     //\r
     mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
@@ -1217,7 +1343,7 @@ DxeImageVerificationHandler (
     //\r
     // It is not a valid Pe/Coff file.\r
     //\r
-    return EFI_ACCESS_DENIED;\r
+    goto Done;\r
   }\r
 \r
   Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
@@ -1225,47 +1351,70 @@ DxeImageVerificationHandler (
     //\r
     // Use PE32 offset.\r
     //\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
+    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }        \r
   } else {\r
     //\r
-    // Invalid header magic number.\r
+    // Use PE32+ offset.\r
     //\r
-    Status       = EFI_INVALID_PARAMETER;\r
-    goto Done;\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }\r
   }\r
 \r
-  if (mSecDataDir->VirtualAddress >= mImageSize) {\r
+  if ((mSecDataDir == NULL) || ((mSecDataDir != NULL) && (mSecDataDir->Size == 0))) {\r
     //\r
-    // Sanity check to see if this file is corrupted.\r
+    // This image is not signed.\r
     //\r
-    Status       = EFI_INVALID_PARAMETER;\r
-    goto Done;\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
-  if (mSecDataDir->Size == 0) {\r
     //\r
-    // This image is not signed.\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
+    goto Done;\r
   }\r
+\r
   //\r
   // Verify signature of executables.\r
   //\r
   WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
+  CertSize = sizeof (WIN_CERTIFICATE);\r
+\r
+  if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) {\r
+    goto Done;\r
+  }\r
+\r
   switch (WinCertificate->wCertificateType) {\r
-  \r
+\r
   case WIN_CERT_TYPE_EFI_GUID:\r
+    CertSize = sizeof (WIN_CERTIFICATE_UEFI_GUID) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256) - sizeof (UINT8);\r
+    if (WinCertificate->dwLength < CertSize) {\r
+      goto Done;\r
+    }\r
+\r
     //\r
     // Verify UEFI GUID type.\r
-    //   \r
+    //\r
     if (!HashPeImage (HASHALG_SHA256)) {\r
       goto Done;\r
     }\r
@@ -1277,8 +1426,8 @@ DxeImageVerificationHandler (
     //\r
     // Verify Pkcs signed data type.\r
     //\r
-    Status    = HashPeImageByType();\r
-    if (EFI_ERROR(Status)) {\r
+    Status = HashPeImageByType();\r
+    if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
 \r
@@ -1289,11 +1438,14 @@ DxeImageVerificationHandler (
     // 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
+    goto Done;\r
   }\r
   //\r
   // Get image hash value as executable's signature.\r
@@ -1317,8 +1469,17 @@ DxeImageVerificationHandler (
     //\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
@@ -1351,17 +1512,15 @@ Done:
     FreePool (SignatureList);\r
   }\r
 \r
-  FreePool (SetupMode);\r
-\r
   return Status;\r
 }\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
@@ -1379,7 +1538,7 @@ VariableWriteCallBack (
   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
@@ -1401,7 +1560,7 @@ VariableWriteCallBack (
   } else {\r
     FreePool (SecureBootModePtr);\r
   }\r
-}  \r
+}\r
 \r
 /**\r
   Register security measurement handler.\r
@@ -1422,7 +1581,7 @@ DxeImageVerificationLibConstructor (
 \r
   //\r
   // Register callback function upon VariableWriteArchProtocol.\r
-  // \r
+  //\r
   EfiCreateProtocolNotifyEvent (\r
     &gEfiVariableWriteArchProtocolGuid,\r
     TPL_CALLBACK,\r
@@ -1434,5 +1593,5 @@ DxeImageVerificationLibConstructor (
   return RegisterSecurityHandler (\r
           DxeImageVerificationHandler,\r
           EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
-          );      \r
+          );\r
 }\r