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