]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
SecurityPkg/DxeImageVerificationLib: reject CertStack.CertNumber==0 per DBX (CVE...
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index ca1bdc0be8c37cd649c038da68dd11dac14803b0..5dcd6efed534668acf0c402c35afeee095ae3147 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 - 2015, 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
@@ -718,7 +704,7 @@ GetImageExeInfoTableSize (
   @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
@@ -737,11 +723,13 @@ AddImageExeInfo (
   UINTN                           NewImageExeInfoEntrySize;\r
   UINTN                           NameStringLen;\r
   UINTN                           DevicePathSize;\r
+  CHAR16                          *NameStr;\r
 \r
   ImageExeInfoTable     = NULL;\r
   NewImageExeInfoTable  = NULL;\r
   ImageExeInfoEntry     = NULL;\r
   NameStringLen         = 0;\r
+  NameStr               = NULL;\r
 \r
   if (DevicePath == NULL) {\r
     return ;\r
@@ -757,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
@@ -769,7 +757,13 @@ AddImageExeInfo (
   }\r
 \r
   DevicePathSize            = GetDevicePathSize (DevicePath);\r
-  NewImageExeInfoEntrySize  = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
+\r
+  //\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
   if (NewImageExeInfoTable == NULL) {\r
     return ;\r
@@ -788,19 +782,21 @@ AddImageExeInfo (
   WriteUnaligned32 ((UINT32 *) ImageExeInfoEntry, Action);\r
   WriteUnaligned32 ((UINT32 *) ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32) NewImageExeInfoEntrySize);\r
 \r
+  NameStr = (CHAR16 *)(ImageExeInfoEntry + 1);\r
   if (Name != NULL) {\r
-    CopyMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), Name, NameStringLen);\r
+    CopyMem ((UINT8 *) NameStr, Name, NameStringLen);\r
   } else {\r
-    ZeroMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), sizeof (CHAR16));\r
+    ZeroMem ((UINT8 *) NameStr, sizeof (CHAR16));\r
   }\r
+\r
   CopyMem (\r
-    (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen,\r
+    (UINT8 *) NameStr + NameStringLen,\r
     DevicePath,\r
     DevicePathSize\r
     );\r
   if (Signature != NULL) {\r
     CopyMem (\r
-      (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
+      (UINT8 *) NameStr + NameStringLen + DevicePathSize,\r
       Signature,\r
       SignatureSize\r
       );\r
@@ -912,6 +908,9 @@ IsCertHashFoundInDatabase (
       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
@@ -952,7 +951,7 @@ 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
 \r
   @return TRUE                    Found the signature in the variable database.\r
@@ -997,7 +996,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
@@ -1010,7 +1009,12 @@ IsSignatureFoundInDatabase (
           // Find the signature in database.\r
           //\r
           IsFound = TRUE;\r
-          SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\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
@@ -1088,14 +1092,14 @@ IsTimeZero (
 }\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
@@ -1230,7 +1234,6 @@ IsForbiddenByDbx (
   UINT8                     *Cert;\r
   UINTN                     CertSize;\r
   EFI_TIME                  RevocationTime;\r
-\r
   //\r
   // Variable Initialization\r
   //\r
@@ -1294,7 +1297,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
@@ -1323,7 +1326,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
@@ -1336,6 +1339,10 @@ IsForbiddenByDbx (
   for (Index = 0; Index < CertNumber; Index++) {\r
     CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);\r
     Cert     = (UINT8 *)CertPtr + sizeof (UINT32);\r
+    //\r
+    // Advance CertPtr to the next cert in image signer's cert list\r
+    //\r
+    CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
 \r
     if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
       //\r
@@ -1344,11 +1351,15 @@ IsForbiddenByDbx (
       IsForbidden = TRUE;\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
       }\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
       goto Done;\r
     }\r
 \r
-    CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
   }\r
 \r
 Done:\r
@@ -1362,6 +1373,7 @@ Done:
   return IsForbidden;\r
 }\r
 \r
+\r
 /**\r
   Check whether the image signature can be verified by the trusted certificates in DB database.\r
 \r
@@ -1381,7 +1393,7 @@ IsAllowedByDb (
   EFI_STATUS                Status;\r
   BOOLEAN                   VerifyStatus;\r
   EFI_SIGNATURE_LIST        *CertList;\r
-  EFI_SIGNATURE_DATA        *Cert;\r
+  EFI_SIGNATURE_DATA        *CertData;\r
   UINTN                     DataSize;\r
   UINT8                     *Data;\r
   UINT8                     *RootCert;\r
@@ -1392,13 +1404,13 @@ IsAllowedByDb (
   UINT8                     *DbxData;\r
   EFI_TIME                  RevocationTime;\r
 \r
-  Data         = NULL;\r
-  CertList     = NULL;\r
-  Cert         = NULL;\r
-  RootCert     = NULL;\r
-  DbxData      = NULL;\r
-  RootCertSize = 0;\r
-  VerifyStatus = FALSE;\r
+  Data              = NULL;\r
+  CertList          = NULL;\r
+  CertData          = NULL;\r
+  RootCert          = NULL;\r
+  DbxData           = NULL;\r
+  RootCertSize      = 0;\r
+  VerifyStatus      = FALSE;\r
 \r
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
@@ -1419,14 +1431,14 @@ IsAllowedByDb (
     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
+        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     = Cert->SignatureData;\r
+          RootCert     = CertData->SignatureData;\r
           RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
 \r
           //\r
@@ -1460,15 +1472,18 @@ IsAllowedByDb (
 \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
+              // 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
-          Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+          CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
         }\r
       }\r
 \r
@@ -1478,8 +1493,9 @@ IsAllowedByDb (
   }\r
 \r
 Done:\r
+\r
   if (VerifyStatus) {\r
-    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);\r
   }\r
 \r
   if (Data != NULL) {\r
@@ -1529,14 +1545,14 @@ Done:
                                  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
+                                 Foundation may not use File. The image has\r
+                                 been added to the file execution table.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1549,10 +1565,8 @@ DxeImageVerificationHandler (
   IN  BOOLEAN                          BootPolicy\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
-  UINT16                               Magic;\r
   EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
-  EFI_STATUS                           VerifyStatus;\r
+  BOOLEAN                              IsVerified;\r
   EFI_SIGNATURE_LIST                   *SignatureList;\r
   UINTN                                SignatureListSize;\r
   EFI_SIGNATURE_DATA                   *Signature;\r
@@ -1569,6 +1583,8 @@ DxeImageVerificationHandler (
   EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;\r
   UINT32                               OffSet;\r
   CHAR16                               *NameStr;\r
+  RETURN_STATUS                        PeCoffStatus;\r
+  EFI_STATUS                           HashStatus;\r
 \r
   SignatureList     = NULL;\r
   SignatureListSize = 0;\r
@@ -1576,8 +1592,8 @@ DxeImageVerificationHandler (
   SecDataDir        = NULL;\r
   PkcsCertData      = NULL;\r
   Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
-  Status            = EFI_ACCESS_DENIED;\r
-  VerifyStatus      = EFI_ACCESS_DENIED;\r
+  IsVerified        = FALSE;\r
+\r
 \r
   //\r
   // Check the image type and get policy setting.\r
@@ -1609,7 +1625,8 @@ DxeImageVerificationHandler (
   //\r
   if (Policy == ALWAYS_EXECUTE) {\r
     return EFI_SUCCESS;\r
-  } else if (Policy == NEVER_EXECUTE) {\r
+  }\r
+  if (Policy == NEVER_EXECUTE) {\r
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
@@ -1631,7 +1648,7 @@ DxeImageVerificationHandler (
   }\r
 \r
   //\r
-  // Skip verification if SecureBoot is disabled.\r
+  // Skip verification if SecureBoot is disabled but not AuditMode\r
   //\r
   if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
     FreePool (SecureBoot);\r
@@ -1643,7 +1660,7 @@ DxeImageVerificationHandler (
   // Read the Dos header.\r
   //\r
   if (FileBuffer == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_ACCESS_DENIED;\r
   }\r
 \r
   mImageBase  = (UINT8 *) FileBuffer;\r
@@ -1656,16 +1673,15 @@ DxeImageVerificationHandler (
   //\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 Done;\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: PeImage invalid. Cannot retrieve image information.\n"));\r
+    goto Failed;\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
@@ -1684,25 +1700,11 @@ DxeImageVerificationHandler (
     //\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
+    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
@@ -1729,14 +1731,16 @@ DxeImageVerificationHandler (
     // and not be reflected in the security data base "dbx".\r
     //\r
     if (!HashPeImage (HASHALG_SHA256)) {\r
-      goto Done;\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHashTypeStr));\r
+      goto Failed;\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
+      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
     if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
@@ -1749,7 +1753,8 @@ DxeImageVerificationHandler (
     //\r
     // Image Hash is not found in both forbidden and allowed database.\r
     //\r
-    goto Done;\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
@@ -1800,8 +1805,8 @@ DxeImageVerificationHandler (
       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
@@ -1810,16 +1815,16 @@ DxeImageVerificationHandler (
     //\r
     if (IsForbiddenByDbx (AuthData, AuthDataSize)) {\r
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
-      VerifyStatus = EFI_ACCESS_DENIED;\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 (!IsVerified) {\r
       if (IsAllowedByDb (AuthData, AuthDataSize)) {\r
-        VerifyStatus = EFI_SUCCESS;\r
+        IsVerified = TRUE;\r
       }\r
     }\r
 \r
@@ -1828,64 +1833,67 @@ DxeImageVerificationHandler (
     //\r
     if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\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
+    }\r
+    if (!IsVerified) {\r
       if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
-        VerifyStatus = EFI_SUCCESS;\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) 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