diff options
author | sfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-08-23 07:55:35 +0000 |
---|---|---|
committer | sfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-08-23 07:55:35 +0000 |
commit | f6f9031f8e95727c4947a41c202f133d98aed642 (patch) | |
tree | 2203578903b9bd47454c6bb69b2ebf284869c89d | |
parent | f6e233534e1523823ccc0cec40a54d9459850143 (diff) | |
download | edk2-platforms-f6f9031f8e95727c4947a41c202f133d98aed642.tar.xz |
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
-rw-r--r-- | SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c | 91 | ||||
-rw-r--r-- | SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf | 1 |
2 files changed, 63 insertions, 29 deletions
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index c86ce1f312..b3648bdee4 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -31,7 +31,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. //
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
UINT32 mPeCoffHeaderOffset;
-EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;
EFI_GUID mCertType;
//
@@ -585,23 +584,20 @@ Done: PE/COFF image is external input, so this function will validate its data structure
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_SUCCESS Hash successfully.
**/
EFI_STATUS
HashPeImageByType (
- VOID
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize
)
{
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++) {
//
@@ -616,18 +612,18 @@ HashPeImageByType ( // 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.
//
- 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.
//
continue;
}
- if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + mHash[Index].OidLength) {
+ if (AuthDataSize < 32 + mHash[Index].OidLength) {
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;
}
}
@@ -875,8 +871,10 @@ Done: Verify PKCS#7 SignedData using certificate found in Variable which formatted
as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
- @param VariableName Name of Variable to search for Certificate.
- @param VendorGuid Variable vendor GUID.
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
+ @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 FALSE Image fail verification.
@@ -884,13 +882,14 @@ Done: **/
BOOLEAN
IsPkcsSignedDataVerifiedBySignatureList (
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize,
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
EFI_STATUS Status;
BOOLEAN VerifyStatus;
- WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
EFI_SIGNATURE_LIST *CertList;
EFI_SIGNATURE_DATA *Cert;
UINTN DataSize;
@@ -906,7 +905,6 @@ IsPkcsSignedDataVerifiedBySignatureList ( RootCert = NULL;
RootCertSize = 0;
VerifyStatus = FALSE;
- PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);
DataSize = 0;
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
@@ -940,8 +938,8 @@ IsPkcsSignedDataVerifiedBySignatureList ( // Call AuthenticodeVerify library to Verify Authenticode struct.
//
VerifyStatus = AuthenticodeVerify (
- PkcsCertData->CertData,
- PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr),
+ AuthData,
+ AuthDataSize,
RootCert,
RootCertSize,
mImageDigest,
@@ -969,19 +967,23 @@ Done: /**
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 (
- VOID
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize
)
{
//
// 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
// 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.
//
- if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
+ if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
return EFI_SUCCESS;
} else {
return EFI_SECURITY_VIOLATION;
@@ -1081,10 +1083,17 @@ DxeImageVerificationHandler ( PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
UINT32 NumberOfRvaAndSizes;
UINT32 CertSize;
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
+ WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
+ UINT8 *AuthData;
+ UINTN AuthDataSize;
+ EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
SignatureList = NULL;
SignatureListSize = 0;
WinCertificate = NULL;
+ SecDataDir = NULL;
+ PkcsCertData = NULL;
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
Status = EFI_ACCESS_DENIED;
//
@@ -1207,7 +1216,7 @@ DxeImageVerificationHandler ( //
NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
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 {
//
@@ -1215,11 +1224,11 @@ DxeImageVerificationHandler ( //
NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
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.
//
@@ -1250,24 +1259,48 @@ DxeImageVerificationHandler ( //
// Verify signature of executables.
//
- WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);
+ WinCertificate = (WIN_CERTIFICATE *) (mImageBase + SecDataDir->VirtualAddress);
CertSize = sizeof (WIN_CERTIFICATE);
- if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) {
+ if ((SecDataDir->Size <= CertSize) || (SecDataDir->Size < WinCertificate->dwLength)) {
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) {
//
- // 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)) {
goto Done;
}
+
+ 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);
- VerifyStatus = VerifyCertPkcsSignedData ();
+ Status = HashPeImageByType (AuthData, AuthDataSize);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
} else {
goto Done;
}
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf index 8ec41f4e11..dd03b0bf8a 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf @@ -68,6 +68,7 @@ gEfiCertSha256Guid
gEfiCertX509Guid
gEfiCertRsa2048Guid
+ gEfiCertPkcs7Guid
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy
|