mirror of https://github.com/acidanthera/audk.git
Update the DxeImageVerificationLib to support for Authenticode-signed UEFI images with multiple signatures.
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com> Reviewed-by: Dong Guo <guo.dong@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14141 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
944c84a6dd
commit
6de4c35f99
|
@ -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 - 2012, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2009 - 2013, 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
|
||||||
|
@ -966,43 +966,6 @@ Done:
|
||||||
return VerifyStatus;
|
return VerifyStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
|
|
||||||
|
|
||||||
@param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
|
|
||||||
@param[in] AuthDataSize Size of the Authenticode Signature in bytes.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS Image pass verification.
|
|
||||||
@retval EFI_SECURITY_VIOLATION Image fail verification.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
VerifyCertPkcsSignedData (
|
|
||||||
IN UINT8 *AuthData,
|
|
||||||
IN UINTN AuthDataSize
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// 1: Find certificate from DBX forbidden database for revoked certificate.
|
|
||||||
//
|
|
||||||
if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
|
|
||||||
//
|
|
||||||
// DBX is forbidden database, if Authenticode verification pass with
|
|
||||||
// one of the certificate in DBX, this image should be rejected.
|
|
||||||
//
|
|
||||||
return EFI_SECURITY_VIOLATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// 2: Find certificate from DB database and try to verify authenticode struct.
|
|
||||||
//
|
|
||||||
if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return EFI_SECURITY_VIOLATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Provide verification service for signed images, which include both signature validation
|
Provide verification service for signed images, which include both signature validation
|
||||||
and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
|
and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
|
||||||
|
@ -1011,25 +974,14 @@ VerifyCertPkcsSignedData (
|
||||||
In this implementation, only verify external executables when in USER MODE.
|
In this implementation, only verify external executables when in USER MODE.
|
||||||
Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
|
Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
|
||||||
|
|
||||||
The image verification process is:
|
The image verification policy is:
|
||||||
If the image is signed,
|
If the image is signed,
|
||||||
If the image's certificate verifies against a certificate (root or intermediate) in the allowed
|
At least one valid signature or at least one hash value of the image must match a record
|
||||||
database (DB) and not in the forbidden database (DBX), the certificate verification is passed.
|
in the security database "db", and no valid signature nor any hash value of the image may
|
||||||
If the image's hash digest is in DBX,
|
be reflected in the security database "dbx".
|
||||||
deny execution.
|
|
||||||
If not,
|
|
||||||
run it.
|
|
||||||
If the Image's certificate verification failed.
|
|
||||||
If the Image's Hash is in DB and not in DBX,
|
|
||||||
run it.
|
|
||||||
Otherwise,
|
|
||||||
deny execution.
|
|
||||||
Otherwise, the image is not signed,
|
Otherwise, the image is not signed,
|
||||||
Is the Image's Hash in DBX?
|
The SHA256 hash value of the image must match a record in the security database "db", and
|
||||||
If yes, deny execution.
|
not be reflected in the security data base "dbx".
|
||||||
If not, is the Image's Hash in DB?
|
|
||||||
If yes, run it.
|
|
||||||
If not, deny execution.
|
|
||||||
|
|
||||||
Caution: This function may receive untrusted input.
|
Caution: This function may receive untrusted input.
|
||||||
PE/COFF image is external input, so this function will validate its data structure
|
PE/COFF image is external input, so this function will validate its data structure
|
||||||
|
@ -1084,12 +1036,12 @@ DxeImageVerificationHandler (
|
||||||
UINT8 *SecureBoot;
|
UINT8 *SecureBoot;
|
||||||
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
||||||
UINT32 NumberOfRvaAndSizes;
|
UINT32 NumberOfRvaAndSizes;
|
||||||
UINT32 CertSize;
|
|
||||||
WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
|
WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
|
||||||
WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
|
WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
|
||||||
UINT8 *AuthData;
|
UINT8 *AuthData;
|
||||||
UINTN AuthDataSize;
|
UINTN AuthDataSize;
|
||||||
EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
|
EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
|
||||||
|
UINT32 OffSet;
|
||||||
|
|
||||||
SignatureList = NULL;
|
SignatureList = NULL;
|
||||||
SignatureListSize = 0;
|
SignatureListSize = 0;
|
||||||
|
@ -1098,6 +1050,8 @@ DxeImageVerificationHandler (
|
||||||
PkcsCertData = NULL;
|
PkcsCertData = NULL;
|
||||||
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
|
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
|
||||||
Status = EFI_ACCESS_DENIED;
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
VerifyStatus = EFI_ACCESS_DENIED;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the image type and get policy setting.
|
// Check the image type and get policy setting.
|
||||||
//
|
//
|
||||||
|
@ -1230,9 +1184,13 @@ DxeImageVerificationHandler (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((SecDataDir == NULL) || ((SecDataDir != NULL) && (SecDataDir->Size == 0))) {
|
|
||||||
//
|
//
|
||||||
// This image is not signed.
|
// Start Image Validation.
|
||||||
|
//
|
||||||
|
if (SecDataDir == NULL || SecDataDir->Size == 0) {
|
||||||
|
//
|
||||||
|
// This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",
|
||||||
|
// and not be reflected in the security data base "dbx".
|
||||||
//
|
//
|
||||||
if (!HashPeImage (HASHALG_SHA256)) {
|
if (!HashPeImage (HASHALG_SHA256)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
|
@ -1259,14 +1217,17 @@ DxeImageVerificationHandler (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Verify signature of executables.
|
// Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
|
||||||
|
// "Attribute Certificate Table".
|
||||||
|
// The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
|
||||||
//
|
//
|
||||||
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + SecDataDir->VirtualAddress);
|
for (OffSet = SecDataDir->VirtualAddress;
|
||||||
|
OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
|
||||||
CertSize = sizeof (WIN_CERTIFICATE);
|
OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {
|
||||||
|
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
|
||||||
if ((SecDataDir->Size <= CertSize) || (SecDataDir->Size < WinCertificate->dwLength)) {
|
if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
|
||||||
goto Done;
|
(SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1279,74 +1240,79 @@ DxeImageVerificationHandler (
|
||||||
//
|
//
|
||||||
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
|
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
|
||||||
if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
|
if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
|
||||||
goto Done;
|
break;
|
||||||
}
|
}
|
||||||
AuthData = PkcsCertData->CertData;
|
AuthData = PkcsCertData->CertData;
|
||||||
AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
|
AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
|
||||||
|
|
||||||
Status = HashPeImageByType (AuthData, AuthDataSize);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
|
|
||||||
} else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
|
} else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
|
||||||
//
|
//
|
||||||
// The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
|
// The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
|
||||||
//
|
//
|
||||||
WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
|
WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
|
||||||
if (!CompareGuid(&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid) ||
|
if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
|
||||||
(WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData))) {
|
break;
|
||||||
goto Done;
|
}
|
||||||
|
if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
AuthData = WinCertUefiGuid->CertData;
|
AuthData = WinCertUefiGuid->CertData;
|
||||||
AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
|
AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
|
||||||
|
} else {
|
||||||
|
if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Status = HashPeImageByType (AuthData, AuthDataSize);
|
Status = HashPeImageByType (AuthData, AuthDataSize);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
goto Done;
|
continue;
|
||||||
}
|
}
|
||||||
VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
|
|
||||||
} else {
|
//
|
||||||
goto Done;
|
// Check the digital signature against the revoked certificate in forbidden database (dbx).
|
||||||
|
//
|
||||||
|
if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
|
||||||
|
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
|
||||||
|
VerifyStatus = EFI_ACCESS_DENIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the digital signature against the valid certificate in allowed database (db).
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (VerifyStatus)) {
|
||||||
|
if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
|
||||||
|
VerifyStatus = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the image's hash value.
|
||||||
|
//
|
||||||
|
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
|
||||||
|
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
|
||||||
|
VerifyStatus = EFI_ACCESS_DENIED;
|
||||||
|
break;
|
||||||
|
} else if (EFI_ERROR (VerifyStatus)) {
|
||||||
|
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
|
||||||
|
VerifyStatus = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
|
||||||
|
//
|
||||||
|
// The Size in Certificate Table or the attribute certicate table is corrupted.
|
||||||
|
//
|
||||||
|
VerifyStatus = EFI_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EFI_ERROR (VerifyStatus)) {
|
if (!EFI_ERROR (VerifyStatus)) {
|
||||||
//
|
|
||||||
// Verification is passed.
|
|
||||||
// Continue to check the image digest in signature database.
|
|
||||||
//
|
|
||||||
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {
|
|
||||||
//
|
|
||||||
// Executable signature verification passes, but is found in forbidden signature database.
|
|
||||||
//
|
|
||||||
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
|
|
||||||
Status = EFI_ACCESS_DENIED;
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// For image verification against enrolled X.509 certificate(root or intermediate),
|
|
||||||
// no need to check image's hash in the allowed database.
|
|
||||||
//
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//
|
|
||||||
// Verification failure.
|
|
||||||
//
|
|
||||||
if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize) &&
|
|
||||||
IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {
|
|
||||||
//
|
|
||||||
// Verification fail, Image Hash is not in forbidden database (DBX),
|
|
||||||
// and Image Hash is in allowed database (DB).
|
|
||||||
//
|
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
} else {
|
|
||||||
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
|
|
||||||
Status = EFI_ACCESS_DENIED;
|
Status = EFI_ACCESS_DENIED;
|
||||||
}
|
if (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED || Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
|
||||||
}
|
|
||||||
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
//
|
//
|
||||||
// Get image hash value as executable's signature.
|
// Get image hash value as executable's signature.
|
||||||
//
|
//
|
||||||
|
@ -1363,6 +1329,7 @@ DxeImageVerificationHandler (
|
||||||
Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
|
Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
|
||||||
CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
|
CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
if (Status != EFI_SUCCESS) {
|
if (Status != EFI_SUCCESS) {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
The internal header file includes the common header files, defines
|
The internal header file includes the common header files, defines
|
||||||
internal structure and functions used by ImageVerificationLib.
|
internal structure and functions used by ImageVerificationLib.
|
||||||
|
|
||||||
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2009 - 2013, 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
|
||||||
|
@ -43,6 +43,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#define MAX_NOTIFY_STRING_LEN 64
|
#define MAX_NOTIFY_STRING_LEN 64
|
||||||
#define TWO_BYTE_ENCODE 0x82
|
#define TWO_BYTE_ENCODE 0x82
|
||||||
|
|
||||||
|
#define ALIGNMENT_SIZE 8
|
||||||
|
#define ALIGN_SIZE(a) (((a) % ALIGNMENT_SIZE) ? ALIGNMENT_SIZE - ((a) % ALIGNMENT_SIZE) : 0)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Image type definitions
|
// Image type definitions
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue