]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
Correct the alignment calculation of PE/COFF attribute certificate entry.
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 9f2bd68299895616b376db3afc61d24da1839a29..c3793b94293602f22dd5a6cf9c424630e3063241 100644 (file)
@@ -64,11 +64,11 @@ UINT8 mHashOidValue[] = {
   };\r
 \r
 HASH_TABLE mHash[] = {\r
-  { L"SHA1",   20, &mHashOidValue[0],  5, Sha1GetContextSize,  Sha1Init,   Sha1Update,    Sha1Final  },\r
-  { L"SHA224", 28, &mHashOidValue[5],  9, NULL,                NULL,       NULL,          NULL       },\r
-  { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize,Sha256Init, Sha256Update,  Sha256Final},\r
-  { L"SHA384", 48, &mHashOidValue[23], 9, NULL,                NULL,       NULL,          NULL       },\r
-  { L"SHA512", 64, &mHashOidValue[32], 9, NULL,                NULL,       NULL,          NULL       }\r
+  { L"SHA1",   20, &mHashOidValue[0],  5, Sha1GetContextSize,   Sha1Init,   Sha1Update,   Sha1Final  },\r
+  { L"SHA224", 28, &mHashOidValue[5],  9, NULL,                 NULL,       NULL,         NULL       },\r
+  { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},\r
+  { L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},\r
+  { L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
 };\r
 \r
 /**\r
@@ -99,11 +99,11 @@ SecureBootHook (
 \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
+  @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
+  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -117,7 +117,7 @@ DxeImageVerificationLibImageRead (
   UINTN               EndPosition;\r
 \r
   if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
-    return EFI_INVALID_PARAMETER;    \r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
@@ -306,7 +306,7 @@ HashPeImage (
   SectionHeader = NULL;\r
   Status        = FALSE;\r
 \r
-  if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
+  if ((HashAlg >= HASHALG_MAX)) {\r
     return FALSE;\r
   }\r
 \r
@@ -315,13 +315,28 @@ HashPeImage (
   //\r
   ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
 \r
-  if (HashAlg == HASHALG_SHA1) {\r
-    mImageDigestSize  = SHA1_DIGEST_SIZE;\r
-    mCertType         = gEfiCertSha1Guid;\r
-  } else if (HashAlg == HASHALG_SHA256) {\r
-    mImageDigestSize  = SHA256_DIGEST_SIZE;\r
-    mCertType         = gEfiCertSha256Guid;\r
-  } else {\r
+  switch (HashAlg) {\r
+  case HASHALG_SHA1:\r
+    mImageDigestSize = SHA1_DIGEST_SIZE;\r
+    mCertType        = gEfiCertSha1Guid;\r
+    break;\r
+\r
+  case HASHALG_SHA256:\r
+    mImageDigestSize = SHA256_DIGEST_SIZE;\r
+    mCertType        = gEfiCertSha256Guid;\r
+    break;\r
+\r
+  case HASHALG_SHA384:\r
+    mImageDigestSize = SHA384_DIGEST_SIZE;\r
+    mCertType        = gEfiCertSha384Guid;\r
+    break;\r
+\r
+  case HASHALG_SHA512:\r
+    mImageDigestSize = SHA512_DIGEST_SIZE;\r
+    mCertType        = gEfiCertSha512Guid;\r
+    break;\r
+\r
+  default:\r
     return FALSE;\r
   }\r
 \r
@@ -347,8 +362,8 @@ HashPeImage (
   //\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
+    // 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
@@ -359,7 +374,7 @@ HashPeImage (
     //\r
     Magic =  mNtHeader.Pe32->OptionalHeader.Magic;\r
   }\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
@@ -466,7 +481,7 @@ HashPeImage (
       if (!Status) {\r
         goto Done;\r
       }\r
-    }    \r
+    }\r
   }\r
 \r
   //\r
@@ -604,7 +619,7 @@ Done:
 \r
   @param[in]  AuthData            Pointer to the Authenticode Signature retrieved from signed image.\r
   @param[in]  AuthDataSize        Size of the Authenticode Signature in bytes.\r
-  \r
+\r
   @retval EFI_UNSUPPORTED             Hash algorithm is not supported.\r
   @retval EFI_SUCCESS                 Hash successfully.\r
 \r
@@ -770,22 +785,22 @@ AddImageExeInfo (
   //\r
   // Update new item's information.\r
   //\r
-  WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->Action, Action);\r
-  WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->InfoSize, (UINT32) NewImageExeInfoEntrySize);\r
+  WriteUnaligned32 ((UINT32 *) ImageExeInfoEntry, Action);\r
+  WriteUnaligned32 ((UINT32 *) ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32) NewImageExeInfoEntrySize);\r
 \r
   if (Name != NULL) {\r
-    CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);\r
+    CopyMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), Name, NameStringLen);\r
   } else {\r
-    ZeroMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), sizeof (CHAR16));\r
+    ZeroMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), sizeof (CHAR16));\r
   }\r
   CopyMem (\r
-    (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,\r
+    (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen,\r
     DevicePath,\r
     DevicePathSize\r
     );\r
   if (Signature != NULL) {\r
     CopyMem (\r
-      (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
+      (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
       Signature,\r
       SignatureSize\r
       );\r
@@ -803,6 +818,124 @@ AddImageExeInfo (
   }\r
 }\r
 \r
+/**\r
+  Check whether the hash of an given X.509 certificate is in forbidden database (DBX).\r
+\r
+  @param[in]  Certificate       Pointer to X.509 Certificate that is searched for.\r
+  @param[in]  CertSize          Size of X.509 Certificate.\r
+  @param[in]  SignatureList     Pointer to the Signature List in forbidden database.\r
+  @param[in]  SignatureListSize Size of Signature List.\r
+  @param[out] RevocationTime    Return the time that the certificate was revoked.\r
+\r
+  @return TRUE   The certificate hash is found in the forbidden database.\r
+  @return FALSE  The certificate hash is not found in the forbidden database.\r
+\r
+**/\r
+BOOLEAN\r
+IsCertHashFoundInDatabase (\r
+  IN  UINT8               *Certificate,\r
+  IN  UINTN               CertSize,\r
+  IN  EFI_SIGNATURE_LIST  *SignatureList,\r
+  IN  UINTN               SignatureListSize,\r
+  OUT EFI_TIME            *RevocationTime\r
+  )\r
+{\r
+  BOOLEAN             IsFound;\r
+  EFI_STATUS          Status;\r
+  EFI_SIGNATURE_LIST  *DbxList;\r
+  UINTN               DbxSize;\r
+  EFI_SIGNATURE_DATA  *CertHash;\r
+  UINTN               CertHashCount;\r
+  UINTN               Index;\r
+  UINT32              HashAlg;\r
+  VOID                *HashCtx;\r
+  UINT8               CertDigest[MAX_DIGEST_SIZE];\r
+  UINT8               *DbxCertHash;\r
+  UINTN               SiglistHeaderSize;\r
+\r
+  IsFound  = FALSE;\r
+  DbxList  = SignatureList;\r
+  DbxSize  = SignatureListSize;\r
+  HashCtx  = NULL;\r
+  HashAlg  = HASHALG_MAX;\r
+\r
+  ASSERT (RevocationTime != NULL);\r
+\r
+  while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
+    //\r
+    // Determine Hash Algorithm of Certificate in the forbidden database.\r
+    //\r
+    if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
+      HashAlg = HASHALG_SHA256;\r
+    } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
+      HashAlg = HASHALG_SHA384;\r
+    } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
+      HashAlg = HASHALG_SHA512;\r
+    } else {\r
+      DbxSize -= DbxList->SignatureListSize;\r
+      DbxList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Calculate the hash value of current db certificate for comparision.\r
+    //\r
+    if (mHash[HashAlg].GetContextSize == NULL) {\r
+      goto Done;\r
+    }\r
+    ZeroMem (CertDigest, MAX_DIGEST_SIZE);\r
+    HashCtx = AllocatePool (mHash[HashAlg].GetContextSize ());\r
+    if (HashCtx == NULL) {\r
+      goto Done;\r
+    }\r
+    Status = mHash[HashAlg].HashInit (HashCtx);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\r
+    Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\r
+    Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\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
+    for (Index = 0; Index < CertHashCount; Index++) {\r
+      //\r
+      // Iterate each Signature Data Node within this CertList for verify.\r
+      //\r
+      DbxCertHash = CertHash->SignatureData;\r
+      if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {\r
+        //\r
+        // Hash of Certificate is found in forbidden database.\r
+        //\r
+        IsFound = TRUE;\r
+\r
+        //\r
+        // Return the revocation time.\r
+        //\r
+        CopyMem (RevocationTime, (EFI_TIME *)(DbxCertHash + mHash[HashAlg].DigestLength), sizeof (EFI_TIME));\r
+        goto Done;\r
+      }\r
+      CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);\r
+    }\r
+\r
+    DbxSize -= DbxList->SignatureListSize;\r
+    DbxList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
+  }\r
+\r
+Done:\r
+  if (HashCtx != NULL) {\r
+    FreePool (HashCtx);\r
+  }\r
+\r
+  return IsFound;\r
+}\r
+\r
 /**\r
   Check whether signature is in specified database.\r
 \r
@@ -831,6 +964,7 @@ IsSignatureFoundInDatabase (
   UINTN               Index;\r
   UINTN               CertCount;\r
   BOOLEAN             IsFound;\r
+\r
   //\r
   // Read signature database variable.\r
   //\r
@@ -890,24 +1024,296 @@ Done:
 }\r
 \r
 /**\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
+  Check whether the timestamp is valid by comparing the signing time and 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]  VariableName  Name of Variable to search for Certificate.\r
-  @param[in]  VendorGuid    Variable vendor GUID.\r
+  @param SigningTime         A pointer to the signing time.\r
+  @param RevocationTime      A pointer to the revocation time.\r
 \r
-  @retval TRUE         Image pass verification.\r
-  @retval FALSE        Image fail verification.\r
+  @retval  TRUE              The SigningTime is not later than the RevocationTime.\r
+  @retval  FALSE             The SigningTime is later than the RevocationTime.\r
 \r
 **/\r
 BOOLEAN\r
-IsPkcsSignedDataVerifiedBySignatureList (\r
+IsValidSignatureByTimestamp (\r
+  IN EFI_TIME               *SigningTime,\r
+  IN EFI_TIME               *RevocationTime\r
+  )\r
+{\r
+  if (SigningTime->Year != RevocationTime->Year) {\r
+    return (BOOLEAN) (SigningTime->Year < RevocationTime->Year);\r
+  } else if (SigningTime->Month != RevocationTime->Month) {\r
+    return (BOOLEAN) (SigningTime->Month < RevocationTime->Month);\r
+  } else if (SigningTime->Day != RevocationTime->Day) {\r
+    return (BOOLEAN) (SigningTime->Day < RevocationTime->Day);\r
+  } else if (SigningTime->Hour != RevocationTime->Hour) {\r
+    return (BOOLEAN) (SigningTime->Hour < RevocationTime->Hour);\r
+  } else if (SigningTime->Minute != RevocationTime->Minute) {\r
+    return (BOOLEAN) (SigningTime->Minute < RevocationTime->Minute);\r
+  }\r
+\r
+  return (BOOLEAN) (SigningTime->Second <= RevocationTime->Second);\r
+}\r
+\r
+/**\r
+  Check if the given time value is zero.\r
+\r
+  @param[in]  Time      Pointer of a time value.\r
+\r
+  @retval     TRUE      The Time is Zero.\r
+  @retval     FALSE     The Time is not Zero.\r
+\r
+**/\r
+BOOLEAN\r
+IsTimeZero (\r
+  IN EFI_TIME               *Time\r
+  )\r
+{\r
+  if ((Time->Year == 0) && (Time->Month == 0) &&  (Time->Day == 0) &&\r
+      (Time->Hour == 0) && (Time->Minute == 0) && (Time->Second == 0)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\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
+                    revocation time.\r
+  @retval FALSE     Timestamp signature is not valid or the signing time is later than the\r
+                    revocation time.\r
+\r
+**/\r
+BOOLEAN\r
+PassTimestampCheck (\r
+  IN UINT8                  *AuthData,\r
+  IN UINTN                  AuthDataSize,\r
+  IN EFI_TIME               *RevocationTime\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   VerifyStatus;\r
+  EFI_SIGNATURE_LIST        *CertList;\r
+  EFI_SIGNATURE_DATA        *Cert;\r
+  UINT8                     *DbtData;\r
+  UINTN                     DbtDataSize;\r
+  UINT8                     *RootCert;\r
+  UINTN                     RootCertSize;\r
+  UINTN                     Index;\r
+  UINTN                     CertCount;\r
+  EFI_TIME                  SigningTime;\r
+\r
+  //\r
+  // Variable Initialization\r
+  //\r
+  VerifyStatus      = FALSE;\r
+  DbtData           = NULL;\r
+  CertList          = NULL;\r
+  Cert              = NULL;\r
+  RootCert          = NULL;\r
+  RootCertSize      = 0;\r
+\r
+  //\r
+  // If RevocationTime is zero, the certificate shall be considered to always be revoked.\r
+  //\r
+  if (IsTimeZero (RevocationTime)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // RevocationTime is non-zero, the certificate should be considered to be revoked from that time and onwards.\r
+  // Using the dbt to get the trusted TSA certificates.\r
+  //\r
+  DbtDataSize = 0;\r
+  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, NULL);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    DbtData = (UINT8 *) AllocateZeroPool (DbtDataSize);\r
+    if (DbtData == NULL) {\r
+      goto Done;\r
+    }\r
+    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *) DbtData);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  CertList = (EFI_SIGNATURE_LIST *) DbtData;\r
+  while ((DbtDataSize > 0) && (DbtDataSize >= 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 verify.\r
+        //\r
+        RootCert     = Cert->SignatureData;\r
+        RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
+        //\r
+        // Get the signing time if the timestamp signature is valid.\r
+        //\r
+        if (ImageTimestampVerify (AuthData, AuthDataSize, RootCert, RootCertSize, &SigningTime)) {\r
+          //\r
+          // The signer signature is valid only when the signing time is earlier than revocation time.\r
+          //\r
+          if (IsValidSignatureByTimestamp (&SigningTime, RevocationTime)) {\r
+            VerifyStatus = TRUE;\r
+            goto Done;\r
+          }\r
+        }\r
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+      }\r
+    }\r
+    DbtDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+Done:\r
+  if (DbtData != NULL) {\r
+    FreePool (DbtData);\r
+  }\r
+\r
+  return VerifyStatus;\r
+}\r
+\r
+/**\r
+  Check whether the image signature is forbidden by the forbidden database (dbx).\r
+  The image is forbidden to load if any certificates for signing are revoked before signing time.\r
+\r
+  @param[in]  AuthData      Pointer to the Authenticode signature retrieved from the signed image.\r
+  @param[in]  AuthDataSize  Size of the Authenticode signature in bytes.\r
+\r
+  @retval TRUE              Image is forbidden by dbx.\r
+  @retval FALSE             Image is not forbidden by dbx.\r
+\r
+**/\r
+BOOLEAN\r
+IsForbiddenByDbx (\r
+  IN UINT8                  *AuthData,\r
+  IN UINTN                  AuthDataSize\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   IsForbidden;\r
+  UINT8                     *Data;\r
+  UINTN                     DataSize;\r
+  UINTN                     Index;\r
+  UINT8                     *CertBuffer;\r
+  UINTN                     BufferLength;\r
+  UINT8                     *TrustedCert;\r
+  UINTN                     TrustedCertLength;\r
+  UINT8                     CertNumber;\r
+  UINT8                     *CertPtr;\r
+  UINT8                     *Cert;\r
+  UINTN                     CertSize;\r
+  EFI_TIME                  RevocationTime;\r
+\r
+  //\r
+  // Variable Initialization\r
+  //\r
+  IsForbidden       = FALSE;\r
+  Data              = NULL;\r
+  Cert              = NULL;\r
+  CertBuffer        = NULL;\r
+  BufferLength      = 0;\r
+  TrustedCert       = NULL;\r
+  TrustedCertLength = 0;\r
+\r
+  //\r
+  // The image will not be forbidden if dbx can't be got.\r
+  //\r
+  DataSize = 0;\r
+  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+    if (Data == NULL) {\r
+      return IsForbidden;\r
+    }\r
+\r
+    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return IsForbidden;\r
+  }\r
+\r
+  //\r
+  // Retrieve the certificate stack from AuthData\r
+  // The output CertStack format will be:\r
+  //       UINT8  CertNumber;\r
+  //       UINT32 Cert1Length;\r
+  //       UINT8  Cert1[];\r
+  //       UINT32 Cert2Length;\r
+  //       UINT8  Cert2[];\r
+  //       ...\r
+  //       UINT32 CertnLength;\r
+  //       UINT8  Certn[];\r
+  //\r
+  Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);\r
+  if (BufferLength == 0) {\r
+    IsForbidden = TRUE;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Check if any certificates 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
+    if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
+      //\r
+      // Check the timestamp signature and signing time to determine if the image can be trusted.\r
+      //\r
+      IsForbidden = TRUE;\r
+      if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {\r
+        IsForbidden = FALSE;\r
+      }\r
+      goto Done;\r
+    }\r
+\r
+    CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
+  }\r
+\r
+Done:\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+\r
+  Pkcs7FreeSigners (CertBuffer);\r
+  Pkcs7FreeSigners (TrustedCert);\r
+\r
+  return IsForbidden;\r
+}\r
+\r
+/**\r
+  Check whether the image signature can be verified by the trusted certificates in DB database.\r
+\r
+  @param[in]  AuthData      Pointer to the Authenticode signature retrieved from signed image.\r
+  @param[in]  AuthDataSize  Size of the Authenticode signature in bytes.\r
+\r
+  @retval TRUE         Image passed verification using certificate in db.\r
+  @retval FALSE        Image didn't pass verification using certificate in db.\r
+\r
+**/\r
+BOOLEAN\r
+IsAllowedByDb (\r
   IN UINT8              *AuthData,\r
-  IN UINTN              AuthDataSize,\r
-  IN CHAR16             *VariableName,\r
-  IN EFI_GUID           *VendorGuid\r
+  IN UINTN              AuthDataSize\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -929,14 +1335,14 @@ IsPkcsSignedDataVerifiedBySignatureList (
   VerifyStatus = FALSE;\r
 \r
   DataSize = 0;\r
-  Status   = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
+  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     Data = (UINT8 *) AllocateZeroPool (DataSize);\r
     if (Data == NULL) {\r
       return VerifyStatus;\r
     }\r
 \r
-    Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);\r
+    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
@@ -947,14 +1353,15 @@ IsPkcsSignedDataVerifiedBySignatureList (
     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
+        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
+\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
-          RootCertSize  = CertList->SignatureSize - sizeof (EFI_GUID);\r
+          RootCert     = Cert->SignatureData;\r
+          RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
 \r
           //\r
           // Call AuthenticodeVerify library to Verify Authenticode struct.\r
@@ -968,12 +1375,14 @@ IsPkcsSignedDataVerifiedBySignatureList (
                            mImageDigestSize\r
                            );\r
           if (VerifyStatus) {\r
-            SecureBootHook (VariableName, VendorGuid, CertList->SignatureSize, Cert);\r
+            SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
             goto Done;\r
           }\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
@@ -1108,7 +1517,7 @@ DxeImageVerificationHandler (
   }\r
 \r
   //\r
-  // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION \r
+  // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION\r
   // violates the UEFI spec and has been removed.\r
   //\r
   ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);\r
@@ -1183,8 +1592,8 @@ DxeImageVerificationHandler (
 \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
+    // 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
@@ -1195,7 +1604,7 @@ DxeImageVerificationHandler (
     //\r
     Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
   }\r
-  \r
+\r
   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset.\r
@@ -1203,7 +1612,7 @@ DxeImageVerificationHandler (
     NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
     if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
       SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
-    }        \r
+    }\r
   } else {\r
     //\r
     // Use PE32+ offset.\r
@@ -1219,7 +1628,7 @@ DxeImageVerificationHandler (
   //\r
   if (SecDataDir == NULL || SecDataDir->Size == 0) {\r
     //\r
-    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db", \r
+    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",\r
     // and not be reflected in the security data base "dbx".\r
     //\r
     if (!HashPeImage (HASHALG_SHA256)) {\r
@@ -1247,25 +1656,25 @@ DxeImageVerificationHandler (
   }\r
 \r
   //\r
-  // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7 \r
+  // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7\r
   // "Attribute Certificate Table".\r
   // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.\r
   //\r
   for (OffSet = SecDataDir->VirtualAddress;\r
        OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);\r
-       OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {\r
+       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {\r
     WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);\r
     if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||\r
         (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {\r
       break;\r
     }\r
-    \r
+\r
     //\r
     // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.\r
     //\r
     if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
       //\r
-      // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the \r
+      // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the\r
       // Authenticode specification.\r
       //\r
       PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;\r
@@ -1298,11 +1707,11 @@ DxeImageVerificationHandler (
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
-    \r
+\r
     //\r
     // Check the digital signature against the revoked certificate in forbidden database (dbx).\r
     //\r
-    if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
+    if (IsForbiddenByDbx (AuthData, AuthDataSize)) {\r
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
       VerifyStatus = EFI_ACCESS_DENIED;\r
       break;\r
@@ -1312,7 +1721,7 @@ DxeImageVerificationHandler (
     // Check the digital signature against the valid certificate in allowed database (db).\r
     //\r
     if (EFI_ERROR (VerifyStatus)) {\r
-      if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
+      if (IsAllowedByDb (AuthData, AuthDataSize)) {\r
         VerifyStatus = EFI_SUCCESS;\r
       }\r
     }\r
@@ -1337,7 +1746,7 @@ DxeImageVerificationHandler (
     //\r
     VerifyStatus = EFI_ACCESS_DENIED;\r
   }\r
-  \r
+\r
   if (!EFI_ERROR (VerifyStatus)) {\r
     return EFI_SUCCESS;\r
   } else {\r
@@ -1407,7 +1816,7 @@ OnReadyToBoot (
     return ;\r
   }\r
 \r
-  ImageExeInfoTable->NumberOfImages = 0;  \r
+  ImageExeInfoTable->NumberOfImages = 0;\r
   gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) ImageExeInfoTable);\r
 \r
 }\r
@@ -1434,10 +1843,10 @@ DxeImageVerificationLibConstructor (
   //\r
   EfiCreateEventReadyToBootEx (\r
     TPL_CALLBACK,\r
-    OnReadyToBoot, \r
-    NULL, \r
+    OnReadyToBoot,\r
+    NULL,\r
     &Event\r
-    ); \r
+    );\r
 \r
   return RegisterSecurity2Handler (\r
           DxeImageVerificationHandler,\r