diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index ed5dbf26b041..8739d1fa2946 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -1412,76 +1412,92 @@ IsAllowedByDb ( RootCertSize = 0; VerifyStatus = FALSE; + // + // Fetch 'db' content. If 'db' doesn't exist or encounters problem to get the + // data, return not-allowed-by-db (FALSE). + // DataSize = 0; Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - Data = (UINT8 *) AllocateZeroPool (DataSize); - if (Data == NULL) { - return VerifyStatus; + ASSERT (EFI_ERROR (Status)); + if (Status != EFI_BUFFER_TOO_SMALL) { + return VerifyStatus; + } + + Data = (UINT8 *) AllocateZeroPool (DataSize); + if (Data == NULL) { + return VerifyStatus; + } + + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'. + // If any other errors occured, no need to check 'db' but just return + // not-allowed-by-db (FALSE) to avoid bypass. + // + DbxDataSize = 0; + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL); + ASSERT (EFI_ERROR (Status)); + if (Status != EFI_BUFFER_TOO_SMALL) { + if (Status != EFI_NOT_FOUND) { + goto Done; + } + // + // 'dbx' does not exist. Continue to check 'db'. + // + } else { + // + // 'dbx' exists. Get its content. + // + DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize); + if (DbxData == NULL) { + goto Done; } - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data); + Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData); if (EFI_ERROR (Status)) { goto Done; } + } - // - // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data. - // - CertList = (EFI_SIGNATURE_LIST *) Data; - while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) { - if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { - CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + // + // Find X509 certificate in Signature List to verify the signature in pkcs7 signed data. + // + CertList = (EFI_SIGNATURE_LIST *) Data; + while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) { + if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { + CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - for (Index = 0; Index < CertCount; Index++) { - // - // Iterate each Signature Data Node within this CertList for verify. - // - RootCert = CertData->SignatureData; - RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID); + for (Index = 0; Index < CertCount; Index++) { + // + // Iterate each Signature Data Node within this CertList for verify. + // + RootCert = CertData->SignatureData; + RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID); + // + // Call AuthenticodeVerify library to Verify Authenticode struct. + // + VerifyStatus = AuthenticodeVerify ( + AuthData, + AuthDataSize, + RootCert, + RootCertSize, + mImageDigest, + mImageDigestSize + ); + if (VerifyStatus) { // - // Call AuthenticodeVerify library to Verify Authenticode struct. + // The image is signed and its signature is found in 'db'. // - VerifyStatus = AuthenticodeVerify ( - AuthData, - AuthDataSize, - RootCert, - RootCertSize, - mImageDigest, - mImageDigestSize - ); - if (VerifyStatus) { + if (DbxData != NULL) { // // Here We still need to check if this RootCert's Hash is revoked // - DbxDataSize = 0; - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL); - if (Status != EFI_BUFFER_TOO_SMALL) { - if (Status != EFI_NOT_FOUND) { - VerifyStatus = FALSE; - } - goto Done; - } - DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize); - if (DbxData == NULL) { - // - // Force not-allowed-by-db to avoid bypass - // - VerifyStatus = FALSE; - goto Done; - } - - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData); - if (EFI_ERROR (Status)) { - // - // Force not-allowed-by-db to avoid bypass - // - VerifyStatus = FALSE; - goto Done; - } - if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) { // // Check the timestamp signature and signing time to determine if the RootCert can be trusted. @@ -1491,17 +1507,23 @@ IsAllowedByDb ( DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed and signature is accepted by DB, but its root cert failed the timestamp check.\n")); } } - - goto Done; } - CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize); + // + // There's no 'dbx' to check revocation time against (must-be pass), + // or, there's revocation time found in 'dbx' and checked againt 'dbt' + // (maybe pass or fail, depending on timestamp compare result). Either + // way the verification job has been completed at this point. + // + goto Done; } - } - DataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); + CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize); + } } + + DataSize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); } Done: