//\r
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
UINT32 mPeCoffHeaderOffset;\r
-EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;\r
EFI_GUID mCertType;\r
\r
//\r
PE/COFF image is external input, so this function will validate its data structure\r
within this image buffer before use.\r
\r
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.\r
+ @param[in] AuthDataSize Size of the Authenticode Signature in bytes.\r
+ \r
@retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
@retval EFI_SUCCESS Hash successfully.\r
\r
**/\r
EFI_STATUS\r
HashPeImageByType (\r
- VOID\r
+ IN UINT8 *AuthData,\r
+ IN UINTN AuthDataSize\r
)\r
{\r
UINT8 Index;\r
- WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
-\r
- PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
-\r
- if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32) {\r
- return EFI_UNSUPPORTED;\r
- }\r
\r
for (Index = 0; Index < HASHALG_MAX; Index++) {\r
//\r
// This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
// Fixed offset (+32) is calculated based on two bytes of length encoding.\r
//\r
- if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
+ if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
//\r
// Only support two bytes of Long Form of Length Encoding.\r
//\r
continue;\r
}\r
\r
- if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + mHash[Index].OidLength) {\r
+ if (AuthDataSize < 32 + mHash[Index].OidLength) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
- if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
+ if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
break;\r
}\r
}\r
Verify PKCS#7 SignedData using certificate found in Variable which formatted\r
as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.\r
\r
- @param VariableName Name of Variable to search for Certificate.\r
- @param VendorGuid Variable vendor GUID.\r
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.\r
+ @param[in] AuthDataSize Size of the Authenticode Signature in bytes.\r
+ @param[in] VariableName Name of Variable to search for Certificate.\r
+ @param[in] VendorGuid Variable vendor GUID.\r
\r
@retval TRUE Image pass verification.\r
@retval FALSE Image fail verification.\r
**/\r
BOOLEAN\r
IsPkcsSignedDataVerifiedBySignatureList (\r
+ IN UINT8 *AuthData,\r
+ IN UINTN AuthDataSize,\r
IN CHAR16 *VariableName,\r
IN EFI_GUID *VendorGuid\r
)\r
{\r
EFI_STATUS Status;\r
BOOLEAN VerifyStatus;\r
- WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
EFI_SIGNATURE_LIST *CertList;\r
EFI_SIGNATURE_DATA *Cert;\r
UINTN DataSize;\r
RootCert = NULL;\r
RootCertSize = 0;\r
VerifyStatus = FALSE;\r
- PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
\r
DataSize = 0;\r
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
// Call AuthenticodeVerify library to Verify Authenticode struct.\r
//\r
VerifyStatus = AuthenticodeVerify (\r
- PkcsCertData->CertData,\r
- PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr),\r
+ AuthData,\r
+ AuthDataSize,\r
RootCert,\r
RootCertSize,\r
mImageDigest,\r
/**\r
Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.\r
\r
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.\r
+ @param[in] AuthDataSize Size of the Authenticode Signature in bytes.\r
+\r
@retval EFI_SUCCESS Image pass verification.\r
@retval EFI_SECURITY_VIOLATION Image fail verification.\r
\r
**/\r
EFI_STATUS\r
VerifyCertPkcsSignedData (\r
- VOID\r
+ IN UINT8 *AuthData,\r
+ IN UINTN AuthDataSize\r
)\r
{\r
//\r
// 1: Find certificate from DBX forbidden database for revoked certificate.\r
//\r
- if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
+ if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
//\r
// DBX is forbidden database, if Authenticode verification pass with\r
// one of the certificate in DBX, this image should be rejected.\r
//\r
// 2: Find certificate from DB database and try to verify authenticode struct.\r
//\r
- if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
+ if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
return EFI_SUCCESS;\r
} else {\r
return EFI_SECURITY_VIOLATION;\r
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
UINT32 NumberOfRvaAndSizes;\r
UINT32 CertSize;\r
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;\r
+ WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;\r
+ UINT8 *AuthData;\r
+ UINTN AuthDataSize;\r
+ EFI_IMAGE_DATA_DIRECTORY *SecDataDir;\r
\r
SignatureList = NULL;\r
SignatureListSize = 0;\r
WinCertificate = NULL;\r
+ SecDataDir = NULL;\r
+ PkcsCertData = NULL;\r
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
Status = EFI_ACCESS_DENIED;\r
//\r
//\r
NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
- mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+ SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
} \r
} else {\r
//\r
//\r
NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
- mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+ SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
}\r
}\r
\r
- if ((mSecDataDir == NULL) || ((mSecDataDir != NULL) && (mSecDataDir->Size == 0))) {\r
+ if ((SecDataDir == NULL) || ((SecDataDir != NULL) && (SecDataDir->Size == 0))) {\r
//\r
// This image is not signed.\r
//\r
//\r
// Verify signature of executables.\r
//\r
- WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
+ WinCertificate = (WIN_CERTIFICATE *) (mImageBase + SecDataDir->VirtualAddress);\r
\r
CertSize = sizeof (WIN_CERTIFICATE);\r
\r
- if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) {\r
+ if ((SecDataDir->Size <= CertSize) || (SecDataDir->Size < WinCertificate->dwLength)) {\r
goto Done;\r
}\r
\r
+ //\r
+ // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.\r
+ //\r
if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
//\r
- // Verify Pkcs signed data type.\r
+ // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the \r
+ // Authenticode specification.\r
//\r
- Status = HashPeImageByType();\r
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;\r
+ AuthData = PkcsCertData->CertData;\r
+ AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);\r
+ \r
+ Status = HashPeImageByType (AuthData, AuthDataSize);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
+\r
+ VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);\r
+ } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
+ //\r
+ // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.\r
+ //\r
+ WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;\r
+ if (!CompareGuid(&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {\r
+ goto Done;\r
+ }\r
+ AuthData = WinCertUefiGuid->CertData;\r
+ AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);\r
\r
- VerifyStatus = VerifyCertPkcsSignedData ();\r
+ Status = HashPeImageByType (AuthData, AuthDataSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);\r
} else {\r
goto Done;\r
}\r