Correct the DBX and Certificate Hash Checking.
Add the missed image signature verification against DBX; and add the missed logic to enhance the certificate hash checking when handling DB database. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Long, Qin" <qin.long@intel.com> Reviewed-by: "Fu, Siyuan" <siyuan.fu@intel.com> Reviewed-by: "Dong, Guo" <guo.dong@initel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16744 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -12,7 +12,7 @@
|
|||||||
DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
|
DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
|
||||||
untrusted PE/COFF image and validate its data structure within this image buffer before use.
|
untrusted PE/COFF image and validate its data structure within this image buffer before use.
|
||||||
|
|
||||||
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -1214,6 +1214,12 @@ IsForbiddenByDbx (
|
|||||||
BOOLEAN IsForbidden;
|
BOOLEAN IsForbidden;
|
||||||
UINT8 *Data;
|
UINT8 *Data;
|
||||||
UINTN DataSize;
|
UINTN DataSize;
|
||||||
|
EFI_SIGNATURE_LIST *CertList;
|
||||||
|
UINTN CertListSize;
|
||||||
|
EFI_SIGNATURE_DATA *CertData;
|
||||||
|
UINT8 *RootCert;
|
||||||
|
UINTN RootCertSize;
|
||||||
|
UINTN CertCount;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINT8 *CertBuffer;
|
UINT8 *CertBuffer;
|
||||||
UINTN BufferLength;
|
UINTN BufferLength;
|
||||||
@ -1230,6 +1236,10 @@ IsForbiddenByDbx (
|
|||||||
//
|
//
|
||||||
IsForbidden = FALSE;
|
IsForbidden = FALSE;
|
||||||
Data = NULL;
|
Data = NULL;
|
||||||
|
CertList = NULL;
|
||||||
|
CertData = NULL;
|
||||||
|
RootCert = NULL;
|
||||||
|
RootCertSize = 0;
|
||||||
Cert = NULL;
|
Cert = NULL;
|
||||||
CertBuffer = NULL;
|
CertBuffer = NULL;
|
||||||
BufferLength = 0;
|
BufferLength = 0;
|
||||||
@ -1254,6 +1264,52 @@ IsForbiddenByDbx (
|
|||||||
return IsForbidden;
|
return IsForbidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Verify image signature with RAW X509 certificates in DBX database.
|
||||||
|
// If passed, the image will be forbidden.
|
||||||
|
//
|
||||||
|
CertList = (EFI_SIGNATURE_LIST *) Data;
|
||||||
|
CertListSize = DataSize;
|
||||||
|
while ((CertListSize > 0) && (CertListSize >= 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);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Call AuthenticodeVerify library to Verify Authenticode struct.
|
||||||
|
//
|
||||||
|
IsForbidden = AuthenticodeVerify (
|
||||||
|
AuthData,
|
||||||
|
AuthDataSize,
|
||||||
|
RootCert,
|
||||||
|
RootCertSize,
|
||||||
|
mImageDigest,
|
||||||
|
mImageDigestSize
|
||||||
|
);
|
||||||
|
if (IsForbidden) {
|
||||||
|
SecureBootHook (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CertListSize -= CertList->SignatureListSize;
|
||||||
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check X.509 Certificate Hash & Possible Timestamp.
|
||||||
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Retrieve the certificate stack from AuthData
|
// Retrieve the certificate stack from AuthData
|
||||||
// The output CertStack format will be:
|
// The output CertStack format will be:
|
||||||
@ -1273,20 +1329,13 @@ IsForbiddenByDbx (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if any certificates in AuthData is in the forbidden database.
|
// Check if any hash of certificates embedded in AuthData is in the forbidden database.
|
||||||
//
|
//
|
||||||
CertNumber = (UINT8) (*CertBuffer);
|
CertNumber = (UINT8) (*CertBuffer);
|
||||||
CertPtr = CertBuffer + 1;
|
CertPtr = CertBuffer + 1;
|
||||||
for (Index = 0; Index < CertNumber; Index++) {
|
for (Index = 0; Index < CertNumber; Index++) {
|
||||||
CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);
|
CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);
|
||||||
Cert = (UINT8 *)CertPtr + sizeof (UINT32);
|
Cert = (UINT8 *)CertPtr + sizeof (UINT32);
|
||||||
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Cert, &gEfiCertX509Guid, CertSize)) {
|
|
||||||
//
|
|
||||||
// Raw certificate in dbx means the image signed by the certificate is forbidden.
|
|
||||||
//
|
|
||||||
IsForbidden = TRUE;
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {
|
if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {
|
||||||
//
|
//
|
||||||
@ -1339,6 +1388,9 @@ IsAllowedByDb (
|
|||||||
UINTN RootCertSize;
|
UINTN RootCertSize;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINTN CertCount;
|
UINTN CertCount;
|
||||||
|
UINTN DbxDataSize;
|
||||||
|
UINT8 *DbxData;
|
||||||
|
EFI_TIME RevocationTime;
|
||||||
|
|
||||||
Data = NULL;
|
Data = NULL;
|
||||||
CertList = NULL;
|
CertList = NULL;
|
||||||
@ -1388,7 +1440,30 @@ IsAllowedByDb (
|
|||||||
mImageDigestSize
|
mImageDigestSize
|
||||||
);
|
);
|
||||||
if (VerifyStatus) {
|
if (VerifyStatus) {
|
||||||
SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);
|
//
|
||||||
|
// Here We still need to check if this RootCert's Hash is revoked
|
||||||
|
//
|
||||||
|
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);
|
||||||
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
DbxData = (UINT8 *) AllocateZeroPool (DataSize);
|
||||||
|
if (DbxData == NULL) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {
|
||||||
|
//
|
||||||
|
// Check the timestamp signature and signing time to determine if the image can be trusted.
|
||||||
|
//
|
||||||
|
VerifyStatus = PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime);
|
||||||
|
}
|
||||||
|
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1402,9 +1477,16 @@ IsAllowedByDb (
|
|||||||
}
|
}
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
|
if (VerifyStatus) {
|
||||||
|
SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);
|
||||||
|
}
|
||||||
|
|
||||||
if (Data != NULL) {
|
if (Data != NULL) {
|
||||||
FreePool (Data);
|
FreePool (Data);
|
||||||
}
|
}
|
||||||
|
if (DbxData != NULL) {
|
||||||
|
FreePool (DbxData);
|
||||||
|
}
|
||||||
|
|
||||||
return VerifyStatus;
|
return VerifyStatus;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user