@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
//\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
@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
- @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
\r
**/\r
-BOOLEAN\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 EFI_TIME *RevocationTime,\r
+ OUT BOOLEAN *IsFound\r
)\r
{\r
- BOOLEAN IsFound;\r
- BOOLEAN Status;\r
+ EFI_STATUS Status;\r
EFI_SIGNATURE_LIST *DbxList;\r
UINTN DbxSize;\r
EFI_SIGNATURE_DATA *CertHash;\r
UINT8 *TBSCert;\r
UINTN TBSCertSize;\r
\r
- IsFound = FALSE;\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 FALSE;\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 FALSE;\r
+ return Status;\r
}\r
\r
while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
if (HashCtx == NULL) {\r
goto Done;\r
}\r
- Status = mHash[HashAlg].HashInit (HashCtx);\r
- if (!Status) {\r
+ if (!mHash[HashAlg].HashInit (HashCtx)) {\r
goto Done;\r
}\r
- Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
- if (!Status) {\r
+ if (!mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize)) {\r
goto Done;\r
}\r
- Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);\r
- if (!Status) {\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
//\r
// Hash of Certificate is found in forbidden database.\r
//\r
- IsFound = TRUE;\r
+ Status = EFI_SUCCESS;\r
+ *IsFound = TRUE;\r
\r
//\r
// Return the revocation time.\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 IsFound;\r
+ return Status;\r
}\r
\r
/**\r
{\r
EFI_STATUS Status;\r
BOOLEAN IsForbidden;\r
+ BOOLEAN IsFound;\r
UINT8 *Data;\r
UINTN DataSize;\r
EFI_SIGNATURE_LIST *CertList;\r
// 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
//\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
//\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
+ } 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
+ } else {\r
+ IsForbidden = TRUE;\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
+ goto Done;\r
}\r
- DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
- goto Done;\r
}\r
\r
}\r
{\r
EFI_STATUS Status;\r
BOOLEAN VerifyStatus;\r
+ BOOLEAN IsFound;\r
EFI_SIGNATURE_LIST *CertList;\r
EFI_SIGNATURE_DATA *CertData;\r
UINTN DataSize;\r
RootCertSize = 0;\r
VerifyStatus = FALSE;\r
\r
+ //\r
+ // Fetch 'db' content. If 'db' doesn't exist or encounters problem to get the\r
+ // data, return not-allowed-by-db (FALSE).\r
+ //\r
DataSize = 0;\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
+ ASSERT (EFI_ERROR (Status));\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return VerifyStatus;\r
+ }\r
+\r
+ Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+ if (Data == NULL) {\r
+ return VerifyStatus;\r
+ }\r
+\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'.\r
+ // If any other errors occured, no need to check 'db' but just return\r
+ // not-allowed-by-db (FALSE) to avoid bypass.\r
+ //\r
+ DbxDataSize = 0;\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);\r
+ ASSERT (EFI_ERROR (Status));\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ if (Status != EFI_NOT_FOUND) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // 'dbx' does not exist. Continue to check 'db'.\r
+ //\r
+ } else {\r
+ //\r
+ // 'dbx' exists. Get its content.\r
+ //\r
+ DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize);\r
+ if (DbxData == NULL) {\r
+ goto Done;\r
}\r
\r
- Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
+ }\r
\r
- //\r
- // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.\r
- //\r
- CertList = (EFI_SIGNATURE_LIST *) Data;\r
- while ((DataSize > 0) && (DataSize >= 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
+ // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data.\r
+ //\r
+ CertList = (EFI_SIGNATURE_LIST *) Data;\r
+ while ((DataSize > 0) && (DataSize >= 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
+ 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
+ VerifyStatus = AuthenticodeVerify (\r
+ AuthData,\r
+ AuthDataSize,\r
+ RootCert,\r
+ RootCertSize,\r
+ mImageDigest,\r
+ mImageDigestSize\r
+ );\r
+ if (VerifyStatus) {\r
//\r
- // Call AuthenticodeVerify library to Verify Authenticode struct.\r
+ // The image is signed and its signature is found in 'db'.\r
//\r
- VerifyStatus = AuthenticodeVerify (\r
- AuthData,\r
- AuthDataSize,\r
- RootCert,\r
- RootCertSize,\r
- mImageDigest,\r
- mImageDigestSize\r
- );\r
- if (VerifyStatus) {\r
+ if (DbxData != NULL) {\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
+ Status = IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime, &IsFound);\r
if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {\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
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
- CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+ //\r
+ // There's no 'dbx' to check revocation time against (must-be pass),\r
+ // or, there's revocation time found in 'dbx' and checked againt 'dbt'\r
+ // (maybe pass or fail, depending on timestamp compare result). Either\r
+ // way the verification job has been completed at this point.\r
+ //\r
+ goto Done;\r
}\r
- }\r
\r
- DataSize -= CertList->SignatureListSize;\r
- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+ CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+ }\r
}\r
+\r
+ DataSize -= CertList->SignatureListSize;\r
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
}\r
\r
Done:\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
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
SignatureList->SignatureHeaderSize = 0;\r
\r
Failed:\r
//\r
- // Policy decides to defer or reject the image; add its information in image executable information table.\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
FreePool (SignatureList);\r
}\r
\r
- return EFI_SECURITY_VIOLATION;\r
+ if (Policy == DEFER_EXECUTE_ON_SECURITY_VIOLATION) {\r
+ return EFI_SECURITY_VIOLATION;\r
+ }\r
+ return EFI_ACCESS_DENIED;\r
}\r
\r
/**\r