TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeTpmMeasureBootLib.c
Go to the documentation of this file.
1
26#include <PiDxe.h>
27
28#include <Protocol/TcgService.h>
29#include <Protocol/BlockIo.h>
30#include <Protocol/DiskIo.h>
32
33#include <Guid/MeasuredFvHob.h>
34
35#include <Library/BaseLib.h>
36#include <Library/DebugLib.h>
42#include <Library/PeCoffLib.h>
44#include <Library/HobLib.h>
45
47
48//
49// Flag to check GPT partition. It only need be measured once.
50//
51BOOLEAN mMeasureGptTableFlag = FALSE;
52UINTN mMeasureGptCount = 0;
53VOID *mFileBuffer;
54UINTN mTpmImageSize;
55//
56// Measured FV handle cache
57//
58EFI_HANDLE mCacheMeasuredHandle = NULL;
59MEASURED_HOB_DATA *mMeasuredHobData = NULL;
60
77EFIAPI
79 IN VOID *FileHandle,
80 IN UINTN FileOffset,
81 IN OUT UINTN *ReadSize,
82 OUT VOID *Buffer
83 )
84{
85 UINTN EndPosition;
86
87 if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
88 return EFI_INVALID_PARAMETER;
89 }
90
91 if (MAX_ADDRESS - FileOffset < *ReadSize) {
92 return EFI_INVALID_PARAMETER;
93 }
94
95 EndPosition = FileOffset + *ReadSize;
96 if (EndPosition > mTpmImageSize) {
97 *ReadSize = (UINT32)(mTpmImageSize - FileOffset);
98 }
99
100 if (FileOffset >= mTpmImageSize) {
101 *ReadSize = 0;
102 }
103
104 CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
105
106 return EFI_SUCCESS;
107}
108
125EFIAPI
127 IN EFI_TCG_PROTOCOL *TcgProtocol,
128 IN EFI_HANDLE GptHandle
129 )
130{
131 EFI_STATUS Status;
132 EFI_BLOCK_IO_PROTOCOL *BlockIo;
133 EFI_DISK_IO_PROTOCOL *DiskIo;
134 EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
135 EFI_PARTITION_ENTRY *PartitionEntry;
136 UINT8 *EntryPtr;
137 UINTN NumberOfPartition;
138 UINT32 Index;
139 TCG_PCR_EVENT *TcgEvent;
140 EFI_GPT_DATA *GptData;
141 UINT32 EventSize;
142 UINT32 EventNumber;
143 EFI_PHYSICAL_ADDRESS EventLogLastEntry;
144 UINT32 AllocSize;
145
146 GptData = NULL;
147
148 if (mMeasureGptCount > 0) {
149 return EFI_SUCCESS;
150 }
151
152 Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
153 if (EFI_ERROR (Status)) {
154 return EFI_UNSUPPORTED;
155 }
156
157 Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);
158 if (EFI_ERROR (Status)) {
159 return EFI_UNSUPPORTED;
160 }
161
162 //
163 // Read the EFI Partition Table Header
164 //
165 PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *)AllocatePool (BlockIo->Media->BlockSize);
166 if (PrimaryHeader == NULL) {
167 return EFI_OUT_OF_RESOURCES;
168 }
169
170 Status = DiskIo->ReadDisk (
171 DiskIo,
172 BlockIo->Media->MediaId,
173 1 * BlockIo->Media->BlockSize,
174 BlockIo->Media->BlockSize,
175 (UINT8 *)PrimaryHeader
176 );
177 if (EFI_ERROR (Status) || EFI_ERROR (TpmSanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) {
178 DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n"));
179 FreePool (PrimaryHeader);
180 return EFI_DEVICE_ERROR;
181 }
182
183 //
184 // Read the partition entry.
185 //
186 Status = TpmSanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize);
187 if (EFI_ERROR (Status)) {
188 FreePool (PrimaryHeader);
189 return EFI_DEVICE_ERROR;
190 }
191
192 EntryPtr = (UINT8 *)AllocatePool (AllocSize);
193 if (EntryPtr == NULL) {
194 FreePool (PrimaryHeader);
195 return EFI_OUT_OF_RESOURCES;
196 }
197
198 Status = DiskIo->ReadDisk (
199 DiskIo,
200 BlockIo->Media->MediaId,
201 MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
202 AllocSize,
203 EntryPtr
204 );
205 if (EFI_ERROR (Status)) {
206 FreePool (PrimaryHeader);
207 FreePool (EntryPtr);
208 return EFI_DEVICE_ERROR;
209 }
210
211 //
212 // Count the valid partition
213 //
214 PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;
215 NumberOfPartition = 0;
216 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
217 if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {
218 NumberOfPartition++;
219 }
220
221 PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
222 }
223
224 //
225 // Prepare Data for Measurement
226 //
227 Status = TpmSanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize);
228 TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize);
229 if (TcgEvent == NULL) {
230 FreePool (PrimaryHeader);
231 FreePool (EntryPtr);
232 return EFI_OUT_OF_RESOURCES;
233 }
234
235 TcgEvent->PCRIndex = 5;
236 TcgEvent->EventType = EV_EFI_GPT_EVENT;
237 TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
238 GptData = (EFI_GPT_DATA *)TcgEvent->Event;
239
240 //
241 // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
242 //
243 CopyMem ((UINT8 *)GptData, (UINT8 *)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
244 GptData->NumberOfPartitions = NumberOfPartition;
245 //
246 // Copy the valid partition entry
247 //
248 PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;
249 NumberOfPartition = 0;
250 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
251 if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {
252 CopyMem (
253 (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,
254 (UINT8 *)PartitionEntry,
255 PrimaryHeader->SizeOfPartitionEntry
256 );
257 NumberOfPartition++;
258 }
259
260 PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
261 }
262
263 //
264 // Measure the GPT data
265 //
266 EventNumber = 1;
267 Status = TcgProtocol->HashLogExtendEvent (
268 TcgProtocol,
269 (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,
270 (UINT64)TcgEvent->EventSize,
272 TcgEvent,
273 &EventNumber,
274 &EventLogLastEntry
275 );
276 if (!EFI_ERROR (Status)) {
277 mMeasureGptCount++;
278 }
279
280 FreePool (PrimaryHeader);
281 FreePool (EntryPtr);
282 FreePool (TcgEvent);
283
284 return Status;
285}
286
312EFIAPI
314 IN EFI_TCG_PROTOCOL *TcgProtocol,
315 IN EFI_PHYSICAL_ADDRESS ImageAddress,
316 IN UINTN ImageSize,
317 IN UINTN LinkTimeBase,
318 IN UINT16 ImageType,
320 )
321{
322 EFI_STATUS Status;
323 TCG_PCR_EVENT *TcgEvent;
324 EFI_IMAGE_LOAD_EVENT *ImageLoad;
325 UINT32 FilePathSize;
326 VOID *Sha1Ctx;
327 UINTN CtxSize;
328 EFI_IMAGE_DOS_HEADER *DosHdr;
329 UINT32 PeCoffHeaderOffset;
331 UINT8 *HashBase;
332 UINTN HashSize;
333 UINTN SumOfBytesHashed;
334 EFI_IMAGE_SECTION_HEADER *SectionHeader;
335 UINTN Index;
336 UINTN Pos;
337 UINT32 EventSize;
338 UINT32 EventNumber;
339 EFI_PHYSICAL_ADDRESS EventLogLastEntry;
341 UINT32 NumberOfRvaAndSizes;
342 BOOLEAN HashStatus;
343 UINT32 CertSize;
344
345 Status = EFI_UNSUPPORTED;
346 ImageLoad = NULL;
347 SectionHeader = NULL;
348 Sha1Ctx = NULL;
349 TcgEvent = NULL;
350 FilePathSize = (UINT32)GetDevicePathSize (FilePath);
351
352 // Determine destination PCR by BootPolicy
353 //
354 Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize);
355 if (EFI_ERROR (Status)) {
356 return EFI_UNSUPPORTED;
357 }
358
359 TcgEvent = AllocateZeroPool (EventSize);
360 if (TcgEvent == NULL) {
361 return EFI_OUT_OF_RESOURCES;
362 }
363
364 TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
365 ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;
366
367 switch (ImageType) {
368 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
369 TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION;
370 TcgEvent->PCRIndex = 4;
371 break;
372 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
373 TcgEvent->EventType = EV_EFI_BOOT_SERVICES_DRIVER;
374 TcgEvent->PCRIndex = 2;
375 break;
376 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
377 TcgEvent->EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;
378 TcgEvent->PCRIndex = 2;
379 break;
380 default:
381 DEBUG (
382 (
383 DEBUG_ERROR,
384 "TcgMeasurePeImage: Unknown subsystem type %d",
385 ImageType
386 )
387 );
388 goto Finish;
389 }
390
391 ImageLoad->ImageLocationInMemory = ImageAddress;
392 ImageLoad->ImageLengthInMemory = ImageSize;
393 ImageLoad->ImageLinkTimeAddress = LinkTimeBase;
394 ImageLoad->LengthOfDevicePath = FilePathSize;
395 if ((FilePath != NULL) && (FilePathSize != 0)) {
396 CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);
397 }
398
399 //
400 // Check PE/COFF image
401 //
402 DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
403 PeCoffHeaderOffset = 0;
404 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
405 PeCoffHeaderOffset = DosHdr->e_lfanew;
406 }
407
408 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
409 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
410 goto Finish;
411 }
412
413 //
414 // PE/COFF Image Measurement
415 //
416 // NOTE: The following codes/steps are based upon the authenticode image hashing in
417 // PE/COFF Specification 8.0 Appendix A.
418 //
419 //
420
421 // 1. Load the image header into memory.
422
423 // 2. Initialize a SHA hash context.
424 CtxSize = Sha1GetContextSize ();
425 Sha1Ctx = AllocatePool (CtxSize);
426 if (Sha1Ctx == NULL) {
427 Status = EFI_OUT_OF_RESOURCES;
428 goto Finish;
429 }
430
431 HashStatus = Sha1Init (Sha1Ctx);
432 if (!HashStatus) {
433 goto Finish;
434 }
435
436 //
437 // Measuring PE/COFF Image Header;
438 // But CheckSum field and SECURITY data directory (certificate) are excluded
439 //
440
441 //
442 // 3. Calculate the distance from the base of the image header to the image checksum address.
443 // 4. Hash the image header from its base to beginning of the image checksum.
444 //
445 HashBase = (UINT8 *)(UINTN)ImageAddress;
446 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
447 //
448 // Use PE32 offset
449 //
450 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
451 HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
452 } else {
453 //
454 // Use PE32+ offset
455 //
456 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
457 HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
458 }
459
460 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
461 if (!HashStatus) {
462 goto Finish;
463 }
464
465 //
466 // 5. Skip over the image checksum (it occupies a single ULONG).
467 //
468 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
469 //
470 // 6. Since there is no Cert Directory in optional header, hash everything
471 // from the end of the checksum to the end of image header.
472 //
473 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
474 //
475 // Use PE32 offset.
476 //
477 HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
478 HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
479 } else {
480 //
481 // Use PE32+ offset.
482 //
483 HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
484 HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
485 }
486
487 if (HashSize != 0) {
488 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
489 if (!HashStatus) {
490 goto Finish;
491 }
492 }
493 } else {
494 //
495 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
496 //
497 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
498 //
499 // Use PE32 offset
500 //
501 HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
502 HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
503 } else {
504 //
505 // Use PE32+ offset
506 //
507 HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
508 HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
509 }
510
511 if (HashSize != 0) {
512 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
513 if (!HashStatus) {
514 goto Finish;
515 }
516 }
517
518 //
519 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
520 // 9. Hash everything from the end of the Cert Directory to the end of image header.
521 //
522 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
523 //
524 // Use PE32 offset
525 //
526 HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
527 HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
528 } else {
529 //
530 // Use PE32+ offset
531 //
532 HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
533 HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
534 }
535
536 if (HashSize != 0) {
537 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
538 if (!HashStatus) {
539 goto Finish;
540 }
541 }
542 }
543
544 //
545 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
546 //
547 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
548 //
549 // Use PE32 offset
550 //
551 SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
552 } else {
553 //
554 // Use PE32+ offset
555 //
556 SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
557 }
558
559 //
560 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
561 // structures in the image. The 'NumberOfSections' field of the image
562 // header indicates how big the table should be. Do not include any
563 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
564 //
565 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
566 if (SectionHeader == NULL) {
567 Status = EFI_OUT_OF_RESOURCES;
568 goto Finish;
569 }
570
571 //
572 // 12. Using the 'PointerToRawData' in the referenced section headers as
573 // a key, arrange the elements in the table in ascending order. In other
574 // words, sort the section headers according to the disk-file offset of
575 // the section.
576 //
577 Section = (EFI_IMAGE_SECTION_HEADER *)(
578 (UINT8 *)(UINTN)ImageAddress +
579 PeCoffHeaderOffset +
580 sizeof (UINT32) +
581 sizeof (EFI_IMAGE_FILE_HEADER) +
582 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
583 );
584 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
585 Pos = Index;
586 while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
587 CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
588 Pos--;
589 }
590
591 CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
592 Section += 1;
593 }
594
595 //
596 // 13. Walk through the sorted table, bring the corresponding section
597 // into memory, and hash the entire section (using the 'SizeOfRawData'
598 // field in the section header to determine the amount of data to hash).
599 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
600 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
601 //
602 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
603 Section = (EFI_IMAGE_SECTION_HEADER *)&SectionHeader[Index];
604 if (Section->SizeOfRawData == 0) {
605 continue;
606 }
607
608 HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;
609 HashSize = (UINTN)Section->SizeOfRawData;
610
611 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
612 if (!HashStatus) {
613 goto Finish;
614 }
615
616 SumOfBytesHashed += HashSize;
617 }
618
619 //
620 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
621 // data in the file that needs to be added to the hash. This data begins
622 // at file offset SUM_OF_BYTES_HASHED and its length is:
623 // FileSize - (CertDirectory->Size)
624 //
625 if (ImageSize > SumOfBytesHashed) {
626 HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;
627
628 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
629 CertSize = 0;
630 } else {
631 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
632 //
633 // Use PE32 offset.
634 //
635 CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
636 } else {
637 //
638 // Use PE32+ offset.
639 //
640 CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
641 }
642 }
643
644 if (ImageSize > CertSize + SumOfBytesHashed) {
645 HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);
646
647 HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
648 if (!HashStatus) {
649 goto Finish;
650 }
651 } else if (ImageSize < CertSize + SumOfBytesHashed) {
652 goto Finish;
653 }
654 }
655
656 //
657 // 17. Finalize the SHA hash.
658 //
659 HashStatus = Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest);
660 if (!HashStatus) {
661 goto Finish;
662 }
663
664 //
665 // Log the PE data
666 //
667 EventNumber = 1;
668 Status = TcgProtocol->HashLogExtendEvent (
669 TcgProtocol,
671 0,
673 TcgEvent,
674 &EventNumber,
675 &EventLogLastEntry
676 );
677 if (Status == EFI_OUT_OF_RESOURCES) {
678 //
679 // Out of resource here means the image is hashed and its result is extended to PCR.
680 // But the event log can't be saved since log area is full.
681 // Just return EFI_SUCCESS in order not to block the image load.
682 //
683 Status = EFI_SUCCESS;
684 }
685
686Finish:
687 FreePool (TcgEvent);
688
689 if (SectionHeader != NULL) {
690 FreePool (SectionHeader);
691 }
692
693 if (Sha1Ctx != NULL ) {
694 FreePool (Sha1Ctx);
695 }
696
697 return Status;
698}
699
739EFIAPI
741 IN UINT32 AuthenticationStatus,
742 IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
743 IN VOID *FileBuffer,
744 IN UINTN FileSize,
745 IN BOOLEAN BootPolicy
746 )
747{
748 EFI_TCG_PROTOCOL *TcgProtocol;
749 EFI_STATUS Status;
750 TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability;
751 UINT32 TCGFeatureFlags;
752 EFI_PHYSICAL_ADDRESS EventLogLocation;
753 EFI_PHYSICAL_ADDRESS EventLogLastEntry;
754 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
755 EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;
756 EFI_HANDLE Handle;
757 EFI_HANDLE TempHandle;
758 BOOLEAN ApplicationRequired;
759 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
761 EFI_PHYSICAL_ADDRESS FvAddress;
762 UINT32 Index;
763
764 Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
765 if (EFI_ERROR (Status)) {
766 //
767 // TCG protocol is not installed. So, TPM is not present.
768 // Don't do any measurement, and directly return EFI_SUCCESS.
769 //
770 return EFI_SUCCESS;
771 }
772
773 ProtocolCapability.Size = (UINT8)sizeof (ProtocolCapability);
774 Status = TcgProtocol->StatusCheck (
775 TcgProtocol,
776 &ProtocolCapability,
777 &TCGFeatureFlags,
778 &EventLogLocation,
779 &EventLogLastEntry
780 );
781 if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag || (!ProtocolCapability.TPMPresentFlag)) {
782 //
783 // TPM device doesn't work or activate.
784 //
785 return EFI_SUCCESS;
786 }
787
788 //
789 // Copy File Device Path
790 //
791 OrigDevicePathNode = DuplicateDevicePath (File);
792
793 //
794 // 1. Check whether this device path support BlockIo protocol.
795 // Is so, this device path may be a GPT device path.
796 //
797 DevicePathNode = OrigDevicePathNode;
798 Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);
799 if (!EFI_ERROR (Status) && !mMeasureGptTableFlag) {
800 //
801 // Find the gpt partition on the given devicepath
802 //
803 DevicePathNode = OrigDevicePathNode;
804 ASSERT (DevicePathNode != NULL);
805 while (!IsDevicePathEnd (DevicePathNode)) {
806 //
807 // Find the Gpt partition
808 //
809 if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
810 (DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP))
811 {
812 //
813 // Check whether it is a gpt partition or not
814 //
815 if ((((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) &&
816 (((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID))
817 {
818 //
819 // Change the partition device path to its parent device path (disk) and get the handle.
820 //
821 DevicePathNode->Type = END_DEVICE_PATH_TYPE;
822 DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
823 DevicePathNode = OrigDevicePathNode;
824 Status = gBS->LocateDevicePath (
825 &gEfiDiskIoProtocolGuid,
826 &DevicePathNode,
827 &Handle
828 );
829 if (!EFI_ERROR (Status)) {
830 //
831 // Measure GPT disk.
832 //
833 Status = TcgMeasureGptTable (TcgProtocol, Handle);
834 if (!EFI_ERROR (Status)) {
835 //
836 // GPT disk check done.
837 //
838 mMeasureGptTableFlag = TRUE;
839 }
840 }
841
842 FreePool (OrigDevicePathNode);
843 OrigDevicePathNode = DuplicateDevicePath (File);
844 ASSERT (OrigDevicePathNode != NULL);
845 break;
846 }
847 }
848
849 DevicePathNode = NextDevicePathNode (DevicePathNode);
850 }
851 }
852
853 //
854 // 2. Measure PE image.
855 //
856 ApplicationRequired = FALSE;
857
858 //
859 // Check whether this device path support FVB protocol.
860 //
861 DevicePathNode = OrigDevicePathNode;
862 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);
863 if (!EFI_ERROR (Status)) {
864 //
865 // Don't check FV image, and directly return EFI_SUCCESS.
866 // It can be extended to the specific FV authentication according to the different requirement.
867 //
868 if (IsDevicePathEnd (DevicePathNode)) {
869 return EFI_SUCCESS;
870 }
871
872 //
873 // The PE image from unmeasured Firmware volume need be measured
874 // The PE image from measured Firmware volume will be measured according to policy below.
875 // If it is driver, do not measure
876 // If it is application, still measure.
877 //
878 ApplicationRequired = TRUE;
879
880 if ((mCacheMeasuredHandle != Handle) && (mMeasuredHobData != NULL)) {
881 //
882 // Search for Root FV of this PE image
883 //
884 TempHandle = Handle;
885 do {
886 Status = gBS->HandleProtocol (
887 TempHandle,
888 &gEfiFirmwareVolumeBlockProtocolGuid,
889 (VOID **)&FvbProtocol
890 );
891 TempHandle = FvbProtocol->ParentHandle;
892 } while (!EFI_ERROR (Status) && FvbProtocol->ParentHandle != NULL);
893
894 //
895 // Search in measured FV Hob
896 //
897 Status = FvbProtocol->GetPhysicalAddress (FvbProtocol, &FvAddress);
898 if (EFI_ERROR (Status)) {
899 return Status;
900 }
901
902 ApplicationRequired = FALSE;
903
904 for (Index = 0; Index < mMeasuredHobData->Num; Index++) {
905 if (mMeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {
906 //
907 // Cache measured FV for next measurement
908 //
909 mCacheMeasuredHandle = Handle;
910 ApplicationRequired = TRUE;
911 break;
912 }
913 }
914 }
915 }
916
917 //
918 // File is not found.
919 //
920 if (FileBuffer == NULL) {
921 Status = EFI_SECURITY_VIOLATION;
922 goto Finish;
923 }
924
925 mTpmImageSize = FileSize;
926 mFileBuffer = FileBuffer;
927
928 //
929 // Measure PE Image
930 //
931 DevicePathNode = OrigDevicePathNode;
932 ZeroMem (&ImageContext, sizeof (ImageContext));
933 ImageContext.Handle = (VOID *)FileBuffer;
935
936 //
937 // Get information about the image being loaded
938 //
939 Status = PeCoffLoaderGetImageInfo (&ImageContext);
940 if (EFI_ERROR (Status)) {
941 //
942 // Check for invalid parameters.
943 //
944 if (File == NULL) {
945 return EFI_ACCESS_DENIED;
946 }
947
948 //
949 // The information can't be got from the invalid PeImage
950 //
951 goto Finish;
952 }
953
954 //
955 // Measure only application if Application flag is set
956 // Measure drivers and applications if Application flag is not set
957 //
958 if ((!ApplicationRequired) ||
959 (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))
960 {
961 //
962 // Print the image path to be measured.
963 //
965 CHAR16 *ToText;
966 ToText = ConvertDevicePathToText (
967 DevicePathNode,
968 FALSE,
969 TRUE
970 );
971 if (ToText != NULL) {
972 DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));
973 FreePool (ToText);
974 }
975
977
978 //
979 // Measure PE image into TPM log.
980 //
981 Status = TcgMeasurePeImage (
982 TcgProtocol,
983 (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,
984 FileSize,
985 (UINTN)ImageContext.ImageAddress,
986 ImageContext.ImageType,
987 DevicePathNode
988 );
989 }
990
991 //
992 // Done, free the allocated resource.
993 //
994Finish:
995 if (OrigDevicePathNode != NULL) {
996 FreePool (OrigDevicePathNode);
997 }
998
999 return Status;
1000}
1001
1012EFIAPI
1014 IN EFI_HANDLE ImageHandle,
1015 IN EFI_SYSTEM_TABLE *SystemTable
1016 )
1017{
1018 EFI_HOB_GUID_TYPE *GuidHob;
1019
1020 GuidHob = NULL;
1021
1022 GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);
1023
1024 if (GuidHob != NULL) {
1025 mMeasuredHobData = GET_GUID_HOB_DATA (GuidHob);
1026 }
1027
1030 EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
1031 );
1032}
UINT64 UINTN
#define MAX_ADDRESS
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
BOOLEAN EFIAPI Sha1Final(IN OUT VOID *Sha1Context, OUT UINT8 *HashValue)
Definition: CryptSha1.c:163
BOOLEAN EFIAPI Sha1Init(OUT VOID *Sha1Context)
Definition: CryptSha1.c:46
UINTN EFIAPI Sha1GetContextSize(VOID)
Definition: CryptSha1.c:22
BOOLEAN EFIAPI Sha1Update(IN OUT VOID *Sha1Context, IN CONST VOID *Data, IN UINTN DataSize)
Definition: CryptSha1.c:115
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EFIAPI IsZeroGuid(IN CONST GUID *Guid)
Definition: MemLibGuid.c:156
#define MEDIA_HARDDRIVE_DP
Definition: DevicePath.h:1014
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
EFI_STATUS EFIAPI TcgMeasureGptTable(IN EFI_TCG_PROTOCOL *TcgProtocol, IN EFI_HANDLE GptHandle)
EFI_STATUS 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)
EFI_STATUS EFIAPI DxeTpmMeasureBootHandler(IN UINT32 AuthenticationStatus, IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL, IN VOID *FileBuffer, IN UINTN FileSize, IN BOOLEAN BootPolicy)
EFI_STATUS EFIAPI DxeTpmMeasureBootLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI DxeTpmMeasureBootLibImageRead(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
EFI_STATUS EFIAPI TpmSanitizePrimaryHeaderAllocationSize(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, OUT UINT32 *AllocationSize)
EFI_STATUS TpmSanitizePrimaryHeaderGptEventSize(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN UINTN NumberOfPartition, OUT UINT32 *EventSize)
EFI_STATUS EFIAPI TpmSanitizeEfiPartitionTableHeader(IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo)
EFI_STATUS TpmSanitizePeImageEventSize(IN UINT32 FilePathSize, OUT UINT32 *EventSize)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
RETURN_STATUS(EFIAPI * PE_COFF_LOADER_READ_FILE)(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
Definition: PeCoffLib.h:65
RETURN_STATUS EFIAPI PeCoffLoaderGetImageInfo(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:577
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: PeImage.h:143
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define EFI_AUTH_OPERATION_IMAGE_REQUIRED
EFI_STATUS EFIAPI RegisterSecurity2Handler(IN SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler, IN UINT32 AuthenticationOperation)
#define TPM_ALG_SHA
The SHA1 algorithm.
Definition: Tpm12.h:365
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
struct tdTCG_PCR_EVENT_HDR TCG_PCR_EVENT_HDR
EFI_BLOCK_IO_MEDIA * Media
Definition: BlockIo.h:224
BOOLEAN TPMDeactivatedFlag
00h = TPM not present.
Definition: TcgService.h:34
UINT32 BlockSize
Definition: BlockIo.h:167
UINT32 e_lfanew
File address of new exe header.
Definition: PeImage.h:76
UINT16 e_magic
Magic number.
Definition: PeImage.h:58
EFI_GUID PartitionTypeGUID
Definition: UefiGpt.h:91
UINT32 NumberOfPartitionEntries
Definition: UefiGpt.h:66
PE_COFF_LOADER_READ_FILE ImageRead
Definition: PeCoffLib.h:100
PHYSICAL_ADDRESS ImageAddress
Definition: PeCoffLib.h:79
UINT8 Event[1]
The event data.
UINT32 EventSize
Size of the event data.
TCG_DIGEST Digest
Value extended into PCRIndex.
TCG_EVENTTYPE EventType
TCG EFI event type.
TCG_PCRINDEX PCRIndex
PCRIndex event extended to.