Skip to content

Commit

Permalink
SecurityPkg/DxeImageVerificationLib: Differentiate error/search resul…
Browse files Browse the repository at this point in the history
…t (2) (CVE-2019-14575)

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
IsSignatureFoundInDatabase() 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.

All intermediate results inside this function will be checked and
returned immediately upon any failure or error, like out-of-resource,
hash calculation error or certificate retrieval failure.

Cc: Jiewen Yao <[email protected]>
Cc: Chao Zhang <[email protected]>
Signed-off-by: Jian J Wang <[email protected]>
Reviewed-by: Laszlo Ersek <[email protected]>
Reviewed-by: Jiewen Yao <[email protected]>
  • Loading branch information
Jian J Wang authored and mergify[bot] committed Feb 19, 2020
1 parent cb30c8f commit b1c1147
Showing 1 changed file with 58 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -955,17 +955,19 @@ IsCertHashFoundInDatabase (
@param[in] Signature Pointer to signature that is searched for.
@param[in] CertType Pointer to hash algorithm.
@param[in] SignatureSize Size of Signature.
@param[out] IsFound Search result. Only valid if EFI_SUCCESS returned
@return TRUE Found the signature in the variable database.
@return FALSE Not found the signature in the variable database.
@retval EFI_SUCCESS Finished the search without any error.
@retval Others Error occurred in the search of database.
**/
BOOLEAN
EFI_STATUS
IsSignatureFoundInDatabase (
IN CHAR16 *VariableName,
IN UINT8 *Signature,
IN EFI_GUID *CertType,
IN UINTN SignatureSize
IN CHAR16 *VariableName,
IN UINT8 *Signature,
IN EFI_GUID *CertType,
IN UINTN SignatureSize,
OUT BOOLEAN *IsFound
)
{
EFI_STATUS Status;
Expand All @@ -975,22 +977,28 @@ IsSignatureFoundInDatabase (
UINT8 *Data;
UINTN Index;
UINTN CertCount;
BOOLEAN IsFound;

//
// Read signature database variable.
//
IsFound = FALSE;
*IsFound = FALSE;
Data = NULL;
DataSize = 0;
Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
if (Status != EFI_BUFFER_TOO_SMALL) {
return FALSE;
if (Status == EFI_NOT_FOUND) {
//
// No database, no need to search.
//
Status = EFI_SUCCESS;
}

return Status;
}

Data = (UINT8 *) AllocateZeroPool (DataSize);
if (Data == NULL) {
return FALSE;
return EFI_OUT_OF_RESOURCES;
}

Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
Expand All @@ -1010,7 +1018,7 @@ IsSignatureFoundInDatabase (
//
// Find the signature in database.
//
IsFound = TRUE;
*IsFound = TRUE;
//
// Entries in UEFI_IMAGE_SECURITY_DATABASE that are used to validate image should be measured
//
Expand All @@ -1023,7 +1031,7 @@ IsSignatureFoundInDatabase (
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
}

if (IsFound) {
if (*IsFound) {
break;
}
}
Expand All @@ -1037,7 +1045,7 @@ IsSignatureFoundInDatabase (
FreePool (Data);
}

return IsFound;
return Status;
}

/**
Expand Down Expand Up @@ -1648,6 +1656,8 @@ DxeImageVerificationHandler (
CHAR16 *NameStr;
RETURN_STATUS PeCoffStatus;
EFI_STATUS HashStatus;
EFI_STATUS DbStatus;
BOOLEAN IsFound;

SignatureList = NULL;
SignatureListSize = 0;
Expand All @@ -1656,7 +1666,7 @@ DxeImageVerificationHandler (
PkcsCertData = NULL;
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
IsVerified = FALSE;

IsFound = FALSE;

//
// Check the image type and get policy setting.
Expand Down Expand Up @@ -1798,15 +1808,29 @@ DxeImageVerificationHandler (
goto Failed;
}

if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
DbStatus = IsSignatureFoundInDatabase (
EFI_IMAGE_SECURITY_DATABASE1,
mImageDigest,
&mCertType,
mImageDigestSize,
&IsFound
);
if (EFI_ERROR (DbStatus) || IsFound) {
//
// Image Hash is in forbidden database (DBX).
//
DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));
goto Failed;
}

if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
DbStatus = IsSignatureFoundInDatabase (
EFI_IMAGE_SECURITY_DATABASE,
mImageDigest,
&mCertType,
mImageDigestSize,
&IsFound
);
if (!EFI_ERROR (DbStatus) && IsFound) {
//
// Image Hash is in allowed database (DB).
//
Expand Down Expand Up @@ -1894,14 +1918,29 @@ DxeImageVerificationHandler (
//
// Check the image's hash value.
//
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
DbStatus = IsSignatureFoundInDatabase (
EFI_IMAGE_SECURITY_DATABASE1,
mImageDigest,
&mCertType,
mImageDigestSize,
&IsFound
);
if (EFI_ERROR (DbStatus) || IsFound) {
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s hash of image is found in DBX.\n", mHashTypeStr));
IsVerified = FALSE;
break;
}

if (!IsVerified) {
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
DbStatus = IsSignatureFoundInDatabase (
EFI_IMAGE_SECURITY_DATABASE,
mImageDigest,
&mCertType,
mImageDigestSize,
&IsFound
);
if (!EFI_ERROR (DbStatus) && IsFound) {
IsVerified = TRUE;
} else {
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));
Expand Down

0 comments on commit b1c1147

Please sign in to comment.