/** @file\r
Implement image verification services for secure boot service in UEFI2.3.1.\r
\r
+ Caution: This file requires additional review when modified.\r
+ This library will have external input - PE/COFF image.\r
+ This external input must be validated carefully to avoid security issue like\r
+ buffer overflow, integer overflow.\r
+\r
+ DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content\r
+ read is within the image buffer.\r
+\r
+ DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept\r
+ untrusted PE/COFF image and validate its data structure within this image buffer before use.\r
+\r
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
\r
#include "DxeImageVerificationLib.h"\r
\r
+//\r
+// Caution: This is used by a function which may receive untrusted input.\r
+// These global variables hold PE/COFF image data, and they should be validated before use.\r
+//\r
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
-UINTN mImageSize;\r
UINT32 mPeCoffHeaderOffset;\r
-UINT8 mImageDigest[MAX_DIGEST_SIZE];\r
-UINTN mImageDigestSize;\r
EFI_IMAGE_DATA_DIRECTORY *mSecDataDir = NULL;\r
-UINT8 *mImageBase = NULL;\r
EFI_GUID mCertType;\r
\r
+//\r
+// Information on current PE/COFF image\r
+//\r
+UINTN mImageSize;\r
+UINT8 *mImageBase = NULL;\r
+UINT8 mImageDigest[MAX_DIGEST_SIZE];\r
+UINTN mImageDigestSize;\r
+\r
//\r
// Notify string for authorization UI.\r
//\r
/**\r
Reads contents of a PE/COFF image in memory buffer.\r
\r
+ Caution: This function may receive untrusted input.\r
+ PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
+ read is within the image buffer.\r
+\r
@param FileHandle Pointer to the file handle to read the PE/COFF image.\r
@param FileOffset Offset into the PE/COFF image to begin the read operation.\r
@param ReadSize On input, the size in bytes of the requested read operation. \r
Caculate hash of Pe/Coff image based on the authenticode image hashing in\r
PE/COFF Specification 8.0 Appendix A\r
\r
+ Caution: This function may receive untrusted input.\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] HashAlg Hash algorithm type.\r
\r
@retval TRUE Successfully hash image.\r
// Measuring PE/COFF Image Header;\r
// But CheckSum field and SECURITY data directory (certificate) are excluded\r
//\r
- Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+ if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+ //\r
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+ } else {\r
+ //\r
+ // Get the magic value from the PE/COFF Optional Header\r
+ //\r
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+ }\r
+ \r
//\r
// 3. Calculate the distance from the base of the image header to the image checksum address.\r
// 4. Hash the image header from its base to beginning of the image checksum.\r
Pe/Coff image based on the authenticode image hashing in PE/COFF Specification\r
8.0 Appendix A\r
\r
+ Caution: This function may receive untrusted input.\r
+ PE/COFF image is external input, so this function will validate its data structure\r
+ within this image buffer before use.\r
+\r
@retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
@retval EFI_SUCCESS Hash successfully.\r
\r
// Iterate each Signature Data Node within this CertList for verify.\r
//\r
RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize;\r
+ RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
\r
//\r
// Call AuthenticodeVerify library to Verify Authenticode struct.\r
//\r
VerifyStatus = AuthenticodeVerify (\r
PkcsCertData->CertData,\r
- mSecDataDir->Size - sizeof(PkcsCertData->Hdr),\r
+ PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr),\r
RootCert,\r
RootCertSize,\r
mImageDigest,\r
//\r
// Get KEK database variable.\r
//\r
- KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME);\r
+ GetEfiGlobalVariable2 (EFI_KEY_EXCHANGE_KEY_NAME, (VOID**)&KekList, NULL);\r
if (KekList == NULL) {\r
return EFI_SECURITY_VIOLATION;\r
}\r
If no,\r
Error out\r
\r
+ Caution: This function may receive untrusted input.\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] AuthenticationStatus\r
This is the authentication status returned from the security\r
measurement services for the input file.\r
UINT16 Magic;\r
EFI_IMAGE_DOS_HEADER *DosHdr;\r
EFI_STATUS VerifyStatus;\r
- UINT8 *SetupMode;\r
EFI_SIGNATURE_LIST *SignatureList;\r
UINTN SignatureListSize;\r
EFI_SIGNATURE_DATA *Signature;\r
EFI_IMAGE_EXECUTION_ACTION Action;\r
WIN_CERTIFICATE *WinCertificate;\r
UINT32 Policy;\r
- UINT8 *SecureBootEnable;\r
+ UINT8 *SecureBoot;\r
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
UINT32 NumberOfRvaAndSizes;\r
UINT32 CertSize;\r
return EFI_ACCESS_DENIED;\r
}\r
\r
- SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
- //\r
- // Skip verification if SecureBootEnable variable doesn't exist.\r
- //\r
- if (SecureBootEnable == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
+ GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);\r
//\r
- // Skip verification if SecureBootEnable is disabled.\r
+ // Skip verification if SecureBoot variable doesn't exist.\r
//\r
- if (*SecureBootEnable == SECURE_BOOT_DISABLE) {\r
- FreePool (SecureBootEnable);\r
+ if (SecureBoot == NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
- FreePool (SecureBootEnable);\r
-\r
- SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);\r
-\r
//\r
- // SetupMode doesn't exist means no AuthVar driver is dispatched,\r
- // skip verification.\r
+ // Skip verification if SecureBoot is disabled.\r
//\r
- if (SetupMode == NULL) {\r
+ if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
+ FreePool (SecureBoot);\r
return EFI_SUCCESS;\r
}\r
-\r
- //\r
- // If platform is in SETUP MODE, skip verification.\r
- //\r
- if (*SetupMode == SETUP_MODE) {\r
- FreePool (SetupMode);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- FreePool (SetupMode);\r
+ FreePool (SecureBoot);\r
\r
//\r
// Read the Dos header.\r
goto Done;\r
}\r
\r
- Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+ if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+ //\r
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+ } else {\r
+ //\r
+ // Get the magic value from the PE/COFF Optional Header\r
+ //\r
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+ }\r
+ \r
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
// If this library is built-in, it means firmware has capability to perform\r
// driver signing verification.\r
//\r
- SecureBootModePtr = GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME);\r
+ GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBootModePtr, NULL);\r
if (SecureBootModePtr == NULL) {\r
SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
//\r