Update the DxeImageVerificationLib to handle the signed image which CertType is set to EFI_CERT_TYPE_PKCS7_GUID.

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@13672 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
sfu5 2012-08-23 07:55:35 +00:00
parent f6e233534e
commit f6f9031f8e
2 changed files with 63 additions and 29 deletions

View File

@ -31,7 +31,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// //
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader; EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
UINT32 mPeCoffHeaderOffset; UINT32 mPeCoffHeaderOffset;
EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;
EFI_GUID mCertType; EFI_GUID mCertType;
// //
@ -585,23 +584,20 @@ Done:
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
within this image buffer before use. within this image buffer before use.
@param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
@param[in] AuthDataSize Size of the Authenticode Signature in bytes.
@retval EFI_UNSUPPORTED Hash algorithm is not supported. @retval EFI_UNSUPPORTED Hash algorithm is not supported.
@retval EFI_SUCCESS Hash successfully. @retval EFI_SUCCESS Hash successfully.
**/ **/
EFI_STATUS EFI_STATUS
HashPeImageByType ( HashPeImageByType (
VOID IN UINT8 *AuthData,
IN UINTN AuthDataSize
) )
{ {
UINT8 Index; UINT8 Index;
WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32) {
return EFI_UNSUPPORTED;
}
for (Index = 0; Index < HASHALG_MAX; Index++) { for (Index = 0; Index < HASHALG_MAX; Index++) {
// //
@ -616,18 +612,18 @@ HashPeImageByType (
// This field has the fixed offset (+32) in final Authenticode ASN.1 data. // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
// Fixed offset (+32) is calculated based on two bytes of length encoding. // Fixed offset (+32) is calculated based on two bytes of length encoding.
// //
if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) { if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
// //
// Only support two bytes of Long Form of Length Encoding. // Only support two bytes of Long Form of Length Encoding.
// //
continue; continue;
} }
if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + mHash[Index].OidLength) { if (AuthDataSize < 32 + mHash[Index].OidLength) {
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) { if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
break; break;
} }
} }
@ -875,8 +871,10 @@ Done:
Verify PKCS#7 SignedData using certificate found in Variable which formatted Verify PKCS#7 SignedData using certificate found in Variable which formatted
as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX. as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
@param VariableName Name of Variable to search for Certificate. @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
@param VendorGuid Variable vendor GUID. @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
@param[in] VariableName Name of Variable to search for Certificate.
@param[in] VendorGuid Variable vendor GUID.
@retval TRUE Image pass verification. @retval TRUE Image pass verification.
@retval FALSE Image fail verification. @retval FALSE Image fail verification.
@ -884,13 +882,14 @@ Done:
**/ **/
BOOLEAN BOOLEAN
IsPkcsSignedDataVerifiedBySignatureList ( IsPkcsSignedDataVerifiedBySignatureList (
IN UINT8 *AuthData,
IN UINTN AuthDataSize,
IN CHAR16 *VariableName, IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid IN EFI_GUID *VendorGuid
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
BOOLEAN VerifyStatus; BOOLEAN VerifyStatus;
WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_LIST *CertList;
EFI_SIGNATURE_DATA *Cert; EFI_SIGNATURE_DATA *Cert;
UINTN DataSize; UINTN DataSize;
@ -906,7 +905,6 @@ IsPkcsSignedDataVerifiedBySignatureList (
RootCert = NULL; RootCert = NULL;
RootCertSize = 0; RootCertSize = 0;
VerifyStatus = FALSE; VerifyStatus = FALSE;
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
DataSize = 0; DataSize = 0;
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL); Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
@ -940,8 +938,8 @@ IsPkcsSignedDataVerifiedBySignatureList (
// Call AuthenticodeVerify library to Verify Authenticode struct. // Call AuthenticodeVerify library to Verify Authenticode struct.
// //
VerifyStatus = AuthenticodeVerify ( VerifyStatus = AuthenticodeVerify (
PkcsCertData->CertData, AuthData,
PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr), AuthDataSize,
RootCert, RootCert,
RootCertSize, RootCertSize,
mImageDigest, mImageDigest,
@ -969,19 +967,23 @@ Done:
/** /**
Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format. 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_SUCCESS Image pass verification.
@retval EFI_SECURITY_VIOLATION Image fail verification. @retval EFI_SECURITY_VIOLATION Image fail verification.
**/ **/
EFI_STATUS EFI_STATUS
VerifyCertPkcsSignedData ( VerifyCertPkcsSignedData (
VOID IN UINT8 *AuthData,
IN UINTN AuthDataSize
) )
{ {
// //
// 1: Find certificate from DBX forbidden database for revoked certificate. // 1: Find certificate from DBX forbidden database for revoked certificate.
// //
if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) { if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
// //
// DBX is forbidden database, if Authenticode verification pass with // DBX is forbidden database, if Authenticode verification pass with
// one of the certificate in DBX, this image should be rejected. // one of the certificate in DBX, this image should be rejected.
@ -992,7 +994,7 @@ VerifyCertPkcsSignedData (
// //
// 2: Find certificate from DB database and try to verify authenticode struct. // 2: Find certificate from DB database and try to verify authenticode struct.
// //
if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) { if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
return EFI_SUCCESS; return EFI_SUCCESS;
} else { } else {
return EFI_SECURITY_VIOLATION; return EFI_SECURITY_VIOLATION;
@ -1081,10 +1083,17 @@ DxeImageVerificationHandler (
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
UINT32 NumberOfRvaAndSizes; UINT32 NumberOfRvaAndSizes;
UINT32 CertSize; UINT32 CertSize;
WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
UINT8 *AuthData;
UINTN AuthDataSize;
EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
SignatureList = NULL; SignatureList = NULL;
SignatureListSize = 0; SignatureListSize = 0;
WinCertificate = NULL; WinCertificate = NULL;
SecDataDir = NULL;
PkcsCertData = NULL;
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED; Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
Status = EFI_ACCESS_DENIED; Status = EFI_ACCESS_DENIED;
// //
@ -1207,7 +1216,7 @@ DxeImageVerificationHandler (
// //
NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes; NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
} }
} else { } else {
// //
@ -1215,11 +1224,11 @@ DxeImageVerificationHandler (
// //
NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) { if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
} }
} }
if ((mSecDataDir == NULL) || ((mSecDataDir != NULL) && (mSecDataDir->Size == 0))) { if ((SecDataDir == NULL) || ((SecDataDir != NULL) && (SecDataDir->Size == 0))) {
// //
// This image is not signed. // This image is not signed.
// //
@ -1250,24 +1259,48 @@ DxeImageVerificationHandler (
// //
// Verify signature of executables. // Verify signature of executables.
// //
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress); WinCertificate = (WIN_CERTIFICATE *) (mImageBase + SecDataDir->VirtualAddress);
CertSize = sizeof (WIN_CERTIFICATE); CertSize = sizeof (WIN_CERTIFICATE);
if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) { if ((SecDataDir->Size <= CertSize) || (SecDataDir->Size < WinCertificate->dwLength)) {
goto Done; goto Done;
} }
//
// Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
//
if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
// //
// Verify Pkcs signed data type. // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
// Authenticode specification.
// //
Status = HashPeImageByType(); PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
AuthData = PkcsCertData->CertData;
AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
Status = HashPeImageByType (AuthData, AuthDataSize);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Done; goto Done;
} }
VerifyStatus = VerifyCertPkcsSignedData (); VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
} else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
//
// The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
//
WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
if (!CompareGuid(&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
goto Done;
}
AuthData = WinCertUefiGuid->CertData;
AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
Status = HashPeImageByType (AuthData, AuthDataSize);
if (EFI_ERROR (Status)) {
goto Done;
}
VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
} else { } else {
goto Done; goto Done;
} }

View File

@ -68,6 +68,7 @@
gEfiCertSha256Guid gEfiCertSha256Guid
gEfiCertX509Guid gEfiCertX509Guid
gEfiCertRsa2048Guid gEfiCertRsa2048Guid
gEfiCertPkcs7Guid
[Pcd] [Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy