+/**\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
+ @param[out] IsFound Search result. Only valid if EFI_SUCCESS returned.\r
+\r
+ @retval EFI_SUCCESS Finished the search without any error.\r
+ @retval Others Error occurred in the search of database.\r
+\r
+**/\r
+EFI_STATUS\r
+IsCertHashFoundInDatabase (\r
+ IN UINT8 *Certificate,\r
+ IN UINTN CertSize,\r
+ IN EFI_SIGNATURE_LIST *SignatureList,\r
+ IN UINTN SignatureListSize,\r
+ OUT EFI_TIME *RevocationTime,\r
+ OUT BOOLEAN *IsFound\r
+ )\r
+{\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
+ UINT8 *TBSCert;\r
+ UINTN TBSCertSize;\r
+\r
+ Status = EFI_ABORTED;\r
+ *IsFound = FALSE;\r
+ DbxList = SignatureList;\r
+ DbxSize = SignatureListSize;\r
+ HashCtx = NULL;\r
+ HashAlg = HASHALG_MAX;\r
+\r
+ if ((RevocationTime == NULL) || (DbxList == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Retrieve the TBSCertificate from the X.509 Certificate.\r
+ //\r
+ if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {\r
+ return Status;\r
+ }\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 TBSCertificate 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
+ if (!mHash[HashAlg].HashInit (HashCtx)) {\r
+ goto Done;\r
+ }\r
+ if (!mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize)) {\r
+ goto Done;\r
+ }\r
+ if (!mHash[HashAlg].HashFinal (HashCtx, CertDigest)) {\r
+ goto Done;\r
+ }\r
+\r
+ FreePool (HashCtx);\r
+ HashCtx = NULL;\r
+\r
+ SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;\r
+ CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);\r
+ CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;\r
+ 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
+ Status = EFI_SUCCESS;\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
+ Status = EFI_SUCCESS;\r
+\r
+Done:\r
+ if (HashCtx != NULL) {\r
+ FreePool (HashCtx);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r