REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1608
To avoid false-negative issue in check hash against dbx, both error
condition (as return value) and check result (as out parameter) of
IsCertHashFoundInDatabase() are added. So the caller of this function
will know exactly if a failure is caused by a black list hit or
other error happening, and enforce a more secure operation to prevent
secure boot from being bypassed. For a white list check (db), there's
no such necessity.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
@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[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
- @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
+ @retval EFI_SUCCESS Finished the search without any error.\r
+ @retval Others Error occurred in the search of database.\r
IsCertHashFoundInDatabase (\r
IN UINT8 *Certificate,\r
IN UINTN CertSize,\r
IN EFI_SIGNATURE_LIST *SignatureList,\r
IN UINTN SignatureListSize,\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 EFI_TIME *RevocationTime,\r
+ OUT BOOLEAN *IsFound\r
- BOOLEAN IsFound;\r
- BOOLEAN Status;\r
EFI_SIGNATURE_LIST *DbxList;\r
UINTN DbxSize;\r
EFI_SIGNATURE_DATA *CertHash;\r
EFI_SIGNATURE_LIST *DbxList;\r
UINTN DbxSize;\r
EFI_SIGNATURE_DATA *CertHash;\r
UINT8 *TBSCert;\r
UINTN TBSCertSize;\r
\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
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
}\r
\r
//\r
// Retrieve the TBSCertificate from the X.509 Certificate.\r
//\r
if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {\r
}\r
\r
while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
}\r
\r
while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
if (HashCtx == NULL) {\r
goto Done;\r
}\r
if (HashCtx == NULL) {\r
goto Done;\r
}\r
- Status = mHash[HashAlg].HashInit (HashCtx);\r
- if (!Status) {\r
+ if (!mHash[HashAlg].HashInit (HashCtx)) {\r
- Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
- if (!Status) {\r
+ if (!mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize)) {\r
- Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);\r
- if (!Status) {\r
+ if (!mHash[HashAlg].HashFinal (HashCtx, CertDigest)) {\r
//\r
// Hash of Certificate is found in forbidden database.\r
//\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
//\r
// Return the revocation time.\r
DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
}\r
\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
Done:\r
if (HashCtx != NULL) {\r
FreePool (HashCtx);\r
}\r
\r
{\r
EFI_STATUS Status;\r
BOOLEAN IsForbidden;\r
{\r
EFI_STATUS Status;\r
BOOLEAN IsForbidden;\r
UINT8 *Data;\r
UINTN DataSize;\r
EFI_SIGNATURE_LIST *CertList;\r
UINT8 *Data;\r
UINTN DataSize;\r
EFI_SIGNATURE_LIST *CertList;\r
//\r
CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
\r
//\r
CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
\r
- if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
+ Status = IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime, &IsFound);\r
+ if (EFI_ERROR (Status)) {\r
- // Check the timestamp signature and signing time to determine if the image can be trusted.\r
+ // Error in searching dbx. Consider it as 'found'. RevocationTime might\r
+ // not be valid in such situation.\r
//\r
IsForbidden = TRUE;\r
//\r
IsForbidden = TRUE;\r
+ } else if (IsFound) {\r
+ //\r
+ // Found Cert in dbx successfully. Check the timestamp signature and\r
+ // signing time to determine if the image can be trusted.\r
+ //\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
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
+ } else {\r
+ IsForbidden = TRUE;\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
+ goto Done;\r
- DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
- goto Done;\r
{\r
EFI_STATUS Status;\r
BOOLEAN VerifyStatus;\r
{\r
EFI_STATUS Status;\r
BOOLEAN VerifyStatus;\r
EFI_SIGNATURE_LIST *CertList;\r
EFI_SIGNATURE_DATA *CertData;\r
UINTN DataSize;\r
EFI_SIGNATURE_LIST *CertList;\r
EFI_SIGNATURE_DATA *CertData;\r
UINTN DataSize;\r
//\r
// Here We still need to check if this RootCert's Hash is revoked\r
//\r
//\r
// Here We still need to check if this RootCert's Hash is revoked\r
//\r
- if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {\r
+ Status = IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime, &IsFound);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Error in searching dbx. Consider it as 'found'. RevocationTime might\r
+ // not be valid in such situation.\r
+ //\r
+ VerifyStatus = FALSE;\r
+ } else if (IsFound) {\r
//\r
// Check the timestamp signature and signing time to determine if the RootCert can be trusted.\r
//\r
//\r
// Check the timestamp signature and signing time to determine if the RootCert can be trusted.\r
//\r