]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
SecurityPkg: remove PE/COFF header workaround for ELILO on IPF
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 443926b5079c2a0d3c296eaeae02de523e36d285..66d96a9396b9137cd4a7bb3367c82affc9f59389 100644 (file)
@@ -1,5 +1,5 @@
 /** @file\r
-  Implement image verification services for secure boot service in UEFI2.3.1.\r
+  Implement image verification services for secure boot service\r
 \r
   Caution: This file requires additional review when modified.\r
   This library will have external input - PE/COFF image.\r
@@ -12,7 +12,8 @@
   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 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<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
@@ -71,6 +72,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
@@ -270,13 +273,16 @@ GetImageType (
 }\r
 \r
 /**\r
-  Caculate hash of Pe/Coff image based on the authenticode image hashing in\r
+  Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
   PE/COFF Specification 8.0 Appendix A\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
+  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 +295,6 @@ HashPeImage (
   )\r
 {\r
   BOOLEAN                   Status;\r
-  UINT16                    Magic;\r
   EFI_IMAGE_SECTION_HEADER  *Section;\r
   VOID                      *HashCtx;\r
   UINTN                     CtxSize;\r
@@ -340,6 +345,7 @@ HashPeImage (
     return FALSE;\r
   }\r
 \r
+  mHashTypeStr = mHash[HashAlg].Name;\r
   CtxSize   = mHash[HashAlg].GetContextSize();\r
 \r
   HashCtx = AllocatePool (CtxSize);\r
@@ -360,37 +366,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 +405,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 +429,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 +454,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 +479,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 +562,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
@@ -609,7 +601,7 @@ Done:
 }\r
 \r
 /**\r
-  Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of\r
+  Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of\r
   Pe/Coff image based on the authenticode image hashing in PE/COFF Specification\r
   8.0 Appendix A\r
 \r
@@ -737,11 +729,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
@@ -769,7 +763,12 @@ AddImageExeInfo (
   }\r
 \r
   DevicePathSize            = GetDevicePathSize (DevicePath);\r
-  NewImageExeInfoEntrySize  = sizeof (EFI_IMAGE_EXECUTION_INFO) - sizeof (EFI_SIGNATURE_LIST) + NameStringLen + DevicePathSize + SignatureSize;\r
+\r
+  //\r
+  // Signature size can be odd. Pad after signature to ensure next EXECUTION_INFO entry align\r
+  //\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 +787,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
@@ -841,7 +842,7 @@ IsCertHashFoundInDatabase (
   )\r
 {\r
   BOOLEAN             IsFound;\r
-  EFI_STATUS          Status;\r
+  BOOLEAN             Status;\r
   EFI_SIGNATURE_LIST  *DbxList;\r
   UINTN               DbxSize;\r
   EFI_SIGNATURE_DATA  *CertHash;\r
@@ -852,6 +853,8 @@ IsCertHashFoundInDatabase (
   UINT8               CertDigest[MAX_DIGEST_SIZE];\r
   UINT8               *DbxCertHash;\r
   UINTN               SiglistHeaderSize;\r
+  UINT8               *TBSCert;\r
+  UINTN               TBSCertSize;\r
 \r
   IsFound  = FALSE;\r
   DbxList  = SignatureList;\r
@@ -859,8 +862,16 @@ IsCertHashFoundInDatabase (
   HashCtx  = NULL;\r
   HashAlg  = HASHALG_MAX;\r
 \r
-  ASSERT (RevocationTime != NULL);\r
-  ASSERT (DbxList != NULL);\r
+  if ((RevocationTime == NULL) || (DbxList == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Retrieve the TBSCertificate from the X.509 Certificate.\r
+  //\r
+  if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {\r
+    return FALSE;\r
+  }\r
 \r
   while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
     //\r
@@ -879,7 +890,7 @@ IsCertHashFoundInDatabase (
     }\r
 \r
     //\r
-    // Calculate the hash value of current db certificate for comparision.\r
+    // Calculate the hash value of current TBSCertificate for comparision.\r
     //\r
     if (mHash[HashAlg].GetContextSize == NULL) {\r
       goto Done;\r
@@ -893,7 +904,7 @@ IsCertHashFoundInDatabase (
     if (!Status) {\r
       goto Done;\r
     }\r
-    Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize);\r
+    Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
     if (!Status) {\r
       goto Done;\r
     }\r
@@ -1000,7 +1011,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
@@ -1078,14 +1094,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
@@ -1204,6 +1220,12 @@ IsForbiddenByDbx (
   BOOLEAN                   IsForbidden;\r
   UINT8                     *Data;\r
   UINTN                     DataSize;\r
+  EFI_SIGNATURE_LIST        *CertList;\r
+  UINTN                     CertListSize;\r
+  EFI_SIGNATURE_DATA        *CertData;\r
+  UINT8                     *RootCert;\r
+  UINTN                     RootCertSize;\r
+  UINTN                     CertCount;\r
   UINTN                     Index;\r
   UINT8                     *CertBuffer;\r
   UINTN                     BufferLength;\r
@@ -1214,12 +1236,15 @@ IsForbiddenByDbx (
   UINT8                     *Cert;\r
   UINTN                     CertSize;\r
   EFI_TIME                  RevocationTime;\r
-\r
   //\r
   // Variable Initialization\r
   //\r
   IsForbidden       = FALSE;\r
   Data              = NULL;\r
+  CertList          = NULL;\r
+  CertData          = NULL;\r
+  RootCert          = NULL;\r
+  RootCertSize      = 0;\r
   Cert              = NULL;\r
   CertBuffer        = NULL;\r
   BufferLength      = 0;\r
@@ -1244,6 +1269,52 @@ IsForbiddenByDbx (
     return IsForbidden;\r
   }\r
 \r
+  //\r
+  // Verify image signature with RAW X509 certificates in DBX database.\r
+  // If passed, the image will be forbidden.\r
+  //\r
+  CertList     = (EFI_SIGNATURE_LIST *) Data;\r
+  CertListSize = DataSize;\r
+  while ((CertListSize > 0) && (CertListSize >= 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
+\r
+        //\r
+        // Call AuthenticodeVerify library to Verify Authenticode struct.\r
+        //\r
+        IsForbidden = AuthenticodeVerify (\r
+                        AuthData,\r
+                        AuthDataSize,\r
+                        RootCert,\r
+                        RootCertSize,\r
+                        mImageDigest,\r
+                        mImageDigestSize\r
+                        );\r
+        if (IsForbidden) {\r
+          DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is forbidden by DBX.\n"));\r
+          goto Done;\r
+        }\r
+\r
+        CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+      }\r
+    }\r
+\r
+    CertListSize -= CertList->SignatureListSize;\r
+    CertList      = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  //\r
+  // Check X.509 Certificate Hash & Possible Timestamp.\r
+  //\r
+\r
   //\r
   // Retrieve the certificate stack from AuthData\r
   // The output CertStack format will be:\r
@@ -1263,20 +1334,17 @@ IsForbiddenByDbx (
   }\r
 \r
   //\r
-  // Check if any certificates in AuthData is in the forbidden database.\r
+  // Check if any hash of certificates embedded in AuthData is in the forbidden database.\r
   //\r
   CertNumber = (UINT8) (*CertBuffer);\r
   CertPtr    = CertBuffer + 1;\r
   for (Index = 0; Index < CertNumber; Index++) {\r
     CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);\r
     Cert     = (UINT8 *)CertPtr + sizeof (UINT32);\r
-    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Cert, &gEfiCertX509Guid, CertSize)) {\r
-      //\r
-      // Raw certificate in dbx means the image signed by the certificate is forbidden.\r
-      //\r
-      IsForbidden = TRUE;\r
-      goto Done;\r
-    }\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
@@ -1285,11 +1353,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
@@ -1303,6 +1375,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
@@ -1322,20 +1395,24 @@ 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
   UINTN                     RootCertSize;\r
   UINTN                     Index;\r
   UINTN                     CertCount;\r
+  UINTN                     DbxDataSize;\r
+  UINT8                     *DbxData;\r
+  EFI_TIME                  RevocationTime;\r
 \r
-  Data         = NULL;\r
-  CertList     = NULL;\r
-  Cert         = NULL;\r
-  RootCert     = 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
@@ -1356,14 +1433,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
@@ -1378,11 +1455,37 @@ IsAllowedByDb (
                            mImageDigestSize\r
                            );\r
           if (VerifyStatus) {\r
-            SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\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
+            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 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
@@ -1392,9 +1495,17 @@ IsAllowedByDb (
   }\r
 \r
 Done:\r
+\r
+  if (VerifyStatus) {\r
+    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);\r
+  }\r
+\r
   if (Data != NULL) {\r
     FreePool (Data);\r
   }\r
+  if (DbxData != NULL) {\r
+    FreePool (DbxData);\r
+  }\r
 \r
   return VerifyStatus;\r
 }\r
@@ -1457,7 +1568,6 @@ DxeImageVerificationHandler (
   )\r
 {\r
   EFI_STATUS                           Status;\r
-  UINT16                               Magic;\r
   EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
   EFI_STATUS                           VerifyStatus;\r
   EFI_SIGNATURE_LIST                   *SignatureList;\r
@@ -1486,6 +1596,7 @@ DxeImageVerificationHandler (
   Status            = EFI_ACCESS_DENIED;\r
   VerifyStatus      = EFI_ACCESS_DENIED;\r
 \r
+\r
   //\r
   // Check the image type and get policy setting.\r
   //\r
@@ -1538,7 +1649,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
@@ -1568,6 +1679,7 @@ DxeImageVerificationHandler (
     //\r
     // The information can't be got from the invalid PeImage\r
     //\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: PeImage invalid. Cannot retrieve image information.\n"));\r
     goto Done;\r
   }\r
 \r
@@ -1591,25 +1703,11 @@ DxeImageVerificationHandler (
     //\r
     // It is not a valid Pe/Coff file.\r
     //\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Not a valid PE/COFF image.\n"));\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
+  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset.\r
     //\r
@@ -1636,6 +1734,7 @@ DxeImageVerificationHandler (
     // and not be reflected in the security data base "dbx".\r
     //\r
     if (!HashPeImage (HASHALG_SHA256)) {\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHashTypeStr));\r
       goto Done;\r
     }\r
 \r
@@ -1643,6 +1742,7 @@ DxeImageVerificationHandler (
       //\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 Done;\r
     }\r
 \r
@@ -1656,6 +1756,7 @@ DxeImageVerificationHandler (
     //\r
     // Image Hash is not found in both forbidden and allowed database.\r
     //\r
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));\r
     goto Done;\r
   }\r
 \r
@@ -1735,11 +1836,14 @@ DxeImageVerificationHandler (
     //\r
     if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;\r
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s hash of image is found in DBX.\n", mHashTypeStr));\r
       VerifyStatus = EFI_ACCESS_DENIED;\r
       break;\r
     } else if (EFI_ERROR (VerifyStatus)) {\r
       if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
         VerifyStatus = EFI_SUCCESS;\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
@@ -1767,7 +1871,7 @@ DxeImageVerificationHandler (
       }\r
       SignatureList->SignatureHeaderSize  = 0;\r
       SignatureList->SignatureListSize    = (UINT32) SignatureListSize;\r
-      SignatureList->SignatureSize        = (UINT32) mImageDigestSize;\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