11abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen/** @file
21abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  This module implements measuring PeCoff image for Tcg2 Protocol.
31abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
41abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Caution: This file requires additional review when modified.
51abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  This driver will have external input - PE/COFF image.
61abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  This external input must be validated carefully to avoid security issue like
71abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  buffer overflow, integer overflow.
81abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
91abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenCopyright (c) 2015, Intel Corporation. All rights reserved.<BR>
101abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenThis program and the accompanying materials
111abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewenare licensed and made available under the terms and conditions of the BSD License
121abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewenwhich accompanies this distribution.  The full text of the license may be found at
131abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewenhttp://opensource.org/licenses/bsd-license.php
141abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
151abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
161abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
171abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
181abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen**/
191abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
201abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <PiDxe.h>
211abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
221abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/BaseLib.h>
231abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/DebugLib.h>
241abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/BaseMemoryLib.h>
251abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/MemoryAllocationLib.h>
261abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/DevicePathLib.h>
271abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/UefiBootServicesTableLib.h>
281abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/PeCoffLib.h>
291abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/Tpm2CommandLib.h>
301abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen#include <Library/HashLib.h>
311abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
321abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen/**
331abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Measure PE image into TPM log based on the authenticode image hashing in
341abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  PE/COFF Specification 8.0 Appendix A.
351abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
361abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Caution: This function may receive untrusted input.
371abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  PE/COFF image is external input, so this function will validate its data structure
381abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  within this image buffer before use.
391abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
401abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @param[in]  PCRIndex       TPM PCR index
411abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @param[in]  ImageAddress   Start address of image buffer.
421abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @param[in]  ImageSize      Image size
431abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @param[out] DigestList     Digeest list of this image.
441abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
451abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @retval EFI_SUCCESS            Successfully measure image.
461abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.
471abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  @retval other error value
481abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen**/
491abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenEFI_STATUS
501abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenMeasurePeImageAndExtend (
511abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  IN  UINT32                    PCRIndex,
521abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  IN  EFI_PHYSICAL_ADDRESS      ImageAddress,
531abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  IN  UINTN                     ImageSize,
541abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  OUT TPML_DIGEST_VALUES        *DigestList
551abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  )
561abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen{
571abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  EFI_STATUS                           Status;
581abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  EFI_IMAGE_DOS_HEADER                 *DosHdr;
591abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINT32                               PeCoffHeaderOffset;
601abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  EFI_IMAGE_SECTION_HEADER             *Section;
611abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINT8                                *HashBase;
621abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINTN                                HashSize;
631abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINTN                                SumOfBytesHashed;
641abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  EFI_IMAGE_SECTION_HEADER             *SectionHeader;
651abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINTN                                Index;
661abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINTN                                Pos;
671abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINT16                               Magic;
681abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
691abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINT32                               NumberOfRvaAndSizes;
701abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  UINT32                               CertSize;
711abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  HASH_HANDLE                          HashHandle;
721abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
731abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  HashHandle = 0xFFFFFFFF; // Know bad value
741abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
751abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Status        = EFI_UNSUPPORTED;
761abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  SectionHeader = NULL;
771abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
781abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
791abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // Check PE/COFF image
801abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
811abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;
821abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  PeCoffHeaderOffset = 0;
831abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
841abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    PeCoffHeaderOffset = DosHdr->e_lfanew;
851abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
861abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
871abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);
881abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
891abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Status = EFI_UNSUPPORTED;
901abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    goto Finish;
911abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
921abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
931abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
941abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // PE/COFF Image Measurement
951abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
961abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //    NOTE: The following codes/steps are based upon the authenticode image hashing in
971abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      PE/COFF Specification 8.0 Appendix A.
981abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
991abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1001abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1011abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 1.  Load the image header into memory.
1021abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1031abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 2.  Initialize a SHA hash context.
1041abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1051abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Status = HashStart (&HashHandle);
1061abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (EFI_ERROR (Status)) {
1071abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    goto Finish;
1081abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
1091abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1101abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1111abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // Measuring PE/COFF Image Header;
1121abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // But CheckSum field and SECURITY data directory (certificate) are excluded
1131abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1141abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1151abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1161abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1171abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1181abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1191abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1201abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1211abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1221abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  } else {
1231abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1241abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // Get the magic value from the PE/COFF Optional Header
1251abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1261abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Magic = Hdr.Pe32->OptionalHeader.Magic;
1271abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
1281abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1291abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1301abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 3.  Calculate the distance from the base of the image header to the image checksum address.
1311abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 4.  Hash the image header from its base to beginning of the image checksum.
1321abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1331abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  HashBase = (UINT8 *) (UINTN) ImageAddress;
1341abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1351abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1361abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // Use PE32 offset
1371abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1381abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
1391abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);
1401abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  } else {
1411abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1421abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // Use PE32+ offset
1431abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1441abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
1451abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
1461abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
1471abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1481abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Status = HashUpdate (HashHandle, HashBase, HashSize);
1491abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (EFI_ERROR (Status)) {
1501abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    goto Finish;
1511abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
1521abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1531abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1541abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 5.  Skip over the image checksum (it occupies a single ULONG).
1551abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
1561abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
1571abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1581abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // 6.  Since there is no Cert Directory in optional header, hash everything
1591abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //     from the end of the checksum to the end of image header.
1601abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1611abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1621abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1631abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      // Use PE32 offset.
1641abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1651abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
1661abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
1671abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    } else {
1681abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1691abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      // Use PE32+ offset.
1701abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1711abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
1721abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
1731abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
1741abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1751abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (HashSize != 0) {
1761abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      Status  = HashUpdate (HashHandle, HashBase, HashSize);
1771abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      if (EFI_ERROR (Status)) {
1781abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        goto Finish;
1791abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      }
1801abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
1811abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  } else {
1821abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1831abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
1841abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
1851abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1861abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1871abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      // Use PE32 offset
1881abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1891abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
1901abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
1911abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    } else {
1921abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1931abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      // Use PE32+ offset
1941abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
1951abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
1961abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
1971abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
1981abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
1991abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (HashSize != 0) {
2001abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      Status  = HashUpdate (HashHandle, HashBase, HashSize);
2011abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      if (EFI_ERROR (Status)) {
2021abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        goto Finish;
2031abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      }
2041abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
2051abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2061abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
2071abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
2081abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // 9.  Hash everything from the end of the Cert Directory to the end of image header.
2091abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
2101abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2111abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
2121abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      // Use PE32 offset
2131abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
2141abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
2151abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
2161abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    } else {
2171abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
2181abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      // Use PE32+ offset
2191abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      //
2201abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
2211abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
2221abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
2231abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2241abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (HashSize != 0) {
2251abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      Status  = HashUpdate (HashHandle, HashBase, HashSize);
2261abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      if (EFI_ERROR (Status)) {
2271abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        goto Finish;
2281abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      }
2291abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
2301abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
2311abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2321abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2331abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
2341abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2351abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2361abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
2371abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // Use PE32 offset
2381abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
2391abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
2401abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  } else {
2411abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
2421abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    // Use PE32+ offset
2431abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    //
2441abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
2451abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
2461abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2471abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2481abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
2491abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //     structures in the image. The 'NumberOfSections' field of the image
2501abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //     header indicates how big the table should be. Do not include any
2511abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
2521abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2531abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
2541abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (SectionHeader == NULL) {
2551abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Status = EFI_OUT_OF_RESOURCES;
2561abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    goto Finish;
2571abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
2581abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2591abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2601abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 12.  Using the 'PointerToRawData' in the referenced section headers as
2611abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      a key, arrange the elements in the table in ascending order. In other
2621abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      words, sort the section headers according to the disk-file offset of
2631abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      the section.
2641abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2651abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Section = (EFI_IMAGE_SECTION_HEADER *) (
2661abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen               (UINT8 *) (UINTN) ImageAddress +
2671abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen               PeCoffHeaderOffset +
2681abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen               sizeof(UINT32) +
2691abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen               sizeof(EFI_IMAGE_FILE_HEADER) +
2701abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen               Hdr.Pe32->FileHeader.SizeOfOptionalHeader
2711abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen               );
2721abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
2731abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Pos = Index;
2741abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
2751abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER));
2761abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      Pos--;
2771abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
2781abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER));
2791abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Section += 1;
2801abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
2811abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2821abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2831abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 13.  Walk through the sorted table, bring the corresponding section
2841abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      into memory, and hash the entire section (using the 'SizeOfRawData'
2851abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      field in the section header to determine the amount of data to hash).
2861abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
2871abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
2881abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
2891abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
2901abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Section  = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index];
2911abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (Section->SizeOfRawData == 0) {
2921abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      continue;
2931abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
2941abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData;
2951abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    HashSize = (UINTN) Section->SizeOfRawData;
2961abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
2971abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    Status = HashUpdate (HashHandle, HashBase, HashSize);
2981abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (EFI_ERROR (Status)) {
2991abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      goto Finish;
3001abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
3011abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3021abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    SumOfBytesHashed += HashSize;
3031abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
3041abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3051abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
3061abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
3071abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      data in the file that needs to be added to the hash. This data begins
3081abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //      at file offset SUM_OF_BYTES_HASHED and its length is:
3091abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //             FileSize  -  (CertDirectory->Size)
3101abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
3111abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (ImageSize > SumOfBytesHashed) {
3121abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed;
3131abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3141abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
3151abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      CertSize = 0;
3161abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    } else {
3171abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
3181abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        //
3191abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        // Use PE32 offset.
3201abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        //
3211abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
3221abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      } else {
3231abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        //
3241abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        // Use PE32+ offset.
3251abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        //
3261abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
3271abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      }
3281abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
3291abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3301abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    if (ImageSize > CertSize + SumOfBytesHashed) {
3311abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed);
3321abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3331abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      Status = HashUpdate (HashHandle, HashBase, HashSize);
3341abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      if (EFI_ERROR (Status)) {
3351abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen        goto Finish;
3361abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      }
3371abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    } else if (ImageSize < CertSize + SumOfBytesHashed) {
3381abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      Status = EFI_UNSUPPORTED;
3391abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen      goto Finish;
3401abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    }
3411abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
3421abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3431abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
3441abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  // 17.  Finalize the SHA hash.
3451abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  //
3461abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  Status = HashCompleteAndExtend (HashHandle, PCRIndex, NULL, 0, DigestList);
3471abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (EFI_ERROR (Status)) {
3481abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    goto Finish;
3491abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
3501abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3511abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, JiewenFinish:
3521abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  if (SectionHeader != NULL) {
3531abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen    FreePool (SectionHeader);
3541abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  }
3551abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen
3561abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen  return Status;
3571abfa4ce4835639c66ae82cc0d72cffcf3f28b6bYao, Jiewen}
358