X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=SecurityPkg%2FLibrary%2FDxeImageVerificationLib%2FDxeImageVerificationLib.c;h=c01ffda61608591840557d88c1150a4a0ae6cd1f;hp=959a9b062db3714fa13b244452a93a43cf3b821a;hb=27c93c06c0a81d7b48cac70f9eeff133858b696c;hpb=35a26499af72f2b0131c5d09141f3da00faf6005 diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 959a9b062d..c01ffda616 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -12,7 +12,7 @@ DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept untrusted PE/COFF image and validate its data structure within this image buffer before use. -Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials 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 @@ -1214,6 +1214,12 @@ IsForbiddenByDbx ( BOOLEAN IsForbidden; UINT8 *Data; UINTN DataSize; + EFI_SIGNATURE_LIST *CertList; + UINTN CertListSize; + EFI_SIGNATURE_DATA *CertData; + UINT8 *RootCert; + UINTN RootCertSize; + UINTN CertCount; UINTN Index; UINT8 *CertBuffer; UINTN BufferLength; @@ -1230,6 +1236,10 @@ IsForbiddenByDbx ( // IsForbidden = FALSE; Data = NULL; + CertList = NULL; + CertData = NULL; + RootCert = NULL; + RootCertSize = 0; Cert = NULL; CertBuffer = NULL; BufferLength = 0; @@ -1254,6 +1264,52 @@ IsForbiddenByDbx ( 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 // 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); CertPtr = CertBuffer + 1; for (Index = 0; Index < CertNumber; Index++) { CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr); 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)) { // @@ -1339,6 +1388,9 @@ IsAllowedByDb ( UINTN RootCertSize; UINTN Index; UINTN CertCount; + UINTN DbxDataSize; + UINT8 *DbxData; + EFI_TIME RevocationTime; Data = NULL; CertList = NULL; @@ -1388,7 +1440,30 @@ IsAllowedByDb ( mImageDigestSize ); 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; } @@ -1402,9 +1477,16 @@ IsAllowedByDb ( } Done: + if (VerifyStatus) { + SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert); + } + if (Data != NULL) { FreePool (Data); } + if (DbxData != NULL) { + FreePool (DbxData); + } return VerifyStatus; }