Fix compile error
[mirror_edk2.git] / SecurityPkg / Library / DxeTpmMeasureBootLib / DxeTpmMeasureBootLib.c
index f0039c8..f3e486e 100644 (file)
@@ -1,6 +1,20 @@
 /** @file\r
   The library instance provides security service of TPM measure boot.  \r
 \r
+  Caution: This file requires additional review when modified.\r
+  This library will have external input - PE/COFF image and GPT partition.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+  DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
+  TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its\r
+  data structure within this image buffer before use.\r
+\r
+  TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse\r
+  partition data carefully.\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
@@ -15,10 +29,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <PiDxe.h>\r
 \r
 #include <Protocol/TcgService.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
 #include <Protocol/BlockIo.h>\r
 #include <Protocol/DiskIo.h>\r
 #include <Protocol/DevicePathToText.h>\r
+#include <Protocol/FirmwareVolumeBlock.h>\r
+\r
+#include <Guid/TrustedFvHob.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
@@ -29,6 +45,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/BaseCryptLib.h>\r
 #include <Library/PeCoffLib.h>\r
 #include <Library/SecurityManagementLib.h>\r
+#include <Library/HobLib.h>\r
 \r
 //\r
 // Flag to check GPT partition. It only need be measured once.\r
@@ -38,10 +55,19 @@ EFI_GUID                          mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}
 UINTN                             mMeasureGptCount = 0;\r
 VOID                              *mFileBuffer;\r
 UINTN                             mImageSize;\r
+//\r
+// Measured FV handle cache\r
+//\r
+EFI_HANDLE                        mCacheMeasuredHandle  = NULL;\r
+UINT32                            *mGuidHobData         = NULL;\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
@@ -52,7 +78,7 @@ UINTN                             mImageSize;
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-ImageRead (\r
+DxeTpmMeasureBootLibImageRead (\r
   IN     VOID    *FileHandle,\r
   IN     UINTN   FileOffset,\r
   IN OUT UINTN   *ReadSize,\r
@@ -86,6 +112,9 @@ ImageRead (
 /**\r
   Measure GPT table data into TPM log.\r
 \r
+  Caution: This function may receive untrusted input.\r
+  The GPT partition table is external input, so this function should parse partition data carefully.\r
+\r
   @param TcgProtocol             Pointer to the located TCG protocol instance.\r
   @param GptHandle               Handle that GPT partition was installed.\r
 \r
@@ -177,15 +206,15 @@ TcgMeasureGptTable (
     if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {\r
       NumberOfPartition++;  \r
     }\r
-    PartitionEntry++;\r
+    PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
   }\r
 \r
   //\r
-  // Parepare Data for Measurement\r
+  // Prepare Data for Measurement\r
   // \r
   EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) \r
                         + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
-  TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));\r
+  TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));\r
   if (TcgEvent == NULL) {\r
     FreePool (PrimaryHeader);\r
     FreePool (EntryPtr);\r
@@ -210,13 +239,13 @@ TcgMeasureGptTable (
   for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
     if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {\r
       CopyMem (\r
-        (UINT8 *)&GptData->Partitions + NumberOfPartition * sizeof (EFI_PARTITION_ENTRY),\r
+        (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,\r
         (UINT8 *)PartitionEntry,\r
-        sizeof (EFI_PARTITION_ENTRY)\r
+        PrimaryHeader->SizeOfPartitionEntry\r
         );\r
       NumberOfPartition++;\r
     }\r
-    PartitionEntry++;\r
+    PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
   }\r
 \r
   //\r
@@ -247,6 +276,10 @@ TcgMeasureGptTable (
   Measure PE image into TPM log 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] TcgProtocol    Pointer to the located TCG protocol instance.\r
   @param[in] ImageAddress   Start address of image buffer.\r
   @param[in] ImageSize      Image size\r
@@ -256,7 +289,9 @@ TcgMeasureGptTable (
 \r
   @retval EFI_SUCCESS            Successfully measure image.\r
   @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.\r
+  @retval EFI_UNSUPPORTED        ImageType is unsupported or PE image is mal-format.  \r
   @retval other error value\r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -269,27 +304,31 @@ TcgMeasurePeImage (
   IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  TCG_PCR_EVENT                     *TcgEvent;\r
-  EFI_IMAGE_LOAD_EVENT              *ImageLoad;\r
-  UINT32                            FilePathSize;\r
-  VOID                              *Sha1Ctx;\r
-  UINTN                             CtxSize;\r
-  EFI_IMAGE_DOS_HEADER              *DosHdr;\r
-  UINT32                            PeCoffHeaderOffset;\r
-  EFI_IMAGE_SECTION_HEADER          *Section;\r
-  UINT8                             *HashBase;\r
-  UINTN                             HashSize;\r
-  UINTN                             SumOfBytesHashed;\r
-  EFI_IMAGE_SECTION_HEADER          *SectionHeader;\r
-  UINTN                             Index, Pos;\r
-  UINT16                            Magic;\r
-  UINT32                            EventSize;\r
-  UINT32                            EventNumber;\r
-  EFI_PHYSICAL_ADDRESS              EventLogLastEntry;\r
+  EFI_STATUS                           Status;\r
+  TCG_PCR_EVENT                        *TcgEvent;\r
+  EFI_IMAGE_LOAD_EVENT                 *ImageLoad;\r
+  UINT32                               FilePathSize;\r
+  VOID                                 *Sha1Ctx;\r
+  UINTN                                CtxSize;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  UINT32                               PeCoffHeaderOffset;\r
+  EFI_IMAGE_SECTION_HEADER             *Section;\r
+  UINT8                                *HashBase;\r
+  UINTN                                HashSize;\r
+  UINTN                                SumOfBytesHashed;\r
+  EFI_IMAGE_SECTION_HEADER             *SectionHeader;\r
+  UINTN                                Index;\r
+  UINTN                                Pos;\r
+  UINT16                               Magic;\r
+  UINT32                               EventSize;\r
+  UINT32                               EventNumber;\r
+  EFI_PHYSICAL_ADDRESS                 EventLogLastEntry;\r
   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  BOOLEAN                              HashStatus;\r
+  UINT32                               CertSize;\r
 \r
-  Status        = EFI_SUCCESS;\r
+  Status        = EFI_UNSUPPORTED;\r
   ImageLoad     = NULL;\r
   SectionHeader = NULL;\r
   Sha1Ctx       = NULL;\r
@@ -326,7 +365,6 @@ TcgMeasurePeImage (
         "TcgMeasurePeImage: Unknown subsystem type %d",\r
         ImageType\r
         ));\r
-      Status = EFI_UNSUPPORTED;\r
       goto Finish;\r
   }\r
 \r
@@ -344,8 +382,9 @@ TcgMeasurePeImage (
   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
     PeCoffHeaderOffset = DosHdr->e_lfanew;\r
   }\r
-  if (((EFI_TE_IMAGE_HEADER *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset))->Signature\r
-       == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+\r
+  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
+  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
     goto Finish;\r
   }\r
 \r
@@ -367,14 +406,29 @@ TcgMeasurePeImage (
     goto Finish;\r
   }\r
 \r
-  Sha1Init (Sha1Ctx);\r
+  HashStatus = Sha1Init (Sha1Ctx);\r
+  if (!HashStatus) {\r
+    goto Finish;\r
+  }\r
 \r
   //\r
   // Measuring PE/COFF Image Header;\r
   // But CheckSum field and SECURITY data directory (certificate) are excluded\r
   //\r
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
-  Magic    = Hdr.Pe32->OptionalHeader.Magic;\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
   // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
@@ -385,58 +439,99 @@ TcgMeasurePeImage (
     //\r
     // Use PE32 offset\r
     //\r
+    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
     HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - 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
   }\r
 \r
-  Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+  HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+  if (!HashStatus) {\r
+    goto Finish;\r
+  }  \r
 \r
   //\r
   // 5.  Skip over the image checksum (it occupies a single ULONG).\r
-  // 6.  Get the address of the beginning of the Cert Directory.\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 (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
     //\r
-    // Use PE32 offset\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
-    HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset.\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    }\r
+\r
+    if (HashSize != 0) {\r
+      HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      if (!HashStatus) {\r
+        goto Finish;\r
+      }\r
+    }    \r
   } else {\r
     //\r
-    // Use PE32+ offset\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
-  }\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
+      //\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
+    } else {\r
+      //\r
+      // Use PE32+ offset\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
+    }\r
 \r
-  Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+    if (HashSize != 0) {\r
+      HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      if (!HashStatus) {\r
+        goto Finish;\r
+      }\r
+    }\r
 \r
-  //\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
-    //\r
-    // Use PE32 offset\r
-    //\r
-    HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders -\r
-             (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress);\r
-  } else {\r
     //\r
-    // Use PE32+ offset\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
-    HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders -\r
-             (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress);\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+    } else {\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
+    if (HashSize != 0) {\r
+      HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      if (!HashStatus) {\r
+        goto Finish;\r
+      }\r
+    }\r
   }\r
-  \r
-  Sha1Update (Sha1Ctx, HashBase, HashSize);\r
 \r
   //\r
   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
@@ -459,7 +554,7 @@ TcgMeasurePeImage (
   //     header indicates how big the table should be. Do not include any\r
   //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
   //\r
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);\r
   if (SectionHeader == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto Finish;\r
@@ -503,7 +598,10 @@ TcgMeasurePeImage (
     HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData;\r
     HashSize = (UINTN) Section->SizeOfRawData;\r
 \r
-    Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+    HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+    if (!HashStatus) {\r
+      goto Finish;\r
+    }\r
 \r
     SumOfBytesHashed += HashSize;\r
   }\r
@@ -516,37 +614,42 @@ TcgMeasurePeImage (
   //\r
   if (ImageSize > SumOfBytesHashed) {\r
     HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed;\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-      if (ImageSize - SumOfBytesHashed < Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Finish;\r
-      }\r
-      //\r
-      // Use PE32 offset\r
-      //\r
-      HashSize = (UINTN)(ImageSize -\r
-                 Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);\r
+\r
+    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      CertSize = 0;\r
     } else {\r
-      if (ImageSize - SumOfBytesHashed < Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) {\r
-        Status = EFI_INVALID_PARAMETER;\r
-        goto Finish;\r
+      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        //\r
+        // Use PE32 offset.\r
+        //\r
+        CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      } else {\r
+        //\r
+        // Use PE32+ offset.\r
+        //\r
+        CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
       }\r
-      //\r
-      // Use PE32+ offset\r
-      //\r
-      HashSize = (UINTN)(ImageSize -\r
-                 Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);      \r
     }\r
 \r
-    Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+    if (ImageSize > CertSize + SumOfBytesHashed) {\r
+      HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed);\r
+\r
+      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      if (!HashStatus) {\r
+        goto Finish;\r
+      }\r
+    } else if (ImageSize < CertSize + SumOfBytesHashed) {\r
+      goto Finish;\r
+    }\r
   }\r
 \r
   //\r
   // 17.  Finalize the SHA hash.\r
   //\r
-  Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest);\r
+  HashStatus = Sha1Final (Sha1Ctx, (UINT8 *) &TcgEvent->Digest);\r
+  if (!HashStatus) {\r
+    goto Finish;\r
+  }\r
 \r
   //\r
   // Log the PE data\r
@@ -599,51 +702,46 @@ Finish:
   might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is \r
   returned.\r
 \r
-  @param[in, out] AuthenticationStatus  This is the authentication status returned\r
+  @param[in]      AuthenticationStatus  This is the authentication status returned\r
                                         from the securitymeasurement services for the\r
                                         input file.\r
   @param[in]      File       This is a pointer to the device path of the file that is\r
                              being dispatched. This will optionally be used for logging.\r
   @param[in]      FileBuffer File buffer matches the input file device path.\r
   @param[in]      FileSize   Size of File buffer matches the input file device path.\r
+  @param[in]      BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
 \r
-  @retval EFI_SUCCESS            The file specified by File did authenticate, and the\r
-                                 platform policy dictates that the DXE Core may use File.\r
-  @retval EFI_INVALID_PARAMETER  File is NULL.\r
-  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
-                                 the platform policy dictates that File should be placed\r
-                                 in the untrusted state. A file may be promoted from\r
-                                 the untrusted to the trusted state at a future time\r
-                                 with a call to the Trust() DXE Service.\r
-  @retval EFI_ACCESS_DENIED      The file specified by File did not authenticate, and\r
-                                 the platform policy dictates that File should not be\r
-                                 used for any purpose.\r
-\r
+  @retval EFI_SUCCESS             The file specified by DevicePath and non-NULL\r
+                                  FileBuffer did authenticate, and the platform policy dictates\r
+                                  that the DXE Foundation may use the file.\r
+  @retval other error value\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 DxeTpmMeasureBootHandler (\r
-  IN  OUT   UINT32                     AuthenticationStatus,\r
+  IN  UINT32                           AuthenticationStatus,\r
   IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
-  IN  VOID                             *FileBuffer OPTIONAL,\r
-  IN  UINTN                            FileSize OPTIONAL\r
+  IN  VOID                             *FileBuffer,\r
+  IN  UINTN                            FileSize,\r
+  IN  BOOLEAN                          BootPolicy\r
   )\r
 {\r
-  EFI_TCG_PROTOCOL                  *TcgProtocol;\r
-  EFI_STATUS                        Status;\r
-  TCG_EFI_BOOT_SERVICE_CAPABILITY   ProtocolCapability;\r
-  UINT32                            TCGFeatureFlags;\r
-  EFI_PHYSICAL_ADDRESS              EventLogLocation;\r
-  EFI_PHYSICAL_ADDRESS              EventLogLastEntry;\r
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePathNode;\r
-  EFI_DEVICE_PATH_PROTOCOL          *OrigDevicePathNode;\r
-  EFI_HANDLE                        Handle;\r
-  BOOLEAN                           ApplicationRequired;\r
-  PE_COFF_LOADER_IMAGE_CONTEXT      ImageContext;\r
-\r
-  if (File == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  EFI_TCG_PROTOCOL                    *TcgProtocol;\r
+  EFI_STATUS                          Status;\r
+  TCG_EFI_BOOT_SERVICE_CAPABILITY     ProtocolCapability;\r
+  UINT32                              TCGFeatureFlags;\r
+  EFI_PHYSICAL_ADDRESS                EventLogLocation;\r
+  EFI_PHYSICAL_ADDRESS                EventLogLastEntry;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL            *OrigDevicePathNode;\r
+  EFI_HANDLE                          Handle;\r
+  EFI_HANDLE                          TempHandle;\r
+  BOOLEAN                             ApplicationRequired;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;\r
+  EFI_PHYSICAL_ADDRESS                FvAddress;\r
+  EFI_PLATFORM_FIRMWARE_BLOB          *TrustedFvBuf;\r
+  UINT32                              Index;\r
 \r
   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);\r
   if (EFI_ERROR (Status)) {\r
@@ -673,7 +771,6 @@ DxeTpmMeasureBootHandler (
   // Copy File Device Path\r
   //\r
   OrigDevicePathNode = DuplicateDevicePath (File);\r
-  ASSERT (OrigDevicePathNode != NULL);\r
   \r
   //\r
   // 1. Check whether this device path support BlockIo protocol.\r
@@ -686,6 +783,7 @@ DxeTpmMeasureBootHandler (
     // Find the gpt partion on the given devicepath\r
     //\r
     DevicePathNode = OrigDevicePathNode;\r
+    ASSERT (DevicePathNode != NULL);\r
     while (!IsDevicePathEnd (DevicePathNode)) {\r
       //\r
       // Find the Gpt partition\r
@@ -737,10 +835,10 @@ DxeTpmMeasureBootHandler (
   ApplicationRequired = FALSE;\r
 \r
   //\r
-  // Check whether this device path support FV2 protocol.\r
+  // Check whether this device path support FVB protocol.\r
   //\r
   DevicePathNode = OrigDevicePathNode;\r
-  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle);\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);\r
   if (!EFI_ERROR (Status)) {\r
     //\r
     // Don't check FV image, and directly return EFI_SUCCESS.\r
@@ -750,13 +848,51 @@ DxeTpmMeasureBootHandler (
       return EFI_SUCCESS;\r
     }\r
     //\r
-    // The image from Firmware image will not be mearsured.\r
-    // Current policy doesn't measure PeImage from Firmware if it is driver\r
-    // If the got PeImage is application, it will be still be measured.\r
+    // The PE image from untrusted Firmware volume need be measured\r
+    // The PE image from trusted Firmware volume will be mearsured according to policy below.\r
+    //   if it is driver, do not measure\r
+    //   If it is application, still measure.\r
     //\r
     ApplicationRequired = TRUE;\r
+\r
+    if (mCacheMeasuredHandle != Handle && mGuidHobData != NULL) {\r
+      //\r
+      // Search for Root FV of this PE image\r
+      //\r
+      TempHandle = Handle;\r
+      do {\r
+        Status = gBS->HandleProtocol(\r
+                        TempHandle, \r
+                        &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                        (VOID**)&FvbProtocol\r
+                        );\r
+        TempHandle = FvbProtocol->ParentHandle;\r
+      } while (!EFI_ERROR(Status) && FvbProtocol->ParentHandle != NULL);\r
+\r
+      //\r
+      // Search in measured FV Hob\r
+      //\r
+      Status = FvbProtocol->GetPhysicalAddress(FvbProtocol, &FvAddress);\r
+      if (EFI_ERROR(Status)){\r
+        return Status;\r
+      }\r
+\r
+      TrustedFvBuf        = (EFI_PLATFORM_FIRMWARE_BLOB *)(mGuidHobData + 1);\r
+      ApplicationRequired = FALSE;\r
+\r
+      for (Index = 0; Index < *mGuidHobData; Index++) {\r
+        if(TrustedFvBuf[Index].BlobBase == FvAddress) {\r
+          //\r
+          // Cache measured FV for next measurement\r
+          //\r
+          mCacheMeasuredHandle = Handle;\r
+          ApplicationRequired  = TRUE;\r
+          break;\r
+        }\r
+      }\r
+    }\r
   }\r
-  \r
+\r
   //\r
   // File is not found.\r
   //\r
@@ -774,7 +910,7 @@ DxeTpmMeasureBootHandler (
   DevicePathNode = OrigDevicePathNode;\r
   ZeroMem (&ImageContext, sizeof (ImageContext));\r
   ImageContext.Handle    = (VOID *) FileBuffer;\r
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) ImageRead;\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeTpmMeasureBootLibImageRead;\r
 \r
   //\r
   // Get information about the image being loaded\r
@@ -833,7 +969,9 @@ DxeTpmMeasureBootHandler (
   // Done, free the allocated resource.\r
   //\r
 Finish:\r
-  FreePool (OrigDevicePathNode);\r
+  if (OrigDevicePathNode != NULL) {\r
+    FreePool (OrigDevicePathNode);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -854,7 +992,17 @@ DxeTpmMeasureBootLibConstructor (
   IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  return RegisterSecurityHandler (\r
+  EFI_HOB_GUID_TYPE  *GuidHob;\r
+\r
+  GuidHob = NULL;\r
+\r
+  GuidHob = GetFirstGuidHob (&gTrustedFvHobGuid);\r
+\r
+  if (GuidHob != NULL) {\r
+    mGuidHobData = GET_GUID_HOB_DATA (GuidHob);\r
+  }\r
+\r
+  return RegisterSecurity2Handler (\r
           DxeTpmMeasureBootHandler,\r
           EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
           );\r