]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c
SecurityPkg: remove PE/COFF header workaround for ELILO on IPF
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Dxe / MeasureBootPeCoff.c
index e2d763a54894f585f99851a4b0d485d8992017e8..e114d672f9d96017c424b189cd3271c52de64eba 100644 (file)
@@ -1,18 +1,18 @@
 /** @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
@@ -29,6 +29,56 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #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
@@ -37,6 +87,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   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
@@ -64,11 +116,11 @@ MeasurePeImageAndExtend (
   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
@@ -78,6 +130,23 @@ MeasurePeImageAndExtend (
   //\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
@@ -111,44 +180,30 @@ MeasurePeImageAndExtend (
   // 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
@@ -158,7 +213,7 @@ MeasurePeImageAndExtend (
     // 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
@@ -177,23 +232,23 @@ MeasurePeImageAndExtend (
       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
@@ -207,7 +262,7 @@ MeasurePeImageAndExtend (
     // 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
@@ -220,7 +275,7 @@ MeasurePeImageAndExtend (
       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
@@ -232,7 +287,7 @@ MeasurePeImageAndExtend (
   //\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
@@ -314,7 +369,7 @@ MeasurePeImageAndExtend (
     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