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