1 /** @file
2   The library instance provides security service of TPM measure boot.
3 
4   Caution: This file requires additional review when modified.
5   This library will have external input - PE/COFF image and GPT partition.
6   This external input must be validated carefully to avoid security issue like
7   buffer overflow, integer overflow.
8 
9   DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content
10   read is within the image buffer.
11 
12   TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its
13   data structure within this image buffer before use.
14 
15   TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse
16   partition data carefully.
17 
18 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
19 This program and the accompanying materials
20 are licensed and made available under the terms and conditions of the BSD License
21 which accompanies this distribution.  The full text of the license may be found at
22 http://opensource.org/licenses/bsd-license.php
23 
24 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
25 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
26 
27 **/
28 
29 #include <PiDxe.h>
30 
31 #include <Protocol/TcgService.h>
32 #include <Protocol/BlockIo.h>
33 #include <Protocol/DiskIo.h>
34 #include <Protocol/FirmwareVolumeBlock.h>
35 
36 #include <Guid/MeasuredFvHob.h>
37 #include <Guid/ZeroGuid.h>
38 
39 #include <Library/BaseLib.h>
40 #include <Library/DebugLib.h>
41 #include <Library/BaseMemoryLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/DevicePathLib.h>
44 #include <Library/UefiBootServicesTableLib.h>
45 #include <Library/BaseCryptLib.h>
46 #include <Library/PeCoffLib.h>
47 #include <Library/SecurityManagementLib.h>
48 #include <Library/HobLib.h>
49 
50 //
51 // Flag to check GPT partition. It only need be measured once.
52 //
53 BOOLEAN                           mMeasureGptTableFlag = FALSE;
54 UINTN                             mMeasureGptCount = 0;
55 VOID                              *mFileBuffer;
56 UINTN                             mTpmImageSize;
57 //
58 // Measured FV handle cache
59 //
60 EFI_HANDLE                        mCacheMeasuredHandle  = NULL;
61 MEASURED_HOB_DATA                 *mMeasuredHobData     = NULL;
62 
63 /**
64   Reads contents of a PE/COFF image in memory buffer.
65 
66   Caution: This function may receive untrusted input.
67   PE/COFF image is external input, so this function will make sure the PE/COFF image content
68   read is within the image buffer.
69 
70   @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
71   @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
72   @param  ReadSize        On input, the size in bytes of the requested read operation.
73                           On output, the number of bytes actually read.
74   @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
75 
76   @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
77 **/
78 EFI_STATUS
79 EFIAPI
DxeTpmMeasureBootLibImageRead(IN VOID * FileHandle,IN UINTN FileOffset,IN OUT UINTN * ReadSize,OUT VOID * Buffer)80 DxeTpmMeasureBootLibImageRead (
81   IN     VOID    *FileHandle,
82   IN     UINTN   FileOffset,
83   IN OUT UINTN   *ReadSize,
84   OUT    VOID    *Buffer
85   )
86 {
87   UINTN               EndPosition;
88 
89   if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
90     return EFI_INVALID_PARAMETER;
91   }
92 
93   if (MAX_ADDRESS - FileOffset < *ReadSize) {
94     return EFI_INVALID_PARAMETER;
95   }
96 
97   EndPosition = FileOffset + *ReadSize;
98   if (EndPosition > mTpmImageSize) {
99     *ReadSize = (UINT32)(mTpmImageSize - FileOffset);
100   }
101 
102   if (FileOffset >= mTpmImageSize) {
103     *ReadSize = 0;
104   }
105 
106   CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
107 
108   return EFI_SUCCESS;
109 }
110 
111 /**
112   Measure GPT table data into TPM log.
113 
114   Caution: This function may receive untrusted input.
115   The GPT partition table is external input, so this function should parse partition data carefully.
116 
117   @param TcgProtocol             Pointer to the located TCG protocol instance.
118   @param GptHandle               Handle that GPT partition was installed.
119 
120   @retval EFI_SUCCESS            Successfully measure GPT table.
121   @retval EFI_UNSUPPORTED        Not support GPT table on the given handle.
122   @retval EFI_DEVICE_ERROR       Can't get GPT table because device error.
123   @retval EFI_OUT_OF_RESOURCES   No enough resource to measure GPT table.
124   @retval other error value
125 **/
126 EFI_STATUS
127 EFIAPI
TcgMeasureGptTable(IN EFI_TCG_PROTOCOL * TcgProtocol,IN EFI_HANDLE GptHandle)128 TcgMeasureGptTable (
129   IN  EFI_TCG_PROTOCOL   *TcgProtocol,
130   IN  EFI_HANDLE         GptHandle
131   )
132 {
133   EFI_STATUS                        Status;
134   EFI_BLOCK_IO_PROTOCOL             *BlockIo;
135   EFI_DISK_IO_PROTOCOL              *DiskIo;
136   EFI_PARTITION_TABLE_HEADER        *PrimaryHeader;
137   EFI_PARTITION_ENTRY               *PartitionEntry;
138   UINT8                             *EntryPtr;
139   UINTN                             NumberOfPartition;
140   UINT32                            Index;
141   TCG_PCR_EVENT                     *TcgEvent;
142   EFI_GPT_DATA                      *GptData;
143   UINT32                            EventSize;
144   UINT32                            EventNumber;
145   EFI_PHYSICAL_ADDRESS              EventLogLastEntry;
146 
147   if (mMeasureGptCount > 0) {
148     return EFI_SUCCESS;
149   }
150 
151   Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo);
152   if (EFI_ERROR (Status)) {
153     return EFI_UNSUPPORTED;
154   }
155   Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo);
156   if (EFI_ERROR (Status)) {
157     return EFI_UNSUPPORTED;
158   }
159   //
160   // Read the EFI Partition Table Header
161   //
162   PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize);
163   if (PrimaryHeader == NULL) {
164     return EFI_OUT_OF_RESOURCES;
165   }
166   Status = DiskIo->ReadDisk (
167                      DiskIo,
168                      BlockIo->Media->MediaId,
169                      1 * BlockIo->Media->BlockSize,
170                      BlockIo->Media->BlockSize,
171                      (UINT8 *)PrimaryHeader
172                      );
173   if (EFI_ERROR (Status)) {
174     DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n"));
175     FreePool (PrimaryHeader);
176     return EFI_DEVICE_ERROR;
177   }
178   //
179   // Read the partition entry.
180   //
181   EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
182   if (EntryPtr == NULL) {
183     FreePool (PrimaryHeader);
184     return EFI_OUT_OF_RESOURCES;
185   }
186   Status = DiskIo->ReadDisk (
187                      DiskIo,
188                      BlockIo->Media->MediaId,
189                      MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
190                      PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
191                      EntryPtr
192                      );
193   if (EFI_ERROR (Status)) {
194     FreePool (PrimaryHeader);
195     FreePool (EntryPtr);
196     return EFI_DEVICE_ERROR;
197   }
198 
199   //
200   // Count the valid partition
201   //
202   PartitionEntry    = (EFI_PARTITION_ENTRY *)EntryPtr;
203   NumberOfPartition = 0;
204   for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
205     if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &gZeroGuid)) {
206       NumberOfPartition++;
207     }
208     PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
209   }
210 
211   //
212   // Prepare Data for Measurement
213   //
214   EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
215                         + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
216   TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));
217   if (TcgEvent == NULL) {
218     FreePool (PrimaryHeader);
219     FreePool (EntryPtr);
220     return EFI_OUT_OF_RESOURCES;
221   }
222 
223   TcgEvent->PCRIndex   = 5;
224   TcgEvent->EventType  = EV_EFI_GPT_EVENT;
225   TcgEvent->EventSize  = EventSize;
226   GptData = (EFI_GPT_DATA *) TcgEvent->Event;
227 
228   //
229   // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
230   //
231   CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
232   GptData->NumberOfPartitions = NumberOfPartition;
233   //
234   // Copy the valid partition entry
235   //
236   PartitionEntry    = (EFI_PARTITION_ENTRY*)EntryPtr;
237   NumberOfPartition = 0;
238   for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
239     if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &gZeroGuid)) {
240       CopyMem (
241         (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,
242         (UINT8 *)PartitionEntry,
243         PrimaryHeader->SizeOfPartitionEntry
244         );
245       NumberOfPartition++;
246     }
247     PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
248   }
249 
250   //
251   // Measure the GPT data
252   //
253   EventNumber = 1;
254   Status = TcgProtocol->HashLogExtendEvent (
255              TcgProtocol,
256              (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,
257              (UINT64) TcgEvent->EventSize,
258              TPM_ALG_SHA,
259              TcgEvent,
260              &EventNumber,
261              &EventLogLastEntry
262              );
263   if (!EFI_ERROR (Status)) {
264     mMeasureGptCount++;
265   }
266 
267   FreePool (PrimaryHeader);
268   FreePool (EntryPtr);
269   FreePool (TcgEvent);
270 
271   return Status;
272 }
273 
274 /**
275   Measure PE image into TPM log based on the authenticode image hashing in
276   PE/COFF Specification 8.0 Appendix A.
277 
278   Caution: This function may receive untrusted input.
279   PE/COFF image is external input, so this function will validate its data structure
280   within this image buffer before use.
281 
282   @param[in] TcgProtocol    Pointer to the located TCG protocol instance.
283   @param[in] ImageAddress   Start address of image buffer.
284   @param[in] ImageSize      Image size
285   @param[in] LinkTimeBase   Address that the image is loaded into memory.
286   @param[in] ImageType      Image subsystem type.
287   @param[in] FilePath       File path is corresponding to the input image.
288 
289   @retval EFI_SUCCESS            Successfully measure image.
290   @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.
291   @retval EFI_UNSUPPORTED        ImageType is unsupported or PE image is mal-format.
292   @retval other error value
293 
294 **/
295 EFI_STATUS
296 EFIAPI
TcgMeasurePeImage(IN EFI_TCG_PROTOCOL * TcgProtocol,IN EFI_PHYSICAL_ADDRESS ImageAddress,IN UINTN ImageSize,IN UINTN LinkTimeBase,IN UINT16 ImageType,IN EFI_DEVICE_PATH_PROTOCOL * FilePath)297 TcgMeasurePeImage (
298   IN  EFI_TCG_PROTOCOL          *TcgProtocol,
299   IN  EFI_PHYSICAL_ADDRESS      ImageAddress,
300   IN  UINTN                     ImageSize,
301   IN  UINTN                     LinkTimeBase,
302   IN  UINT16                    ImageType,
303   IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath
304   )
305 {
306   EFI_STATUS                           Status;
307   TCG_PCR_EVENT                        *TcgEvent;
308   EFI_IMAGE_LOAD_EVENT                 *ImageLoad;
309   UINT32                               FilePathSize;
310   VOID                                 *Sha1Ctx;
311   UINTN                                CtxSize;
312   EFI_IMAGE_DOS_HEADER                 *DosHdr;
313   UINT32                               PeCoffHeaderOffset;
314   EFI_IMAGE_SECTION_HEADER             *Section;
315   UINT8                                *HashBase;
316   UINTN                                HashSize;
317   UINTN                                SumOfBytesHashed;
318   EFI_IMAGE_SECTION_HEADER             *SectionHeader;
319   UINTN                                Index;
320   UINTN                                Pos;
321   UINT16                               Magic;
322   UINT32                               EventSize;
323   UINT32                               EventNumber;
324   EFI_PHYSICAL_ADDRESS                 EventLogLastEntry;
325   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
326   UINT32                               NumberOfRvaAndSizes;
327   BOOLEAN                              HashStatus;
328   UINT32                               CertSize;
329 
330   Status        = EFI_UNSUPPORTED;
331   ImageLoad     = NULL;
332   SectionHeader = NULL;
333   Sha1Ctx       = NULL;
334   FilePathSize  = (UINT32) GetDevicePathSize (FilePath);
335 
336   //
337   // Determine destination PCR by BootPolicy
338   //
339   EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
340   TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));
341   if (TcgEvent == NULL) {
342     return EFI_OUT_OF_RESOURCES;
343   }
344 
345   TcgEvent->EventSize = EventSize;
346   ImageLoad           = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event;
347 
348   switch (ImageType) {
349     case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
350       TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION;
351       TcgEvent->PCRIndex  = 4;
352       break;
353     case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
354       TcgEvent->EventType = EV_EFI_BOOT_SERVICES_DRIVER;
355       TcgEvent->PCRIndex  = 2;
356       break;
357     case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
358       TcgEvent->EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;
359       TcgEvent->PCRIndex  = 2;
360       break;
361     default:
362       DEBUG ((
363         EFI_D_ERROR,
364         "TcgMeasurePeImage: Unknown subsystem type %d",
365         ImageType
366         ));
367       goto Finish;
368   }
369 
370   ImageLoad->ImageLocationInMemory = ImageAddress;
371   ImageLoad->ImageLengthInMemory   = ImageSize;
372   ImageLoad->ImageLinkTimeAddress  = LinkTimeBase;
373   ImageLoad->LengthOfDevicePath    = FilePathSize;
374   if ((FilePath != NULL) && (FilePathSize != 0)) {
375     CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);
376   }
377 
378   //
379   // Check PE/COFF image
380   //
381   DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;
382   PeCoffHeaderOffset = 0;
383   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
384     PeCoffHeaderOffset = DosHdr->e_lfanew;
385   }
386 
387   Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);
388   if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
389     goto Finish;
390   }
391 
392   //
393   // PE/COFF Image Measurement
394   //
395   //    NOTE: The following codes/steps are based upon the authenticode image hashing in
396   //      PE/COFF Specification 8.0 Appendix A.
397   //
398   //
399 
400   // 1.  Load the image header into memory.
401 
402   // 2.  Initialize a SHA hash context.
403   CtxSize = Sha1GetContextSize ();
404   Sha1Ctx = AllocatePool (CtxSize);
405   if (Sha1Ctx == NULL) {
406     Status = EFI_OUT_OF_RESOURCES;
407     goto Finish;
408   }
409 
410   HashStatus = Sha1Init (Sha1Ctx);
411   if (!HashStatus) {
412     goto Finish;
413   }
414 
415   //
416   // Measuring PE/COFF Image Header;
417   // But CheckSum field and SECURITY data directory (certificate) are excluded
418   //
419   if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
420     //
421     // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
422     //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
423     //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
424     //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
425     //
426     Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
427   } else {
428     //
429     // Get the magic value from the PE/COFF Optional Header
430     //
431     Magic = Hdr.Pe32->OptionalHeader.Magic;
432   }
433 
434   //
435   // 3.  Calculate the distance from the base of the image header to the image checksum address.
436   // 4.  Hash the image header from its base to beginning of the image checksum.
437   //
438   HashBase = (UINT8 *) (UINTN) ImageAddress;
439   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
440     //
441     // Use PE32 offset
442     //
443     NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
444     HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);
445   } else {
446     //
447     // Use PE32+ offset
448     //
449     NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
450     HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
451   }
452 
453   HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
454   if (!HashStatus) {
455     goto Finish;
456   }
457 
458   //
459   // 5.  Skip over the image checksum (it occupies a single ULONG).
460   //
461   if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
462     //
463     // 6.  Since there is no Cert Directory in optional header, hash everything
464     //     from the end of the checksum to the end of image header.
465     //
466     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
467       //
468       // Use PE32 offset.
469       //
470       HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
471       HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
472     } else {
473       //
474       // Use PE32+ offset.
475       //
476       HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
477       HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
478     }
479 
480     if (HashSize != 0) {
481       HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);
482       if (!HashStatus) {
483         goto Finish;
484       }
485     }
486   } else {
487     //
488     // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
489     //
490     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
491       //
492       // Use PE32 offset
493       //
494       HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
495       HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
496     } else {
497       //
498       // Use PE32+ offset
499       //
500       HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
501       HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
502     }
503 
504     if (HashSize != 0) {
505       HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);
506       if (!HashStatus) {
507         goto Finish;
508       }
509     }
510 
511     //
512     // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
513     // 9.  Hash everything from the end of the Cert Directory to the end of image header.
514     //
515     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
516       //
517       // Use PE32 offset
518       //
519       HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
520       HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
521     } else {
522       //
523       // Use PE32+ offset
524       //
525       HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
526       HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);
527     }
528 
529     if (HashSize != 0) {
530       HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);
531       if (!HashStatus) {
532         goto Finish;
533       }
534     }
535   }
536 
537   //
538   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
539   //
540   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
541     //
542     // Use PE32 offset
543     //
544     SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
545   } else {
546     //
547     // Use PE32+ offset
548     //
549     SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
550   }
551 
552   //
553   // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
554   //     structures in the image. The 'NumberOfSections' field of the image
555   //     header indicates how big the table should be. Do not include any
556   //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
557   //
558   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
559   if (SectionHeader == NULL) {
560     Status = EFI_OUT_OF_RESOURCES;
561     goto Finish;
562   }
563 
564   //
565   // 12.  Using the 'PointerToRawData' in the referenced section headers as
566   //      a key, arrange the elements in the table in ascending order. In other
567   //      words, sort the section headers according to the disk-file offset of
568   //      the section.
569   //
570   Section = (EFI_IMAGE_SECTION_HEADER *) (
571                (UINT8 *) (UINTN) ImageAddress +
572                PeCoffHeaderOffset +
573                sizeof(UINT32) +
574                sizeof(EFI_IMAGE_FILE_HEADER) +
575                Hdr.Pe32->FileHeader.SizeOfOptionalHeader
576                );
577   for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
578     Pos = Index;
579     while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
580       CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER));
581       Pos--;
582     }
583     CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER));
584     Section += 1;
585   }
586 
587   //
588   // 13.  Walk through the sorted table, bring the corresponding section
589   //      into memory, and hash the entire section (using the 'SizeOfRawData'
590   //      field in the section header to determine the amount of data to hash).
591   // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
592   // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
593   //
594   for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
595     Section  = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index];
596     if (Section->SizeOfRawData == 0) {
597       continue;
598     }
599     HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData;
600     HashSize = (UINTN) Section->SizeOfRawData;
601 
602     HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
603     if (!HashStatus) {
604       goto Finish;
605     }
606 
607     SumOfBytesHashed += HashSize;
608   }
609 
610   //
611   // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
612   //      data in the file that needs to be added to the hash. This data begins
613   //      at file offset SUM_OF_BYTES_HASHED and its length is:
614   //             FileSize  -  (CertDirectory->Size)
615   //
616   if (ImageSize > SumOfBytesHashed) {
617     HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed;
618 
619     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
620       CertSize = 0;
621     } else {
622       if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
623         //
624         // Use PE32 offset.
625         //
626         CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
627       } else {
628         //
629         // Use PE32+ offset.
630         //
631         CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
632       }
633     }
634 
635     if (ImageSize > CertSize + SumOfBytesHashed) {
636       HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed);
637 
638       HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
639       if (!HashStatus) {
640         goto Finish;
641       }
642     } else if (ImageSize < CertSize + SumOfBytesHashed) {
643       goto Finish;
644     }
645   }
646 
647   //
648   // 17.  Finalize the SHA hash.
649   //
650   HashStatus = Sha1Final (Sha1Ctx, (UINT8 *) &TcgEvent->Digest);
651   if (!HashStatus) {
652     goto Finish;
653   }
654 
655   //
656   // Log the PE data
657   //
658   EventNumber = 1;
659   Status = TcgProtocol->HashLogExtendEvent (
660              TcgProtocol,
661              (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) NULL,
662              0,
663              TPM_ALG_SHA,
664              TcgEvent,
665              &EventNumber,
666              &EventLogLastEntry
667              );
668   if (Status == EFI_OUT_OF_RESOURCES) {
669     //
670     // Out of resource here means the image is hashed and its result is extended to PCR.
671     // But the event log cann't be saved since log area is full.
672     // Just return EFI_SUCCESS in order not to block the image load.
673     //
674     Status = EFI_SUCCESS;
675   }
676 
677 Finish:
678   FreePool (TcgEvent);
679 
680   if (SectionHeader != NULL) {
681     FreePool (SectionHeader);
682   }
683 
684   if (Sha1Ctx != NULL ) {
685     FreePool (Sha1Ctx);
686   }
687   return Status;
688 }
689 
690 /**
691   The security handler is used to abstract platform-specific policy
692   from the DXE core response to an attempt to use a file that returns a
693   given status for the authentication check from the section extraction protocol.
694 
695   The possible responses in a given SAP implementation may include locking
696   flash upon failure to authenticate, attestation logging for all signed drivers,
697   and other exception operations.  The File parameter allows for possible logging
698   within the SAP of the driver.
699 
700   If File is NULL, then EFI_INVALID_PARAMETER is returned.
701 
702   If the file specified by File with an authentication status specified by
703   AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.
704 
705   If the file specified by File with an authentication status specified by
706   AuthenticationStatus is not safe for the DXE Core to use under any circumstances,
707   then EFI_ACCESS_DENIED is returned.
708 
709   If the file specified by File with an authentication status specified by
710   AuthenticationStatus is not safe for the DXE Core to use right now, but it
711   might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is
712   returned.
713 
714   @param[in]      AuthenticationStatus  This is the authentication status returned
715                                         from the securitymeasurement services for the
716                                         input file.
717   @param[in]      File       This is a pointer to the device path of the file that is
718                              being dispatched. This will optionally be used for logging.
719   @param[in]      FileBuffer File buffer matches the input file device path.
720   @param[in]      FileSize   Size of File buffer matches the input file device path.
721   @param[in]      BootPolicy A boot policy that was used to call LoadImage() UEFI service.
722 
723   @retval EFI_SUCCESS             The file specified by DevicePath and non-NULL
724                                   FileBuffer did authenticate, and the platform policy dictates
725                                   that the DXE Foundation may use the file.
726   @retval other error value
727 **/
728 EFI_STATUS
729 EFIAPI
DxeTpmMeasureBootHandler(IN UINT32 AuthenticationStatus,IN CONST EFI_DEVICE_PATH_PROTOCOL * File,IN VOID * FileBuffer,IN UINTN FileSize,IN BOOLEAN BootPolicy)730 DxeTpmMeasureBootHandler (
731   IN  UINT32                           AuthenticationStatus,
732   IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,
733   IN  VOID                             *FileBuffer,
734   IN  UINTN                            FileSize,
735   IN  BOOLEAN                          BootPolicy
736   )
737 {
738   EFI_TCG_PROTOCOL                    *TcgProtocol;
739   EFI_STATUS                          Status;
740   TCG_EFI_BOOT_SERVICE_CAPABILITY     ProtocolCapability;
741   UINT32                              TCGFeatureFlags;
742   EFI_PHYSICAL_ADDRESS                EventLogLocation;
743   EFI_PHYSICAL_ADDRESS                EventLogLastEntry;
744   EFI_DEVICE_PATH_PROTOCOL            *DevicePathNode;
745   EFI_DEVICE_PATH_PROTOCOL            *OrigDevicePathNode;
746   EFI_HANDLE                          Handle;
747   EFI_HANDLE                          TempHandle;
748   BOOLEAN                             ApplicationRequired;
749   PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;
750   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;
751   EFI_PHYSICAL_ADDRESS                FvAddress;
752   UINT32                              Index;
753 
754   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);
755   if (EFI_ERROR (Status)) {
756     //
757     // TCG protocol is not installed. So, TPM is not present.
758     // Don't do any measurement, and directly return EFI_SUCCESS.
759     //
760     return EFI_SUCCESS;
761   }
762 
763   ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability);
764   Status = TcgProtocol->StatusCheck (
765              TcgProtocol,
766              &ProtocolCapability,
767              &TCGFeatureFlags,
768              &EventLogLocation,
769              &EventLogLastEntry
770            );
771   if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag || (!ProtocolCapability.TPMPresentFlag)) {
772     //
773     // TPM device doesn't work or activate.
774     //
775     return EFI_SUCCESS;
776   }
777 
778   //
779   // Copy File Device Path
780   //
781   OrigDevicePathNode = DuplicateDevicePath (File);
782 
783   //
784   // 1. Check whether this device path support BlockIo protocol.
785   // Is so, this device path may be a GPT device path.
786   //
787   DevicePathNode = OrigDevicePathNode;
788   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);
789   if (!EFI_ERROR (Status) && !mMeasureGptTableFlag) {
790     //
791     // Find the gpt partion on the given devicepath
792     //
793     DevicePathNode = OrigDevicePathNode;
794     ASSERT (DevicePathNode != NULL);
795     while (!IsDevicePathEnd (DevicePathNode)) {
796       //
797       // Find the Gpt partition
798       //
799       if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH &&
800             DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP) {
801         //
802         // Check whether it is a gpt partition or not
803         //
804         if (((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER &&
805             ((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID) {
806 
807           //
808           // Change the partition device path to its parent device path (disk) and get the handle.
809           //
810           DevicePathNode->Type    = END_DEVICE_PATH_TYPE;
811           DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
812           DevicePathNode          = OrigDevicePathNode;
813           Status = gBS->LocateDevicePath (
814                          &gEfiDiskIoProtocolGuid,
815                          &DevicePathNode,
816                          &Handle
817                          );
818           if (!EFI_ERROR (Status)) {
819             //
820             // Measure GPT disk.
821             //
822             Status = TcgMeasureGptTable (TcgProtocol, Handle);
823             if (!EFI_ERROR (Status)) {
824               //
825               // GPT disk check done.
826               //
827               mMeasureGptTableFlag = TRUE;
828             }
829           }
830           FreePool (OrigDevicePathNode);
831           OrigDevicePathNode = DuplicateDevicePath (File);
832           ASSERT (OrigDevicePathNode != NULL);
833           break;
834         }
835       }
836       DevicePathNode    = NextDevicePathNode (DevicePathNode);
837     }
838   }
839 
840   //
841   // 2. Measure PE image.
842   //
843   ApplicationRequired = FALSE;
844 
845   //
846   // Check whether this device path support FVB protocol.
847   //
848   DevicePathNode = OrigDevicePathNode;
849   Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);
850   if (!EFI_ERROR (Status)) {
851     //
852     // Don't check FV image, and directly return EFI_SUCCESS.
853     // It can be extended to the specific FV authentication according to the different requirement.
854     //
855     if (IsDevicePathEnd (DevicePathNode)) {
856       return EFI_SUCCESS;
857     }
858     //
859     // The PE image from unmeasured Firmware volume need be measured
860     // The PE image from measured Firmware volume will be mearsured according to policy below.
861     //   If it is driver, do not measure
862     //   If it is application, still measure.
863     //
864     ApplicationRequired = TRUE;
865 
866     if (mCacheMeasuredHandle != Handle && mMeasuredHobData != NULL) {
867       //
868       // Search for Root FV of this PE image
869       //
870       TempHandle = Handle;
871       do {
872         Status = gBS->HandleProtocol(
873                         TempHandle,
874                         &gEfiFirmwareVolumeBlockProtocolGuid,
875                         (VOID**)&FvbProtocol
876                         );
877         TempHandle = FvbProtocol->ParentHandle;
878       } while (!EFI_ERROR(Status) && FvbProtocol->ParentHandle != NULL);
879 
880       //
881       // Search in measured FV Hob
882       //
883       Status = FvbProtocol->GetPhysicalAddress(FvbProtocol, &FvAddress);
884       if (EFI_ERROR(Status)){
885         return Status;
886       }
887 
888       ApplicationRequired = FALSE;
889 
890       for (Index = 0; Index < mMeasuredHobData->Num; Index++) {
891         if(mMeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {
892           //
893           // Cache measured FV for next measurement
894           //
895           mCacheMeasuredHandle = Handle;
896           ApplicationRequired  = TRUE;
897           break;
898         }
899       }
900     }
901   }
902 
903   //
904   // File is not found.
905   //
906   if (FileBuffer == NULL) {
907     Status = EFI_SECURITY_VIOLATION;
908     goto Finish;
909   }
910 
911   mTpmImageSize  = FileSize;
912   mFileBuffer = FileBuffer;
913 
914   //
915   // Measure PE Image
916   //
917   DevicePathNode = OrigDevicePathNode;
918   ZeroMem (&ImageContext, sizeof (ImageContext));
919   ImageContext.Handle    = (VOID *) FileBuffer;
920   ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeTpmMeasureBootLibImageRead;
921 
922   //
923   // Get information about the image being loaded
924   //
925   Status = PeCoffLoaderGetImageInfo (&ImageContext);
926   if (EFI_ERROR (Status)) {
927     //
928     // The information can't be got from the invalid PeImage
929     //
930     goto Finish;
931   }
932 
933   //
934   // Measure only application if Application flag is set
935   // Measure drivers and applications if Application flag is not set
936   //
937   if ((!ApplicationRequired) ||
938         (ApplicationRequired && ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {
939     //
940     // Print the image path to be measured.
941     //
942     DEBUG_CODE_BEGIN ();
943       CHAR16                            *ToText;
944       ToText = ConvertDevicePathToText (
945                  DevicePathNode,
946                  FALSE,
947                  TRUE
948                  );
949       if (ToText != NULL) {
950         DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));
951         FreePool (ToText);
952       }
953     DEBUG_CODE_END ();
954 
955     //
956     // Measure PE image into TPM log.
957     //
958     Status = TcgMeasurePeImage (
959                TcgProtocol,
960                (EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer,
961                FileSize,
962                (UINTN) ImageContext.ImageAddress,
963                ImageContext.ImageType,
964                DevicePathNode
965                );
966   }
967 
968   //
969   // Done, free the allocated resource.
970   //
971 Finish:
972   if (OrigDevicePathNode != NULL) {
973     FreePool (OrigDevicePathNode);
974   }
975 
976   return Status;
977 }
978 
979 /**
980   Register the security handler to provide TPM measure boot service.
981 
982   @param  ImageHandle  ImageHandle of the loaded driver.
983   @param  SystemTable  Pointer to the EFI System Table.
984 
985   @retval  EFI_SUCCESS            Register successfully.
986   @retval  EFI_OUT_OF_RESOURCES   No enough memory to register this handler.
987 **/
988 EFI_STATUS
989 EFIAPI
DxeTpmMeasureBootLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)990 DxeTpmMeasureBootLibConstructor (
991   IN EFI_HANDLE        ImageHandle,
992   IN EFI_SYSTEM_TABLE  *SystemTable
993   )
994 {
995   EFI_HOB_GUID_TYPE  *GuidHob;
996 
997   GuidHob = NULL;
998 
999   GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);
1000 
1001   if (GuidHob != NULL) {
1002     mMeasuredHobData = GET_GUID_HOB_DATA (GuidHob);
1003   }
1004 
1005   return RegisterSecurity2Handler (
1006           DxeTpmMeasureBootHandler,
1007           EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
1008           );
1009 }
1010