]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
SecurityPkg/TPM2: Move GetDigestFromDigestList() to Tpm2CommandLib
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Pei / Tcg2Pei.c
1 /** @file
2 Initialize TPM2 device and measure FVs before handing off control to DXE.
3
4 Copyright (c) 2015 - 2016, 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 <PiPei.h>
16
17 #include <IndustryStandard/UefiTcgPlatform.h>
18 #include <Ppi/FirmwareVolumeInfo.h>
19 #include <Ppi/FirmwareVolumeInfo2.h>
20 #include <Ppi/LockPhysicalPresence.h>
21 #include <Ppi/TpmInitialized.h>
22 #include <Ppi/FirmwareVolume.h>
23 #include <Ppi/EndOfPeiPhase.h>
24 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
25
26 #include <Guid/TcgEventHob.h>
27 #include <Guid/MeasuredFvHob.h>
28 #include <Guid/TpmInstance.h>
29
30 #include <Library/DebugLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/PeiServicesLib.h>
33 #include <Library/PeimEntryPoint.h>
34 #include <Library/Tpm2CommandLib.h>
35 #include <Library/Tpm2DeviceLib.h>
36 #include <Library/HashLib.h>
37 #include <Library/HobLib.h>
38 #include <Library/PcdLib.h>
39 #include <Library/PeiServicesTablePointerLib.h>
40 #include <Protocol/Tcg2Protocol.h>
41 #include <Library/PerformanceLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/ReportStatusCodeLib.h>
44 #include <Library/Tcg2PhysicalPresenceLib.h>
45
46 #define PERF_ID_TCG2_PEI 0x3080
47
48 typedef struct {
49 EFI_GUID *EventGuid;
50 EFI_TCG2_EVENT_LOG_FORMAT LogFormat;
51 } TCG2_EVENT_INFO_STRUCT;
52
53 TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = {
54 {&gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2},
55 {&gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2},
56 };
57
58 BOOLEAN mImageInMemory = FALSE;
59 EFI_PEI_FILE_HANDLE mFileHandle;
60
61 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = {
62 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
63 &gPeiTpmInitializedPpiGuid,
64 NULL
65 };
66
67 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
68 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
69 &gPeiTpmInitializationDonePpiGuid,
70 NULL
71 };
72
73 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
74 UINT32 mMeasuredBaseFvIndex = 0;
75
76 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
77 UINT32 mMeasuredChildFvIndex = 0;
78
79 /**
80 Measure and record the Firmware Volum Information once FvInfoPPI install.
81
82 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
83 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
84 @param[in] Ppi Address of the PPI that was installed.
85
86 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
87 @return Others Fail to measure FV.
88
89 **/
90 EFI_STATUS
91 EFIAPI
92 FirmwareVolmeInfoPpiNotifyCallback (
93 IN EFI_PEI_SERVICES **PeiServices,
94 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
95 IN VOID *Ppi
96 );
97
98 /**
99 Record all measured Firmware Volum Information into a Guid Hob
100
101 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
102 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
103 @param[in] Ppi Address of the PPI that was installed.
104
105 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
106 @return Others Fail to measure FV.
107
108 **/
109 EFI_STATUS
110 EFIAPI
111 EndofPeiSignalNotifyCallBack (
112 IN EFI_PEI_SERVICES **PeiServices,
113 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
114 IN VOID *Ppi
115 );
116
117 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
118 {
119 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
120 &gEfiPeiFirmwareVolumeInfoPpiGuid,
121 FirmwareVolmeInfoPpiNotifyCallback
122 },
123 {
124 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
125 &gEfiPeiFirmwareVolumeInfo2PpiGuid,
126 FirmwareVolmeInfoPpiNotifyCallback
127 },
128 {
129 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
130 &gEfiEndOfPeiSignalPpiGuid,
131 EndofPeiSignalNotifyCallBack
132 }
133 };
134
135 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
136
137 /**
138 Record all measured Firmware Volum Information into a Guid Hob
139 Guid Hob payload layout is
140
141 UINT32 *************************** FIRMWARE_BLOB number
142 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
143
144 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
145 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
146 @param[in] Ppi Address of the PPI that was installed.
147
148 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
149 @return Others Fail to measure FV.
150
151 **/
152 EFI_STATUS
153 EFIAPI
154 EndofPeiSignalNotifyCallBack (
155 IN EFI_PEI_SERVICES **PeiServices,
156 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
157 IN VOID *Ppi
158 )
159 {
160 MEASURED_HOB_DATA *MeasuredHobData;
161
162 MeasuredHobData = NULL;
163
164 //
165 // Create a Guid hob to save all measured Fv
166 //
167 MeasuredHobData = BuildGuidHob(
168 &gMeasuredFvHobGuid,
169 sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
170 );
171
172 if (MeasuredHobData != NULL){
173 //
174 // Save measured FV info enty number
175 //
176 MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
177
178 //
179 // Save measured base Fv info
180 //
181 CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
182
183 //
184 // Save measured child Fv info
185 //
186 CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
187 }
188
189 return EFI_SUCCESS;
190 }
191
192 /**
193 Get TPML_DIGEST_VALUES data size.
194
195 @param[in] DigestList TPML_DIGEST_VALUES data.
196
197 @return TPML_DIGEST_VALUES data size.
198 **/
199 UINT32
200 GetDigestListSize (
201 IN TPML_DIGEST_VALUES *DigestList
202 )
203 {
204 UINTN Index;
205 UINT16 DigestSize;
206 UINT32 TotalSize;
207
208 TotalSize = sizeof(DigestList->count);
209 for (Index = 0; Index < DigestList->count; Index++) {
210 DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
211 TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize;
212 }
213
214 return TotalSize;
215 }
216
217 /**
218 Return if hash alg is supported in TPM PCR bank.
219
220 @param HashAlg Hash algorithm to be checked.
221
222 @retval TRUE Hash algorithm is supported.
223 @retval FALSE Hash algorithm is not supported.
224 **/
225 BOOLEAN
226 IsHashAlgSupportedInPcrBank (
227 IN TPMI_ALG_HASH HashAlg
228 )
229 {
230 UINT32 ActivePcrBanks;
231
232 ActivePcrBanks = PcdGet32 (PcdTpm2HashMask);
233 switch (HashAlg) {
234 case TPM_ALG_SHA1:
235 if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
236 return TRUE;
237 }
238 break;
239 case TPM_ALG_SHA256:
240 if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
241 return TRUE;
242 }
243 break;
244 case TPM_ALG_SHA384:
245 if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
246 return TRUE;
247 }
248 break;
249 case TPM_ALG_SHA512:
250 if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
251 return TRUE;
252 }
253 break;
254 case TPM_ALG_SM3_256:
255 if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
256 return TRUE;
257 }
258 break;
259 }
260
261 return FALSE;
262 }
263
264 /**
265 Copy TPML_DIGEST_VALUES into a buffer
266
267 @param[in,out] Buffer Buffer to hold TPML_DIGEST_VALUES.
268 @param[in] DigestList TPML_DIGEST_VALUES to be copied.
269
270 @return The end of buffer to hold TPML_DIGEST_VALUES.
271 **/
272 VOID *
273 CopyDigestListToBuffer (
274 IN OUT VOID *Buffer,
275 IN TPML_DIGEST_VALUES *DigestList
276 )
277 {
278 UINTN Index;
279 UINT16 DigestSize;
280
281 CopyMem (Buffer, &DigestList->count, sizeof(DigestList->count));
282 Buffer = (UINT8 *)Buffer + sizeof(DigestList->count);
283 for (Index = 0; Index < DigestList->count; Index++) {
284 if (!IsHashAlgSupportedInPcrBank (DigestList->digests[Index].hashAlg)) {
285 DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg));
286 continue;
287 }
288 CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg));
289 Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg);
290 DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
291 CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);
292 Buffer = (UINT8 *)Buffer + DigestSize;
293 }
294
295 return Buffer;
296 }
297
298 /**
299 Set Tpm2HashMask PCD value according to TPM2 PCR bank.
300 **/
301 VOID
302 SetTpm2HashMask (
303 VOID
304 )
305 {
306 EFI_STATUS Status;
307 UINT32 ActivePcrBanks;
308 TPML_PCR_SELECTION Pcrs;
309 UINTN Index;
310
311 DEBUG ((EFI_D_ERROR, "SetTpm2HashMask!\n"));
312
313 Status = Tpm2GetCapabilityPcrs (&Pcrs);
314 if (EFI_ERROR (Status)) {
315 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));
316 ActivePcrBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1;
317 } else {
318 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));
319 ActivePcrBanks = 0;
320 for (Index = 0; Index < Pcrs.count; Index++) {
321 DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash));
322 switch (Pcrs.pcrSelections[Index].hash) {
323 case TPM_ALG_SHA1:
324 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
325 ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA1;
326 }
327 break;
328 case TPM_ALG_SHA256:
329 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
330 ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA256;
331 }
332 break;
333 case TPM_ALG_SHA384:
334 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
335 ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA384;
336 }
337 break;
338 case TPM_ALG_SHA512:
339 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
340 ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA512;
341 }
342 break;
343 case TPM_ALG_SM3_256:
344 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
345 ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SM3_256;
346 }
347 break;
348 }
349 }
350 }
351 Status = PcdSet32S (PcdTpm2HashMask, ActivePcrBanks);
352 ASSERT_EFI_ERROR (Status);
353 }
354
355 /**
356 Add a new entry to the Event Log.
357
358 @param[in] DigestList A list of digest.
359 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
360 @param[in] NewEventData Pointer to the new event data.
361
362 @retval EFI_SUCCESS The new event log entry was added.
363 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
364 **/
365 EFI_STATUS
366 LogHashEvent (
367 IN TPML_DIGEST_VALUES *DigestList,
368 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,
369 IN UINT8 *NewEventData
370 )
371 {
372 VOID *HobData;
373 EFI_STATUS Status;
374 UINTN Index;
375 EFI_STATUS RetStatus;
376 UINT32 SupportedEventLogs;
377 TCG_PCR_EVENT2 *TcgPcrEvent2;
378 UINT8 *DigestBuffer;
379
380 SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
381
382 RetStatus = EFI_SUCCESS;
383 for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) {
384 if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
385 DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
386 switch (mTcg2EventInfo[Index].LogFormat) {
387 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
388 Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
389 if (!EFI_ERROR (Status)) {
390 HobData = BuildGuidHob (
391 &gTcgEventEntryHobGuid,
392 sizeof (*NewEventHdr) + NewEventHdr->EventSize
393 );
394 if (HobData == NULL) {
395 RetStatus = EFI_OUT_OF_RESOURCES;
396 break;
397 }
398
399 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
400 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
401 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
402 }
403 break;
404 case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
405 HobData = BuildGuidHob (
406 &gTcgEvent2EntryHobGuid,
407 sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
408 );
409 if (HobData == NULL) {
410 RetStatus = EFI_OUT_OF_RESOURCES;
411 break;
412 }
413
414 TcgPcrEvent2 = HobData;
415 TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
416 TcgPcrEvent2->EventType = NewEventHdr->EventType;
417 DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
418 DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList);
419 CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));
420 DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
421 CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
422 break;
423 }
424 }
425 }
426
427 return RetStatus;
428 }
429
430 /**
431 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
432 and build a GUIDed HOB recording the event which will be passed to the DXE phase and
433 added into the Event Log.
434
435 @param[in] Flags Bitmap providing additional information.
436 @param[in] HashData Physical address of the start of the data buffer
437 to be hashed, extended, and logged.
438 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
439 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
440 @param[in] NewEventData Pointer to the new event data.
441
442 @retval EFI_SUCCESS Operation completed successfully.
443 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
444 @retval EFI_DEVICE_ERROR The command was unsuccessful.
445
446 **/
447 EFI_STATUS
448 HashLogExtendEvent (
449 IN UINT64 Flags,
450 IN UINT8 *HashData,
451 IN UINTN HashDataLen,
452 IN TCG_PCR_EVENT_HDR *NewEventHdr,
453 IN UINT8 *NewEventData
454 )
455 {
456 EFI_STATUS Status;
457 TPML_DIGEST_VALUES DigestList;
458
459 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
460 return EFI_DEVICE_ERROR;
461 }
462
463 Status = HashAndExtend (
464 NewEventHdr->PCRIndex,
465 HashData,
466 HashDataLen,
467 &DigestList
468 );
469 if (!EFI_ERROR (Status)) {
470 if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
471 Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
472 }
473 }
474
475 if (Status == EFI_DEVICE_ERROR) {
476 DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
477 BuildGuidHob (&gTpmErrorHobGuid,0);
478 REPORT_STATUS_CODE (
479 EFI_ERROR_CODE | EFI_ERROR_MINOR,
480 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
481 );
482 }
483
484 return Status;
485 }
486
487 /**
488 Measure CRTM version.
489
490 @retval EFI_SUCCESS Operation completed successfully.
491 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
492 @retval EFI_DEVICE_ERROR The command was unsuccessful.
493
494 **/
495 EFI_STATUS
496 MeasureCRTMVersion (
497 VOID
498 )
499 {
500 TCG_PCR_EVENT_HDR TcgEventHdr;
501
502 //
503 // Use FirmwareVersion string to represent CRTM version.
504 // OEMs should get real CRTM version string and measure it.
505 //
506
507 TcgEventHdr.PCRIndex = 0;
508 TcgEventHdr.EventType = EV_S_CRTM_VERSION;
509 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
510
511 return HashLogExtendEvent (
512 0,
513 (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
514 TcgEventHdr.EventSize,
515 &TcgEventHdr,
516 (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
517 );
518 }
519
520 /**
521 Measure FV image.
522 Add it into the measured FV list after the FV is measured successfully.
523
524 @param[in] FvBase Base address of FV image.
525 @param[in] FvLength Length of FV image.
526
527 @retval EFI_SUCCESS Fv image is measured successfully
528 or it has been already measured.
529 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
530 @retval EFI_DEVICE_ERROR The command was unsuccessful.
531
532 **/
533 EFI_STATUS
534 MeasureFvImage (
535 IN EFI_PHYSICAL_ADDRESS FvBase,
536 IN UINT64 FvLength
537 )
538 {
539 UINT32 Index;
540 EFI_STATUS Status;
541 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
542 TCG_PCR_EVENT_HDR TcgEventHdr;
543
544 //
545 // Check if it is in Excluded FV list
546 //
547 if (mMeasurementExcludedFvPpi != NULL) {
548 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
549 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
550 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));
551 DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));
552 return EFI_SUCCESS;
553 }
554 }
555 }
556
557 //
558 // Check whether FV is in the measured FV list.
559 //
560 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
561 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
562 return EFI_SUCCESS;
563 }
564 }
565
566 //
567 // Measure and record the FV to the TPM
568 //
569 FvBlob.BlobBase = FvBase;
570 FvBlob.BlobLength = FvLength;
571
572 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));
573 DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));
574
575 TcgEventHdr.PCRIndex = 0;
576 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
577 TcgEventHdr.EventSize = sizeof (FvBlob);
578
579 Status = HashLogExtendEvent (
580 0,
581 (UINT8*) (UINTN) FvBlob.BlobBase,
582 (UINTN) FvBlob.BlobLength,
583 &TcgEventHdr,
584 (UINT8*) &FvBlob
585 );
586
587 //
588 // Add new FV into the measured FV list.
589 //
590 ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
591 if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
592 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;
593 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
594 mMeasuredBaseFvIndex++;
595 }
596
597 return Status;
598 }
599
600 /**
601 Measure main BIOS.
602
603 @retval EFI_SUCCESS Operation completed successfully.
604 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
605 @retval EFI_DEVICE_ERROR The command was unsuccessful.
606
607 **/
608 EFI_STATUS
609 MeasureMainBios (
610 VOID
611 )
612 {
613 EFI_STATUS Status;
614 UINT32 FvInstances;
615 EFI_PEI_FV_HANDLE VolumeHandle;
616 EFI_FV_INFO VolumeInfo;
617 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
618
619 PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);
620 FvInstances = 0;
621 while (TRUE) {
622 //
623 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
624 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
625 // platform for special CRTM TPM measuring.
626 //
627 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
628 if (EFI_ERROR (Status)) {
629 break;
630 }
631
632 //
633 // Measure and record the firmware volume that is dispatched by PeiCore
634 //
635 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
636 ASSERT_EFI_ERROR (Status);
637 //
638 // Locate the corresponding FV_PPI according to founded FV's format guid
639 //
640 Status = PeiServicesLocatePpi (
641 &VolumeInfo.FvFormat,
642 0,
643 NULL,
644 (VOID**)&FvPpi
645 );
646 if (!EFI_ERROR (Status)) {
647 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
648 }
649
650 FvInstances++;
651 }
652 PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);
653
654 return EFI_SUCCESS;
655 }
656
657 /**
658 Measure and record the Firmware Volum Information once FvInfoPPI install.
659
660 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
661 @param[in] NotifyDescriptor Address of the notification descriptor data structure.
662 @param[in] Ppi Address of the PPI that was installed.
663
664 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.
665 @return Others Fail to measure FV.
666
667 **/
668 EFI_STATUS
669 EFIAPI
670 FirmwareVolmeInfoPpiNotifyCallback (
671 IN EFI_PEI_SERVICES **PeiServices,
672 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
673 IN VOID *Ppi
674 )
675 {
676 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
677 EFI_STATUS Status;
678 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
679 UINTN Index;
680
681 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
682
683 //
684 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
685 //
686 Status = PeiServicesLocatePpi (
687 &Fv->FvFormat,
688 0,
689 NULL,
690 (VOID**)&FvPpi
691 );
692 if (EFI_ERROR (Status)) {
693 return EFI_SUCCESS;
694 }
695
696 //
697 // This is an FV from an FFS file, and the parent FV must have already been measured,
698 // No need to measure twice, so just record the FV and return
699 //
700 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
701
702 ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
703 if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
704 //
705 // Check whether FV is in the measured child FV list.
706 //
707 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
708 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
709 return EFI_SUCCESS;
710 }
711 }
712 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
713 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
714 mMeasuredChildFvIndex++;
715 }
716 return EFI_SUCCESS;
717 }
718
719 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
720 }
721
722 /**
723 Do measurement after memory is ready.
724
725 @param[in] PeiServices Describes the list of possible PEI Services.
726
727 @retval EFI_SUCCESS Operation completed successfully.
728 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
729 @retval EFI_DEVICE_ERROR The command was unsuccessful.
730
731 **/
732 EFI_STATUS
733 PeimEntryMP (
734 IN EFI_PEI_SERVICES **PeiServices
735 )
736 {
737 EFI_STATUS Status;
738
739 Status = PeiServicesLocatePpi (
740 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
741 0,
742 NULL,
743 (VOID**)&mMeasurementExcludedFvPpi
744 );
745 // Do not check status, because it is optional
746
747 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
748 ASSERT (mMeasuredBaseFvInfo != NULL);
749 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
750 ASSERT (mMeasuredChildFvInfo != NULL);
751
752 if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
753 Status = MeasureCRTMVersion ();
754 }
755
756 Status = MeasureMainBios ();
757
758 //
759 // Post callbacks:
760 // for the FvInfoPpi services to measure and record
761 // the additional Fvs to TPM
762 //
763 Status = PeiServicesNotifyPpi (&mNotifyList[0]);
764 ASSERT_EFI_ERROR (Status);
765
766 return Status;
767 }
768
769 /**
770 Measure and log Separator event with error, and extend the measurement result into a specific PCR.
771
772 @param[in] PCRIndex PCR index.
773
774 @retval EFI_SUCCESS Operation completed successfully.
775 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
776
777 **/
778 EFI_STATUS
779 MeasureSeparatorEventWithError (
780 IN TPM_PCRINDEX PCRIndex
781 )
782 {
783 TCG_PCR_EVENT_HDR TcgEvent;
784 UINT32 EventData;
785
786 //
787 // Use EventData 0x1 to indicate there is error.
788 //
789 EventData = 0x1;
790 TcgEvent.PCRIndex = PCRIndex;
791 TcgEvent.EventType = EV_SEPARATOR;
792 TcgEvent.EventSize = (UINT32)sizeof (EventData);
793 return HashLogExtendEvent(0,(UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
794 }
795
796 /**
797 Entry point of this module.
798
799 @param[in] FileHandle Handle of the file being invoked.
800 @param[in] PeiServices Describes the list of possible PEI Services.
801
802 @return Status.
803
804 **/
805 EFI_STATUS
806 EFIAPI
807 PeimEntryMA (
808 IN EFI_PEI_FILE_HANDLE FileHandle,
809 IN CONST EFI_PEI_SERVICES **PeiServices
810 )
811 {
812 EFI_STATUS Status;
813 EFI_STATUS Status2;
814 EFI_BOOT_MODE BootMode;
815 TPM_PCRINDEX PcrIndex;
816 BOOLEAN S3ErrorReport;
817
818 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
819 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
820 DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));
821 return EFI_UNSUPPORTED;
822 }
823
824 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
825 DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
826 return EFI_DEVICE_ERROR;
827 }
828
829 Status = PeiServicesGetBootMode (&BootMode);
830 ASSERT_EFI_ERROR (Status);
831
832 //
833 // In S3 path, skip shadow logic. no measurement is required
834 //
835 if (BootMode != BOOT_ON_S3_RESUME) {
836 Status = (**PeiServices).RegisterForShadow(FileHandle);
837 if (Status == EFI_ALREADY_STARTED) {
838 mImageInMemory = TRUE;
839 mFileHandle = FileHandle;
840 } else if (Status == EFI_NOT_FOUND) {
841 ASSERT_EFI_ERROR (Status);
842 }
843 }
844
845 if (!mImageInMemory) {
846 //
847 // Initialize TPM device
848 //
849 Status = Tpm2RequestUseTpm ();
850 if (EFI_ERROR (Status)) {
851 DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n"));
852 goto Done;
853 }
854
855 S3ErrorReport = FALSE;
856 if (PcdGet8 (PcdTpm2InitializationPolicy) == 1) {
857 if (BootMode == BOOT_ON_S3_RESUME) {
858 Status = Tpm2Startup (TPM_SU_STATE);
859 if (EFI_ERROR (Status) ) {
860 Status = Tpm2Startup (TPM_SU_CLEAR);
861 if (!EFI_ERROR(Status)) {
862 S3ErrorReport = TRUE;
863 }
864 }
865 } else {
866 Status = Tpm2Startup (TPM_SU_CLEAR);
867 }
868 if (EFI_ERROR (Status) ) {
869 goto Done;
870 }
871 }
872
873 //
874 // Update Tpm2HashMask according to PCR bank.
875 //
876 SetTpm2HashMask ();
877
878 if (S3ErrorReport) {
879 //
880 // The system firmware that resumes from S3 MUST deal with a
881 // TPM2_Startup error appropriately.
882 // For example, issue a TPM2_Startup(TPM_SU_CLEAR) command and
883 // configuring the device securely by taking actions like extending a
884 // separator with an error digest (0x01) into PCRs 0 through 7.
885 //
886 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
887 Status = MeasureSeparatorEventWithError (PcrIndex);
888 if (EFI_ERROR (Status)) {
889 DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n"));
890 }
891 }
892 }
893
894 //
895 // TpmSelfTest is optional on S3 path, skip it to save S3 time
896 //
897 if (BootMode != BOOT_ON_S3_RESUME) {
898 if (PcdGet8 (PcdTpm2SelfTestPolicy) == 1) {
899 Status = Tpm2SelfTest (NO);
900 if (EFI_ERROR (Status)) {
901 goto Done;
902 }
903 }
904 }
905
906 //
907 // Only intall TpmInitializedPpi on success
908 //
909 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
910 ASSERT_EFI_ERROR (Status);
911 }
912
913 if (mImageInMemory) {
914 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
915 return Status;
916 }
917
918 Done:
919 if (EFI_ERROR (Status)) {
920 DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));
921 BuildGuidHob (&gTpmErrorHobGuid,0);
922 REPORT_STATUS_CODE (
923 EFI_ERROR_CODE | EFI_ERROR_MINOR,
924 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
925 );
926 }
927 //
928 // Always intall TpmInitializationDonePpi no matter success or fail.
929 // Other driver can know TPM initialization state by TpmInitializedPpi.
930 //
931 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
932 ASSERT_EFI_ERROR (Status2);
933
934 return Status;
935 }