/** @file\r
This module implements measuring PeCoff image for Tcg2 Protocol.\r
- \r
+\r
Caution: This file requires additional review when modified.\r
This driver 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
-Copyright (c) 2015, 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
-which accompanies this distribution. The full text of the license may be found at \r
+Copyright (c) 2015 - 2018, 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
+which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
#include <Library/Tpm2CommandLib.h>\r
#include <Library/HashLib.h>\r
\r
+UINTN mTcg2DxeImageSize = 0;\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
+ On output, the number of bytes actually read.\r
+ @param Buffer Output buffer that contains the data read from the PE/COFF image.\r
+\r
+ @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tcg2DxeImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINTN *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ UINTN EndPosition;\r
+\r
+ if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ EndPosition = FileOffset + *ReadSize;\r
+ if (EndPosition > mTcg2DxeImageSize) {\r
+ *ReadSize = (UINT32)(mTcg2DxeImageSize - FileOffset);\r
+ }\r
+\r
+ if (FileOffset >= mTcg2DxeImageSize) {\r
+ *ReadSize = 0;\r
+ }\r
+\r
+ CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Measure PE image into TPM log based on the authenticode image hashing in\r
PE/COFF Specification 8.0 Appendix A.\r
PE/COFF image is external input, so this function will validate its data structure\r
within this image buffer before use.\r
\r
+ Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
+\r
@param[in] PCRIndex TPM PCR index\r
@param[in] ImageAddress Start address of image buffer.\r
@param[in] ImageSize Image size\r
EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
UINTN Index;\r
UINTN Pos;\r
- UINT16 Magic;\r
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
UINT32 NumberOfRvaAndSizes;\r
UINT32 CertSize;\r
HASH_HANDLE HashHandle;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
\r
HashHandle = 0xFFFFFFFF; // Know bad value\r
\r
//\r
// Check PE/COFF image\r
//\r
+ ZeroMem (&ImageContext, sizeof (ImageContext));\r
+ ImageContext.Handle = (VOID *) (UINTN) ImageAddress;\r
+ mTcg2DxeImageSize = ImageSize;\r
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) Tcg2DxeImageRead;\r
+\r
+ //\r
+ // Get information about the image being loaded\r
+ //\r
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The information can't be got from the invalid PeImage\r
+ //\r
+ DEBUG ((DEBUG_INFO, "Tcg2Dxe: PeImage invalid. Cannot retrieve image information.\n"));\r
+ goto Finish;\r
+ }\r
+\r
DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;\r
PeCoffHeaderOffset = 0;\r
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
// Measuring PE/COFF Image Header;\r
// But CheckSum field and SECURITY data directory (certificate) are excluded\r
//\r
- if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.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 = Hdr.Pe32->OptionalHeader.Magic;\r
- }\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
//\r
HashBase = (UINT8 *) (UINTN) ImageAddress;\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset\r
//\r
NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
- HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+ HashSize = (UINTN) (&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
} else {\r
//\r
// Use PE32+ offset\r
//\r
NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
- HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+ HashSize = (UINTN) (&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
}\r
\r
Status = HashUpdate (HashHandle, HashBase, HashSize);\r
if (EFI_ERROR (Status)) {\r
goto Finish;\r
- } \r
+ }\r
\r
//\r
// 5. Skip over the image checksum (it occupies a single ULONG).\r
// 6. Since there is no Cert Directory in optional header, hash everything\r
// from the end of the checksum to the end of image header.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
if (EFI_ERROR (Status)) {\r
goto Finish;\r
}\r
- } \r
+ }\r
} else {\r
//\r
// 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset\r
//\r
HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+ HashSize = (UINTN) (&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
} else {\r
//\r
// Use PE32+ offset\r
- // \r
+ //\r
HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+ HashSize = (UINTN) (&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
}\r
\r
if (HashSize != 0) {\r
// 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
// 9. Hash everything from the end of the Cert Directory to the end of image header.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset\r
//\r
HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
}\r
- \r
+\r
if (HashSize != 0) {\r
Status = HashUpdate (HashHandle, HashBase, HashSize);\r
if (EFI_ERROR (Status)) {\r
//\r
// 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset\r
//\r
if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
CertSize = 0;\r
} else {\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r