]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.c
SecurityPkg/TdTcg2Dxe: td-guest shall halt when CcMeasurement install fail
[mirror_edk2.git] / SecurityPkg / Tcg / TdTcg2Dxe / TdTcg2Dxe.c
CommitLineData
57a6ee34
MX
1/** @file\r
2 This module implements EFI TD Protocol.\r
3\r
4 Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include <PiDxe.h>\r
10#include <IndustryStandard/Acpi.h>\r
11#include <IndustryStandard/PeImage.h>\r
12#include <IndustryStandard/TcpaAcpi.h>\r
13\r
14#include <Guid/GlobalVariable.h>\r
15#include <Guid/HobList.h>\r
16#include <Guid/EventGroup.h>\r
17#include <Guid/EventExitBootServiceFailed.h>\r
18#include <Guid/ImageAuthentication.h>\r
19#include <Guid/TpmInstance.h>\r
20\r
21#include <Protocol/DevicePath.h>\r
22#include <Protocol/MpService.h>\r
23#include <Protocol/VariableWrite.h>\r
24#include <Protocol/Tcg2Protocol.h>\r
25#include <Protocol/TrEEProtocol.h>\r
26#include <Protocol/ResetNotification.h>\r
27#include <Protocol/AcpiTable.h>\r
28\r
29#include <Library/DebugLib.h>\r
30#include <Library/BaseMemoryLib.h>\r
31#include <Library/UefiRuntimeServicesTableLib.h>\r
32#include <Library/UefiDriverEntryPoint.h>\r
33#include <Library/HobLib.h>\r
34#include <Library/UefiBootServicesTableLib.h>\r
35#include <Library/BaseLib.h>\r
36#include <Library/MemoryAllocationLib.h>\r
37#include <Library/PrintLib.h>\r
38#include <Library/PcdLib.h>\r
39#include <Library/UefiLib.h>\r
40#include <Library/HashLib.h>\r
41#include <Library/PerformanceLib.h>\r
42#include <Library/ReportStatusCodeLib.h>\r
43#include <Library/TpmMeasurementLib.h>\r
44\r
45#include <Protocol/CcMeasurement.h>\r
46#include <Guid/CcEventHob.h>\r
47#include <Library/TdxLib.h>\r
48\r
49#define PERF_ID_CC_TCG2_DXE 0x3130\r
50\r
51#define CC_EVENT_LOG_AREA_COUNT_MAX 1\r
fb91d6cb
MX
52#define CC_MR_INDEX_0_MRTD 0\r
53#define CC_MR_INDEX_1_RTMR0 1\r
54#define CC_MR_INDEX_2_RTMR1 2\r
55#define CC_MR_INDEX_3_RTMR2 3\r
56#define CC_MR_INDEX_INVALID 4\r
57a6ee34
MX
57\r
58typedef struct {\r
59 CHAR16 *VariableName;\r
60 EFI_GUID *VendorGuid;\r
61} VARIABLE_TYPE;\r
62\r
63typedef struct {\r
64 EFI_GUID *EventGuid;\r
65 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
66} CC_EVENT_INFO_STRUCT;\r
67\r
68typedef struct {\r
69 EFI_CC_EVENT_LOG_FORMAT EventLogFormat;\r
70 EFI_PHYSICAL_ADDRESS Lasa;\r
71 UINT64 Laml;\r
72 UINTN EventLogSize;\r
73 UINT8 *LastEvent;\r
74 BOOLEAN EventLogStarted;\r
75 BOOLEAN EventLogTruncated;\r
76 UINTN Next800155EventOffset;\r
77} CC_EVENT_LOG_AREA_STRUCT;\r
78\r
79typedef struct _TDX_DXE_DATA {\r
80 EFI_CC_BOOT_SERVICE_CAPABILITY BsCap;\r
81 CC_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
82 BOOLEAN GetEventLogCalled[CC_EVENT_LOG_AREA_COUNT_MAX];\r
83 CC_EVENT_LOG_AREA_STRUCT FinalEventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
84 EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable[CC_EVENT_LOG_AREA_COUNT_MAX];\r
85} TDX_DXE_DATA;\r
86\r
87typedef struct {\r
88 TPMI_ALG_HASH HashAlgo;\r
89 UINT16 HashSize;\r
90 UINT32 HashMask;\r
91} TDX_HASH_INFO;\r
92\r
93//\r
94//\r
95CC_EVENT_INFO_STRUCT mCcEventInfo[] = {\r
96 { &gCcEventEntryHobGuid, EFI_CC_EVENT_LOG_FORMAT_TCG_2 },\r
97};\r
98\r
99TDX_DXE_DATA mTdxDxeData = {\r
100 {\r
101 sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY), // Size\r
102 { 1, 1 }, // StructureVersion\r
103 { 1, 1 }, // ProtocolVersion\r
104 EFI_CC_BOOT_HASH_ALG_SHA384, // HashAlgorithmBitmap\r
105 EFI_CC_EVENT_LOG_FORMAT_TCG_2, // SupportedEventLogs\r
106 { 2, 0 } // {CC_TYPE, CC_SUBTYPE}\r
107 },\r
108};\r
109\r
110UINTN mBootAttempts = 0;\r
111CHAR16 mBootVarName[] = L"BootOrder";\r
112\r
113VARIABLE_TYPE mVariableType[] = {\r
114 { EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid },\r
115 { EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid },\r
116 { EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid },\r
117 { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },\r
118 { EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid },\r
119};\r
120\r
121EFI_CC_EVENTLOG_ACPI_TABLE mTdxEventlogAcpiTemplate = {\r
122 {\r
123 EFI_CC_EVENTLOG_ACPI_TABLE_SIGNATURE,\r
124 sizeof (mTdxEventlogAcpiTemplate),\r
125 EFI_CC_EVENTLOG_ACPI_TABLE_REVISION,\r
126 //\r
127 // Compiler initializes the remaining bytes to 0\r
128 // These fields should be filled in production\r
129 //\r
130 },\r
131 { EFI_CC_TYPE_TDX, 0 }, // CcType\r
132 0, // rsvd\r
133 0, // laml\r
134 0, // lasa\r
135};\r
136\r
137//\r
138// Supported Hash list in Td guest.\r
139// Currently SHA384 is supported.\r
140//\r
141TDX_HASH_INFO mHashInfo[] = {\r
142 { TPM_ALG_SHA384, SHA384_DIGEST_SIZE, HASH_ALG_SHA384 }\r
143};\r
144\r
145/**\r
146 Get hash size based on Algo\r
147\r
148 @param[in] HashAlgo Hash Algorithm Id.\r
149\r
150 @return Size of the hash.\r
151**/\r
152UINT16\r
153GetHashSizeFromAlgo (\r
154 IN TPMI_ALG_HASH HashAlgo\r
155 )\r
156{\r
157 UINTN Index;\r
158\r
159 for (Index = 0; Index < sizeof (mHashInfo)/sizeof (mHashInfo[0]); Index++) {\r
160 if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
161 return mHashInfo[Index].HashSize;\r
162 }\r
163 }\r
164\r
165 return 0;\r
166}\r
167\r
168/**\r
169 Get hash mask based on Algo\r
170\r
171 @param[in] HashAlgo Hash Algorithm Id.\r
172\r
173 @return Hash mask.\r
174**/\r
175UINT32\r
176GetHashMaskFromAlgo (\r
177 IN TPMI_ALG_HASH HashAlgo\r
178 )\r
179{\r
180 UINTN Index;\r
181\r
182 for (Index = 0; Index < ARRAY_SIZE (mHashInfo); Index++) {\r
183 if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
184 return mHashInfo[Index].HashMask;\r
185 }\r
186 }\r
187\r
188 ASSERT (FALSE);\r
189 return 0;\r
190}\r
191\r
192/**\r
193 Copy TPML_DIGEST_VALUES into a buffer\r
194\r
195 @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
196 @param[in] DigestList TPML_DIGEST_VALUES to be copied.\r
197 @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
198\r
199 @return The end of buffer to hold TPML_DIGEST_VALUES.\r
200**/\r
201VOID *\r
202CopyDigestListToBuffer (\r
203 IN OUT VOID *Buffer,\r
204 IN TPML_DIGEST_VALUES *DigestList,\r
205 IN UINT32 HashAlgorithmMask\r
206 )\r
207{\r
208 UINTN Index;\r
209 UINT16 DigestSize;\r
210 UINT32 DigestListCount;\r
211 UINT32 *DigestListCountPtr;\r
212\r
213 DigestListCountPtr = (UINT32 *)Buffer;\r
214 DigestListCount = 0;\r
215 Buffer = (UINT8 *)Buffer + sizeof (DigestList->count);\r
216 for (Index = 0; Index < DigestList->count; Index++) {\r
217 if ((DigestList->digests[Index].hashAlg & HashAlgorithmMask) == 0) {\r
218 DEBUG ((DEBUG_ERROR, "WARNING: TD Event log has HashAlg unsupported (0x%x)\n", DigestList->digests[Index].hashAlg));\r
219 continue;\r
220 }\r
221\r
222 CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof (DigestList->digests[Index].hashAlg));\r
223 Buffer = (UINT8 *)Buffer + sizeof (DigestList->digests[Index].hashAlg);\r
224 DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);\r
225 CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);\r
226 Buffer = (UINT8 *)Buffer + DigestSize;\r
227 DigestListCount++;\r
228 }\r
229\r
230 WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
231\r
232 return Buffer;\r
233}\r
234\r
235EFI_HANDLE mImageHandle;\r
236\r
237/**\r
238 Measure PE image into TPM log based on the authenticode image hashing in\r
239 PE/COFF Specification 8.0 Appendix A.\r
240\r
241 Caution: This function may receive untrusted input.\r
242 PE/COFF image is external input, so this function will validate its data structure\r
243 within this image buffer before use.\r
244\r
245 Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
246\r
fb91d6cb 247 @param[in] RtmrIndex RTMR index\r
57a6ee34
MX
248 @param[in] ImageAddress Start address of image buffer.\r
249 @param[in] ImageSize Image size\r
250 @param[out] DigestList Digest list of this image.\r
251\r
252 @retval EFI_SUCCESS Successfully measure image.\r
253 @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
254 @retval other error value\r
255**/\r
256EFI_STATUS\r
257MeasurePeImageAndExtend (\r
fb91d6cb 258 IN UINT32 RtmrIndex,\r
57a6ee34
MX
259 IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
260 IN UINTN ImageSize,\r
261 OUT TPML_DIGEST_VALUES *DigestList\r
262 );\r
263\r
264#define COLUME_SIZE (16 * 2)\r
265\r
266/**\r
267\r
268 This function dump raw data.\r
269\r
270 @param Data raw data\r
271 @param Size raw data size\r
272\r
273**/\r
274VOID\r
275InternalDumpData (\r
276 IN UINT8 *Data,\r
277 IN UINTN Size\r
278 )\r
279{\r
280 UINTN Index;\r
281\r
282 for (Index = 0; Index < Size; Index++) {\r
283 DEBUG ((DEBUG_INFO, Index == COLUME_SIZE/2 ? " | %02x" : " %02x", (UINTN)Data[Index]));\r
284 }\r
285}\r
286\r
287/**\r
288\r
289 This function dump raw data with colume format.\r
290\r
291 @param Data raw data\r
292 @param Size raw data size\r
293\r
294**/\r
295VOID\r
296InternalDumpHex (\r
297 IN UINT8 *Data,\r
298 IN UINTN Size\r
299 )\r
300{\r
301 UINTN Index;\r
302 UINTN Count;\r
303 UINTN Left;\r
304\r
305 Count = Size / COLUME_SIZE;\r
306 Left = Size % COLUME_SIZE;\r
307 for (Index = 0; Index < Count; Index++) {\r
308 DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
309 InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
310 DEBUG ((DEBUG_INFO, "\n"));\r
311 }\r
312\r
313 if (Left != 0) {\r
314 DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
315 InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
316 DEBUG ((DEBUG_INFO, "\n"));\r
317 }\r
318}\r
319\r
320/**\r
321\r
322 This function initialize TD_EVENT_HDR for EV_NO_ACTION\r
323 Event Type other than EFI Specification ID event. The behavior is defined\r
324 by TCG PC Client PFP Spec. Section 9.3.4 EV_NO_ACTION Event Types\r
325\r
326 @param[in, out] NoActionEvent Event Header of EV_NO_ACTION Event\r
327 @param[in] EventSize Event Size of the EV_NO_ACTION Event\r
328\r
329**/\r
330VOID\r
331InitNoActionEvent (\r
332 IN OUT CC_EVENT_HDR *NoActionEvent,\r
333 IN UINT32 EventSize\r
334 )\r
335{\r
336 UINT32 DigestListCount;\r
337 TPMI_ALG_HASH HashAlgId;\r
338 UINT8 *DigestBuffer;\r
339\r
340 DigestBuffer = (UINT8 *)NoActionEvent->Digests.digests;\r
341 DigestListCount = 0;\r
342\r
343 NoActionEvent->MrIndex = 0;\r
344 NoActionEvent->EventType = EV_NO_ACTION;\r
345\r
346 //\r
347 // Set Hash count & hashAlg accordingly, while Digest.digests[n].digest to all 0\r
348 //\r
349 ZeroMem (&NoActionEvent->Digests, sizeof (NoActionEvent->Digests));\r
350\r
351 if ((mTdxDxeData.BsCap.HashAlgorithmBitmap & EFI_CC_BOOT_HASH_ALG_SHA384) != 0) {\r
352 HashAlgId = TPM_ALG_SHA384;\r
353 CopyMem (DigestBuffer, &HashAlgId, sizeof (TPMI_ALG_HASH));\r
354 DigestBuffer += sizeof (TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId);\r
355 DigestListCount++;\r
356 }\r
357\r
358 //\r
359 // Set Digests Count\r
360 //\r
361 WriteUnaligned32 ((UINT32 *)&NoActionEvent->Digests.count, DigestListCount);\r
362\r
363 //\r
364 // Set Event Size\r
365 //\r
366 WriteUnaligned32 ((UINT32 *)DigestBuffer, EventSize);\r
367}\r
368\r
369/**\r
370 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function\r
371 Caller is responsible to free LocationBuf.\r
372\r
373 @param[out] LocationBuf Returns Processor Location Buffer.\r
374 @param[out] Num Returns processor number.\r
375\r
376 @retval EFI_SUCCESS Operation completed successfully.\r
377 @retval EFI_UNSUPPORTED MpService protocol not found.\r
378\r
379**/\r
380EFI_STATUS\r
381GetProcessorsCpuLocation (\r
382 OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf,\r
383 OUT UINTN *Num\r
384 )\r
385{\r
386 EFI_STATUS Status;\r
387 EFI_MP_SERVICES_PROTOCOL *MpProtocol;\r
388 UINTN ProcessorNum;\r
389 UINTN EnabledProcessorNum;\r
390 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
391 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
392 UINTN Index;\r
393\r
394 Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpProtocol);\r
395 if (EFI_ERROR (Status)) {\r
396 //\r
397 // MP protocol is not installed\r
398 //\r
399 return EFI_UNSUPPORTED;\r
400 }\r
401\r
402 Status = MpProtocol->GetNumberOfProcessors (\r
403 MpProtocol,\r
404 &ProcessorNum,\r
405 &EnabledProcessorNum\r
406 );\r
407 if (EFI_ERROR (Status)) {\r
408 return Status;\r
409 }\r
410\r
411 Status = gBS->AllocatePool (\r
412 EfiBootServicesData,\r
413 sizeof (EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
414 (VOID **)&ProcessorLocBuf\r
415 );\r
416 if (EFI_ERROR (Status)) {\r
417 return Status;\r
418 }\r
419\r
420 //\r
421 // Get each processor Location info\r
422 //\r
423 for (Index = 0; Index < ProcessorNum; Index++) {\r
424 Status = MpProtocol->GetProcessorInfo (\r
425 MpProtocol,\r
426 Index,\r
427 &ProcessorInfo\r
428 );\r
429 if (EFI_ERROR (Status)) {\r
430 FreePool (ProcessorLocBuf);\r
431 return Status;\r
432 }\r
433\r
434 //\r
435 // Get all Processor Location info & measure\r
436 //\r
437 CopyMem (\r
438 &ProcessorLocBuf[Index],\r
439 &ProcessorInfo.Location,\r
440 sizeof (EFI_CPU_PHYSICAL_LOCATION)\r
441 );\r
442 }\r
443\r
444 *LocationBuf = ProcessorLocBuf;\r
445 *Num = ProcessorNum;\r
446\r
447 return Status;\r
448}\r
449\r
450/**\r
451 The EFI_CC_MEASUREMENT_PROTOCOL GetCapability function call provides protocol\r
452 capability information and state information.\r
453\r
454 @param[in] This Indicates the calling context\r
455 @param[in, out] ProtocolCapability The caller allocates memory for a EFI_CC_BOOT_SERVICE_CAPABILITY\r
456 structure and sets the size field to the size of the structure allocated.\r
457 The callee fills in the fields with the EFI protocol capability information\r
458 and the current EFI TCG2 state information up to the number of fields which\r
459 fit within the size of the structure passed in.\r
460\r
461 @retval EFI_SUCCESS Operation completed successfully.\r
462 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
463 The ProtocolCapability variable will not be populated.\r
464 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
465 The ProtocolCapability variable will not be populated.\r
466 @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response.\r
467 It will be partially populated (required Size field will be set).\r
468**/\r
469EFI_STATUS\r
470EFIAPI\r
471TdGetCapability (\r
472 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
473 IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
474 )\r
475{\r
476 DEBUG ((DEBUG_VERBOSE, "TdGetCapability\n"));\r
477\r
478 if ((This == NULL) || (ProtocolCapability == NULL)) {\r
479 return EFI_INVALID_PARAMETER;\r
480 }\r
481\r
482 CopyMem (ProtocolCapability, &mTdxDxeData.BsCap, sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY));\r
483\r
484 return EFI_SUCCESS;\r
485}\r
486\r
487/**\r
488 This function dump PCR event.\r
489 TD Event log reuse the TCG PCR Event spec.\r
490 The first event in the event log is the SHA1 log format.\r
491 There is only ONE TCG_PCR_EVENT in TD Event log.\r
492\r
493 @param[in] EventHdr TCG PCR event structure.\r
494**/\r
495VOID\r
496DumpPcrEvent (\r
497 IN TCG_PCR_EVENT_HDR *EventHdr\r
498 )\r
499{\r
500 UINTN Index;\r
501\r
502 DEBUG ((DEBUG_INFO, " Event:\n"));\r
503 DEBUG ((DEBUG_INFO, " MrIndex - %d\n", EventHdr->PCRIndex));\r
504 DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", EventHdr->EventType));\r
505 DEBUG ((DEBUG_INFO, " Digest - "));\r
506 for (Index = 0; Index < sizeof (TCG_DIGEST); Index++) {\r
507 DEBUG ((DEBUG_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
508 }\r
509\r
510 DEBUG ((DEBUG_INFO, "\n"));\r
511 DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize));\r
512 InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
513}\r
514\r
515/**\r
516 This function dump TCG_EfiSpecIDEventStruct.\r
517\r
518 @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
519**/\r
520VOID\r
521DumpTcgEfiSpecIdEventStruct (\r
522 IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
523 )\r
524{\r
525 TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
526 UINTN Index;\r
527 UINT8 *VendorInfoSize;\r
528 UINT8 *VendorInfo;\r
529 UINT32 NumberOfAlgorithms;\r
530\r
531 DEBUG ((DEBUG_INFO, " TCG_EfiSpecIDEventStruct:\n"));\r
532 DEBUG ((DEBUG_INFO, " signature - '"));\r
533 for (Index = 0; Index < sizeof (TcgEfiSpecIdEventStruct->signature); Index++) {\r
534 DEBUG ((DEBUG_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index]));\r
535 }\r
536\r
537 DEBUG ((DEBUG_INFO, "'\n"));\r
538 DEBUG ((DEBUG_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass));\r
539 DEBUG ((DEBUG_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata));\r
540 DEBUG ((DEBUG_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize));\r
541\r
542 CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
543 DEBUG ((DEBUG_INFO, " NumberOfAlgorithms - 0x%08x\n", NumberOfAlgorithms));\r
544\r
545 DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
546 for (Index = 0; Index < NumberOfAlgorithms; Index++) {\r
547 DEBUG ((DEBUG_INFO, " digest(%d)\n", Index));\r
548 DEBUG ((DEBUG_INFO, " algorithmId - 0x%04x\n", DigestSize[Index].algorithmId));\r
549 DEBUG ((DEBUG_INFO, " digestSize - 0x%04x\n", DigestSize[Index].digestSize));\r
550 }\r
551\r
552 VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
553 DEBUG ((DEBUG_INFO, " VendorInfoSize - 0x%02x\n", *VendorInfoSize));\r
554 VendorInfo = VendorInfoSize + 1;\r
555 DEBUG ((DEBUG_INFO, " VendorInfo - "));\r
556 for (Index = 0; Index < *VendorInfoSize; Index++) {\r
557 DEBUG ((DEBUG_INFO, "%02x ", VendorInfo[Index]));\r
558 }\r
559\r
560 DEBUG ((DEBUG_INFO, "\n"));\r
561}\r
562\r
563/**\r
564 This function get size of TCG_EfiSpecIDEventStruct.\r
565\r
566 @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
567**/\r
568UINTN\r
569GetTcgEfiSpecIdEventStructSize (\r
570 IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
571 )\r
572{\r
573 TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
574 UINT8 *VendorInfoSize;\r
575 UINT32 NumberOfAlgorithms;\r
576\r
577 CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
578\r
579 DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
580 VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
581 return sizeof (TCG_EfiSpecIDEventStruct) + sizeof (UINT32) + (NumberOfAlgorithms * sizeof (TCG_EfiSpecIdEventAlgorithmSize)) + sizeof (UINT8) + (*VendorInfoSize);\r
582}\r
583\r
584/**\r
585 This function dump TD Event (including the Digests).\r
586\r
587 @param[in] CcEvent TD Event structure.\r
588**/\r
589VOID\r
590DumpCcEvent (\r
591 IN CC_EVENT *CcEvent\r
592 )\r
593{\r
594 UINT32 DigestIndex;\r
595 UINT32 DigestCount;\r
596 TPMI_ALG_HASH HashAlgo;\r
597 UINT32 DigestSize;\r
598 UINT8 *DigestBuffer;\r
599 UINT32 EventSize;\r
600 UINT8 *EventBuffer;\r
601\r
602 DEBUG ((DEBUG_INFO, "Cc Event:\n"));\r
603 DEBUG ((DEBUG_INFO, " MrIndex - %d\n", CcEvent->MrIndex));\r
604 DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", CcEvent->EventType));\r
605 DEBUG ((DEBUG_INFO, " DigestCount: 0x%08x\n", CcEvent->Digests.count));\r
606\r
607 DigestCount = CcEvent->Digests.count;\r
608 HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
609 DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
610 for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
611 DEBUG ((DEBUG_INFO, " HashAlgo : 0x%04x\n", HashAlgo));\r
612 DEBUG ((DEBUG_INFO, " Digest(%d): \n", DigestIndex));\r
613 DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
614 InternalDumpHex (DigestBuffer, DigestSize);\r
615 //\r
616 // Prepare next\r
617 //\r
618 CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
619 DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
620 }\r
621\r
622 DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
623\r
624 CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
625 DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventSize));\r
626 EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
627 InternalDumpHex (EventBuffer, EventSize);\r
628 DEBUG ((DEBUG_INFO, "\n"));\r
629}\r
630\r
631/**\r
632 This function returns size of Td Table event.\r
633\r
634 @param[in] CcEvent Td Table event structure.\r
635\r
636 @return size of Td event.\r
637**/\r
638UINTN\r
639GetCcEventSize (\r
640 IN CC_EVENT *CcEvent\r
641 )\r
642{\r
643 UINT32 DigestIndex;\r
644 UINT32 DigestCount;\r
645 TPMI_ALG_HASH HashAlgo;\r
646 UINT32 DigestSize;\r
647 UINT8 *DigestBuffer;\r
648 UINT32 EventSize;\r
649 UINT8 *EventBuffer;\r
650\r
651 DigestCount = CcEvent->Digests.count;\r
652 HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
653 DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
654 for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
655 DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
656 //\r
657 // Prepare next\r
658 //\r
659 CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
660 DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
661 }\r
662\r
663 DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
664\r
665 CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
666 EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
667\r
668 return (UINTN)EventBuffer + EventSize - (UINTN)CcEvent;\r
669}\r
670\r
671/**\r
672 This function dump CC event log.\r
673 TDVF only supports EFI_CC_EVENT_LOG_FORMAT_TCG_2\r
674\r
675 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
676 @param[in] EventLogLocation A pointer to the memory address of the event log.\r
677 @param[in] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
678 address of the start of the last entry in the event log in memory.\r
679 @param[in] FinalEventsTable A pointer to the memory address of the final event table.\r
680**/\r
681VOID\r
682DumpCcEventLog (\r
683 IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
684 IN EFI_PHYSICAL_ADDRESS EventLogLocation,\r
685 IN EFI_PHYSICAL_ADDRESS EventLogLastEntry,\r
686 IN EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable\r
687 )\r
688{\r
689 TCG_PCR_EVENT_HDR *EventHdr;\r
690 CC_EVENT *CcEvent;\r
691 TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
692 UINTN NumberOfEvents;\r
693\r
694 DEBUG ((DEBUG_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
695 ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
696\r
697 //\r
698 // Dump first event.\r
699 // The first event is always the TCG_PCR_EVENT_HDR\r
700 // After this event is a TCG_EfiSpecIDEventStruct\r
701 //\r
702 EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
703 DumpPcrEvent (EventHdr);\r
704\r
705 TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)(EventHdr + 1);\r
706 DumpTcgEfiSpecIdEventStruct (TcgEfiSpecIdEventStruct);\r
707\r
708 //\r
709 // Then the CcEvent (Its structure is similar to TCG_PCR_EVENT2)\r
710 //\r
711 CcEvent = (CC_EVENT *)((UINTN)TcgEfiSpecIdEventStruct + GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct));\r
712 while ((UINTN)CcEvent <= EventLogLastEntry) {\r
713 DumpCcEvent (CcEvent);\r
714 CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
715 }\r
716\r
717 if (FinalEventsTable == NULL) {\r
718 DEBUG ((DEBUG_INFO, "FinalEventsTable: NOT FOUND\n"));\r
719 } else {\r
720 DEBUG ((DEBUG_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable));\r
721 DEBUG ((DEBUG_INFO, " Version: (0x%x)\n", FinalEventsTable->Version));\r
722 DEBUG ((DEBUG_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents));\r
723\r
724 CcEvent = (CC_EVENT *)(UINTN)(FinalEventsTable + 1);\r
725 for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) {\r
726 DumpCcEvent (CcEvent);\r
727 CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
728 }\r
729 }\r
730\r
731 return;\r
732}\r
733\r
734/**\r
735 The EFI_CC_MEASUREMENT_PROTOCOL Get Event Log function call allows a caller to\r
736 retrieve the address of a given event log and its last entry.\r
737\r
738 @param[in] This Indicates the calling context\r
739 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
740 @param[out] EventLogLocation A pointer to the memory address of the event log.\r
741 @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
742 address of the start of the last entry in the event log in memory.\r
743 @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would\r
744 have exceeded the area allocated for events, this value is set to TRUE.\r
745 Otherwise, the value will be FALSE and the Event Log will be complete.\r
746\r
747 @retval EFI_SUCCESS Operation completed successfully.\r
748 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect\r
749 (e.g. asking for an event log whose format is not supported).\r
750**/\r
751EFI_STATUS\r
752EFIAPI\r
753TdGetEventLog (\r
754 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
755 IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
756 OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,\r
757 OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,\r
758 OUT BOOLEAN *EventLogTruncated\r
759 )\r
760{\r
761 UINTN Index = 0;\r
762\r
763 DEBUG ((DEBUG_INFO, "TdGetEventLog ... (0x%x)\n", EventLogFormat));\r
764 ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
765\r
766 if (EventLogLocation != NULL) {\r
767 *EventLogLocation = mTdxDxeData.EventLogAreaStruct[Index].Lasa;\r
768 DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
769 }\r
770\r
771 if (EventLogLastEntry != NULL) {\r
772 if (!mTdxDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
773 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
774 } else {\r
775 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTdxDxeData.EventLogAreaStruct[Index].LastEvent;\r
776 }\r
777\r
778 DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
779 }\r
780\r
781 if (EventLogTruncated != NULL) {\r
782 *EventLogTruncated = mTdxDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
783 DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
784 }\r
785\r
786 DEBUG ((DEBUG_INFO, "TdGetEventLog - %r\n", EFI_SUCCESS));\r
787\r
788 // Dump Event Log for debug purpose\r
789 if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
790 DumpCcEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry, mTdxDxeData.FinalEventsTable[Index]);\r
791 }\r
792\r
793 //\r
794 // All events generated after the invocation of EFI_TCG2_GET_EVENT_LOG SHALL be stored\r
795 // in an instance of an EFI_CONFIGURATION_TABLE named by the VendorGuid of EFI_TCG2_FINAL_EVENTS_TABLE_GUID.\r
796 //\r
797 mTdxDxeData.GetEventLogCalled[Index] = TRUE;\r
798\r
799 return EFI_SUCCESS;\r
800}\r
801\r
802/**\r
803 Return if this is a Tcg800155PlatformIdEvent.\r
804\r
805 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.\r
806 @param[in] NewEventHdrSize New event header size.\r
807 @param[in] NewEventData Pointer to the new event data.\r
808 @param[in] NewEventSize New event data size.\r
809\r
810 @retval TRUE This is a Tcg800155PlatformIdEvent.\r
811 @retval FALSE This is NOT a Tcg800155PlatformIdEvent.\r
812\r
813**/\r
814BOOLEAN\r
815Is800155Event (\r
816 IN VOID *NewEventHdr,\r
817 IN UINT32 NewEventHdrSize,\r
818 IN UINT8 *NewEventData,\r
819 IN UINT32 NewEventSize\r
820 )\r
821{\r
822 if ((((TCG_PCR_EVENT2_HDR *)NewEventHdr)->EventType == EV_NO_ACTION) &&\r
823 (NewEventSize >= sizeof (TCG_Sp800_155_PlatformId_Event2)) &&\r
824 (CompareMem (\r
825 NewEventData,\r
826 TCG_Sp800_155_PlatformId_Event2_SIGNATURE,\r
827 sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1\r
828 ) == 0))\r
829 {\r
830 return TRUE;\r
831 }\r
832\r
833 return FALSE;\r
834}\r
835\r
836/**\r
837 Add a new entry to the Event Log.\r
838\r
839 @param[in, out] EventLogAreaStruct The event log area data structure\r
840 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.\r
841 @param[in] NewEventHdrSize New event header size.\r
842 @param[in] NewEventData Pointer to the new event data.\r
843 @param[in] NewEventSize New event data size.\r
844\r
845 @retval EFI_SUCCESS The new event log entry was added.\r
846 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
847\r
848**/\r
849EFI_STATUS\r
850TcgCommLogEvent (\r
851 IN OUT CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct,\r
852 IN VOID *NewEventHdr,\r
853 IN UINT32 NewEventHdrSize,\r
854 IN UINT8 *NewEventData,\r
855 IN UINT32 NewEventSize\r
856 )\r
857{\r
858 UINTN NewLogSize;\r
859 BOOLEAN Record800155Event;\r
860 CC_EVENT_HDR *CcEventHdr;\r
861\r
862 CcEventHdr = (CC_EVENT_HDR *)NewEventHdr;\r
863 DEBUG ((DEBUG_VERBOSE, "Td: Try to log event. Index = %d, EventType = 0x%x\n", CcEventHdr->MrIndex, CcEventHdr->EventType));\r
864\r
865 if (NewEventSize > MAX_ADDRESS - NewEventHdrSize) {\r
866 return EFI_OUT_OF_RESOURCES;\r
867 }\r
868\r
869 NewLogSize = NewEventHdrSize + NewEventSize;\r
870\r
871 if (NewLogSize > MAX_ADDRESS - EventLogAreaStruct->EventLogSize) {\r
872 return EFI_OUT_OF_RESOURCES;\r
873 }\r
874\r
875 if (NewLogSize + EventLogAreaStruct->EventLogSize > EventLogAreaStruct->Laml) {\r
876 DEBUG ((DEBUG_INFO, " Laml - 0x%x\n", EventLogAreaStruct->Laml));\r
877 DEBUG ((DEBUG_INFO, " NewLogSize - 0x%x\n", NewLogSize));\r
878 DEBUG ((DEBUG_INFO, " LogSize - 0x%x\n", EventLogAreaStruct->EventLogSize));\r
879 DEBUG ((DEBUG_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
880 return EFI_OUT_OF_RESOURCES;\r
881 }\r
882\r
883 //\r
884 // Check 800-155 event\r
885 // Record to 800-155 event offset only.\r
886 // If the offset is 0, no need to record.\r
887 //\r
888 Record800155Event = Is800155Event (NewEventHdr, NewEventHdrSize, NewEventData, NewEventSize);\r
889 if (Record800155Event) {\r
890 DEBUG ((DEBUG_INFO, "It is 800155Event.\n"));\r
891\r
892 if (EventLogAreaStruct->Next800155EventOffset != 0) {\r
893 CopyMem (\r
894 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewLogSize,\r
895 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
896 EventLogAreaStruct->EventLogSize - EventLogAreaStruct->Next800155EventOffset\r
897 );\r
898\r
899 CopyMem (\r
900 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
901 NewEventHdr,\r
902 NewEventHdrSize\r
903 );\r
904 CopyMem (\r
905 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewEventHdrSize,\r
906 NewEventData,\r
907 NewEventSize\r
908 );\r
909\r
910 EventLogAreaStruct->Next800155EventOffset += NewLogSize;\r
911 EventLogAreaStruct->LastEvent += NewLogSize;\r
912 EventLogAreaStruct->EventLogSize += NewLogSize;\r
913 }\r
914\r
915 return EFI_SUCCESS;\r
916 }\r
917\r
918 EventLogAreaStruct->LastEvent = (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->EventLogSize;\r
919 EventLogAreaStruct->EventLogSize += NewLogSize;\r
920\r
921 CopyMem (EventLogAreaStruct->LastEvent, NewEventHdr, NewEventHdrSize);\r
922 CopyMem (\r
923 EventLogAreaStruct->LastEvent + NewEventHdrSize,\r
924 NewEventData,\r
925 NewEventSize\r
926 );\r
927\r
928 return EFI_SUCCESS;\r
929}\r
930\r
931/**\r
fb91d6cb
MX
932 According to UEFI Spec 2.10 Section 38.4.1:\r
933 The following table shows the TPM PCR index mapping and CC event log measurement\r
934 register index interpretation for Intel TDX, where MRTD means Trust Domain Measurement\r
935 Register and RTMR means Runtime Measurement Register\r
936\r
937 // TPM PCR Index | CC Measurement Register Index | TDX-measurement register\r
938 // ------------------------------------------------------------------------\r
939 // 0 | 0 | MRTD\r
940 // 1, 7 | 1 | RTMR[0]\r
941 // 2~6 | 2 | RTMR[1]\r
942 // 8~15 | 3 | RTMR[2]\r
943\r
944 @param[in] PCRIndex Index of the TPM PCR\r
945\r
946 @retval UINT32 Index of the CC Event Log Measurement Register Index\r
947 @retval CC_MR_INDEX_INVALID Invalid MR Index\r
57a6ee34
MX
948**/\r
949UINT32\r
950EFIAPI\r
951MapPcrToMrIndex (\r
952 IN UINT32 PCRIndex\r
953 )\r
954{\r
955 UINT32 MrIndex;\r
956\r
fb91d6cb 957 if (PCRIndex > 15) {\r
57a6ee34 958 ASSERT (FALSE);\r
fb91d6cb 959 return CC_MR_INDEX_INVALID;\r
57a6ee34
MX
960 }\r
961\r
962 MrIndex = 0;\r
fb91d6cb
MX
963 if (PCRIndex == 0) {\r
964 MrIndex = CC_MR_INDEX_0_MRTD;\r
965 } else if ((PCRIndex == 1) || (PCRIndex == 7)) {\r
966 MrIndex = CC_MR_INDEX_1_RTMR0;\r
967 } else if ((PCRIndex >= 2) && (PCRIndex <= 6)) {\r
968 MrIndex = CC_MR_INDEX_2_RTMR1;\r
969 } else if ((PCRIndex >= 8) && (PCRIndex <= 15)) {\r
970 MrIndex = CC_MR_INDEX_3_RTMR2;\r
57a6ee34
MX
971 }\r
972\r
973 return MrIndex;\r
974}\r
975\r
976EFI_STATUS\r
977EFIAPI\r
978TdMapPcrToMrIndex (\r
979 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
980 IN UINT32 PCRIndex,\r
981 OUT UINT32 *MrIndex\r
982 )\r
983{\r
984 if (MrIndex == NULL) {\r
985 return EFI_INVALID_PARAMETER;\r
986 }\r
987\r
57a6ee34
MX
988 *MrIndex = MapPcrToMrIndex (PCRIndex);\r
989\r
fb91d6cb 990 return *MrIndex == CC_MR_INDEX_INVALID ? EFI_INVALID_PARAMETER : EFI_SUCCESS;\r
57a6ee34
MX
991}\r
992\r
993/**\r
994 Add a new entry to the Event Log.\r
995\r
996 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
997 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.\r
998 @param[in] NewEventHdrSize New event header size.\r
999 @param[in] NewEventData Pointer to the new event data.\r
1000 @param[in] NewEventSize New event data size.\r
1001\r
1002 @retval EFI_SUCCESS The new event log entry was added.\r
1003 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
1004\r
1005**/\r
1006EFI_STATUS\r
1007TdxDxeLogEvent (\r
1008 IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
1009 IN VOID *NewEventHdr,\r
1010 IN UINT32 NewEventHdrSize,\r
1011 IN UINT8 *NewEventData,\r
1012 IN UINT32 NewEventSize\r
1013 )\r
1014{\r
1015 EFI_STATUS Status;\r
1016 UINTN Index;\r
1017 CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct;\r
1018\r
1019 if (EventLogFormat != EFI_CC_EVENT_LOG_FORMAT_TCG_2) {\r
1020 ASSERT (FALSE);\r
1021 return EFI_INVALID_PARAMETER;\r
1022 }\r
1023\r
1024 Index = 0;\r
1025\r
1026 //\r
1027 // Record to normal event log\r
1028 //\r
1029 EventLogAreaStruct = &mTdxDxeData.EventLogAreaStruct[Index];\r
1030\r
1031 if (EventLogAreaStruct->EventLogTruncated) {\r
1032 return EFI_VOLUME_FULL;\r
1033 }\r
1034\r
1035 Status = TcgCommLogEvent (\r
1036 EventLogAreaStruct,\r
1037 NewEventHdr,\r
1038 NewEventHdrSize,\r
1039 NewEventData,\r
1040 NewEventSize\r
1041 );\r
1042\r
1043 if (Status == EFI_OUT_OF_RESOURCES) {\r
1044 EventLogAreaStruct->EventLogTruncated = TRUE;\r
1045 return EFI_VOLUME_FULL;\r
1046 } else if (Status == EFI_SUCCESS) {\r
1047 EventLogAreaStruct->EventLogStarted = TRUE;\r
1048 }\r
1049\r
1050 //\r
1051 // If GetEventLog is called, record to FinalEventsTable, too.\r
1052 //\r
1053 if (mTdxDxeData.GetEventLogCalled[Index]) {\r
1054 if (mTdxDxeData.FinalEventsTable[Index] == NULL) {\r
1055 //\r
1056 // no need for FinalEventsTable\r
1057 //\r
1058 return EFI_SUCCESS;\r
1059 }\r
1060\r
1061 EventLogAreaStruct = &mTdxDxeData.FinalEventLogAreaStruct[Index];\r
1062\r
1063 if (EventLogAreaStruct->EventLogTruncated) {\r
1064 return EFI_VOLUME_FULL;\r
1065 }\r
1066\r
1067 Status = TcgCommLogEvent (\r
1068 EventLogAreaStruct,\r
1069 NewEventHdr,\r
1070 NewEventHdrSize,\r
1071 NewEventData,\r
1072 NewEventSize\r
1073 );\r
1074 if (Status == EFI_OUT_OF_RESOURCES) {\r
1075 EventLogAreaStruct->EventLogTruncated = TRUE;\r
1076 return EFI_VOLUME_FULL;\r
1077 } else if (Status == EFI_SUCCESS) {\r
1078 EventLogAreaStruct->EventLogStarted = TRUE;\r
1079 //\r
1080 // Increase the NumberOfEvents in FinalEventsTable\r
1081 //\r
1082 (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents++;\r
1083 DEBUG ((DEBUG_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents));\r
1084 DEBUG ((DEBUG_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize));\r
1085 }\r
1086 }\r
1087\r
1088 return Status;\r
1089}\r
1090\r
1091/**\r
1092 Get TPML_DIGEST_VALUES compact binary buffer size.\r
1093\r
1094 @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
1095\r
1096 @return TPML_DIGEST_VALUES compact binary buffer size.\r
1097**/\r
1098UINT32\r
1099GetDigestListBinSize (\r
1100 IN VOID *DigestListBin\r
1101 )\r
1102{\r
1103 UINTN Index;\r
1104 UINT16 DigestSize;\r
1105 UINT32 TotalSize;\r
1106 UINT32 Count;\r
1107 TPMI_ALG_HASH HashAlg;\r
1108\r
1109 Count = ReadUnaligned32 (DigestListBin);\r
1110 TotalSize = sizeof (Count);\r
1111 DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
1112 for (Index = 0; Index < Count; Index++) {\r
1113 HashAlg = ReadUnaligned16 (DigestListBin);\r
1114 TotalSize += sizeof (HashAlg);\r
1115 DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
1116\r
1117 DigestSize = GetHashSizeFromAlgo (HashAlg);\r
1118 TotalSize += DigestSize;\r
1119 DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
1120 }\r
1121\r
1122 return TotalSize;\r
1123}\r
1124\r
1125/**\r
1126 Copy TPML_DIGEST_VALUES compact binary into a buffer\r
1127\r
1128 @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
1129 @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
1130 @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
1131 @param[out] HashAlgorithmMaskCopied Pointer to HASH bits corresponding to the digests copied.\r
1132\r
1133 @return The end of buffer to hold TPML_DIGEST_VALUES compact binary.\r
1134**/\r
1135VOID *\r
1136CopyDigestListBinToBuffer (\r
1137 IN OUT VOID *Buffer,\r
1138 IN VOID *DigestListBin,\r
1139 IN UINT32 HashAlgorithmMask,\r
1140 OUT UINT32 *HashAlgorithmMaskCopied\r
1141 )\r
1142{\r
1143 UINTN Index;\r
1144 UINT16 DigestSize;\r
1145 UINT32 Count;\r
1146 TPMI_ALG_HASH HashAlg;\r
1147 UINT32 DigestListCount;\r
1148 UINT32 *DigestListCountPtr;\r
1149\r
1150 DigestListCountPtr = (UINT32 *)Buffer;\r
1151 DigestListCount = 0;\r
1152 *HashAlgorithmMaskCopied = 0;\r
1153\r
1154 Count = ReadUnaligned32 (DigestListBin);\r
1155 Buffer = (UINT8 *)Buffer + sizeof (Count);\r
1156 DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
1157 for (Index = 0; Index < Count; Index++) {\r
1158 HashAlg = ReadUnaligned16 (DigestListBin);\r
1159 DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
1160 DigestSize = GetHashSizeFromAlgo (HashAlg);\r
1161\r
1162 if ((HashAlg & HashAlgorithmMask) != 0) {\r
1163 CopyMem (Buffer, &HashAlg, sizeof (HashAlg));\r
1164 Buffer = (UINT8 *)Buffer + sizeof (HashAlg);\r
1165 CopyMem (Buffer, DigestListBin, DigestSize);\r
1166 Buffer = (UINT8 *)Buffer + DigestSize;\r
1167 DigestListCount++;\r
1168 (*HashAlgorithmMaskCopied) |= GetHashMaskFromAlgo (HashAlg);\r
1169 } else {\r
1170 DEBUG ((DEBUG_ERROR, "WARNING: CopyDigestListBinToBuffer Event log has HashAlg unsupported by PCR bank (0x%x)\n", HashAlg));\r
1171 }\r
1172\r
1173 DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
1174 }\r
1175\r
1176 WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
1177\r
1178 return Buffer;\r
1179}\r
1180\r
1181/**\r
1182 Add a new entry to the Event Log. The call chain is like below:\r
1183 TdxDxeLogHashEvent -> TdxDxeLogEvent -> TcgCommonLogEvent\r
1184\r
1185 Before this function is called, the event information (including the digest)\r
1186 is ready.\r
1187\r
1188 @param[in] DigestList A list of digest.\r
1189 @param[in,out] NewEventHdr Pointer to a TD_EVENT_HDR data structure.\r
1190 @param[in] NewEventData Pointer to the new event data.\r
1191\r
1192 @retval EFI_SUCCESS The new event log entry was added.\r
1193 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
1194**/\r
1195EFI_STATUS\r
1196TdxDxeLogHashEvent (\r
1197 IN TPML_DIGEST_VALUES *DigestList,\r
1198 IN OUT CC_EVENT_HDR *NewEventHdr,\r
1199 IN UINT8 *NewEventData\r
1200 )\r
1201{\r
1202 EFI_STATUS Status;\r
1203 EFI_TPL OldTpl;\r
1204 EFI_STATUS RetStatus;\r
1205 CC_EVENT CcEvent;\r
1206 UINT8 *DigestBuffer;\r
1207 UINT32 *EventSizePtr;\r
1208 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
1209\r
1210 RetStatus = EFI_SUCCESS;\r
1211 LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
1212\r
1213 ZeroMem (&CcEvent, sizeof (CcEvent));\r
fb91d6cb 1214 CcEvent.MrIndex = NewEventHdr->MrIndex;\r
57a6ee34
MX
1215 CcEvent.EventType = NewEventHdr->EventType;\r
1216 DigestBuffer = (UINT8 *)&CcEvent.Digests;\r
1217 EventSizePtr = CopyDigestListToBuffer (DigestBuffer, DigestList, HASH_ALG_SHA384);\r
1218 CopyMem (EventSizePtr, &NewEventHdr->EventSize, sizeof (NewEventHdr->EventSize));\r
1219\r
1220 //\r
1221 // Enter critical region\r
1222 //\r
1223 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
1224 Status = TdxDxeLogEvent (\r
1225 LogFormat,\r
1226 &CcEvent,\r
1227 sizeof (CcEvent.MrIndex) + sizeof (CcEvent.EventType) + GetDigestListBinSize (DigestBuffer) + sizeof (CcEvent.EventSize),\r
1228 NewEventData,\r
1229 NewEventHdr->EventSize\r
1230 );\r
1231 if (Status != EFI_SUCCESS) {\r
1232 RetStatus = Status;\r
1233 }\r
1234\r
1235 gBS->RestoreTPL (OldTpl);\r
1236\r
1237 return RetStatus;\r
1238}\r
1239\r
1240/**\r
1241 Do a hash operation on a data buffer, extend a specific RTMR with the hash result,\r
1242 and add an entry to the Event Log.\r
1243\r
1244 @param[in] Flags Bitmap providing additional information.\r
1245 @param[in] HashData Physical address of the start of the data buffer\r
1246 to be hashed, extended, and logged.\r
1247 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
1248 @param[in, out] NewEventHdr Pointer to a TD_EVENT_HDR data structure.\r
1249 @param[in] NewEventData Pointer to the new event data.\r
1250\r
1251 @retval EFI_SUCCESS Operation completed successfully.\r
1252 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
1253 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
1254\r
1255**/\r
1256EFI_STATUS\r
1257TdxDxeHashLogExtendEvent (\r
1258 IN UINT64 Flags,\r
1259 IN UINT8 *HashData,\r
1260 IN UINT64 HashDataLen,\r
1261 IN OUT CC_EVENT_HDR *NewEventHdr,\r
1262 IN UINT8 *NewEventData\r
1263 )\r
1264{\r
1265 EFI_STATUS Status;\r
1266 TPML_DIGEST_VALUES DigestList;\r
1267 CC_EVENT_HDR NoActionEvent;\r
1268\r
1269 if (NewEventHdr->EventType == EV_NO_ACTION) {\r
1270 //\r
1271 // Do not do RTMR extend for EV_NO_ACTION\r
1272 //\r
1273 Status = EFI_SUCCESS;\r
1274 InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize);\r
1275 if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
1276 Status = TdxDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData);\r
1277 }\r
1278\r
1279 return Status;\r
1280 }\r
1281\r
fb91d6cb
MX
1282 //\r
1283 // According to UEFI Spec 2.10 Section 38.4.1 the mapping between MrIndex and Intel\r
1284 // TDX Measurement Register is:\r
1285 // MrIndex 0 <--> MRTD\r
1286 // MrIndex 1-3 <--> RTMR[0-2]\r
1287 // Only the RMTR registers can be extended in TDVF by HashAndExtend. So MrIndex will\r
1288 // decreased by 1 before it is sent to HashAndExtend.\r
1289 //\r
57a6ee34 1290 Status = HashAndExtend (\r
fb91d6cb 1291 NewEventHdr->MrIndex - 1,\r
57a6ee34
MX
1292 HashData,\r
1293 (UINTN)HashDataLen,\r
1294 &DigestList\r
1295 );\r
1296 if (!EFI_ERROR (Status)) {\r
1297 if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
1298 Status = TdxDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
1299 }\r
1300 }\r
1301\r
1302 return Status;\r
1303}\r
1304\r
1305/**\r
1306 The EFI_CC_MEASUREMENT_PROTOCOL HashLogExtendEvent function call provides callers with\r
1307 an opportunity to extend and optionally log events without requiring\r
1308 knowledge of actual TPM commands.\r
1309 The extend operation will occur even if this function cannot create an event\r
1310 log entry (e.g. due to the event log being full).\r
1311\r
1312 @param[in] This Indicates the calling context\r
1313 @param[in] Flags Bitmap providing additional information.\r
1314 @param[in] DataToHash Physical address of the start of the data buffer to be hashed.\r
1315 @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash.\r
1316 @param[in] Event Pointer to data buffer containing information about the event.\r
1317\r
1318 @retval EFI_SUCCESS Operation completed successfully.\r
1319 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
1320 @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs.\r
1321 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
1322 @retval EFI_UNSUPPORTED The PE/COFF image type is not supported.\r
1323**/\r
1324EFI_STATUS\r
1325EFIAPI\r
1326TdHashLogExtendEvent (\r
1327 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
1328 IN UINT64 Flags,\r
1329 IN EFI_PHYSICAL_ADDRESS DataToHash,\r
1330 IN UINT64 DataToHashLen,\r
1331 IN EFI_CC_EVENT *CcEvent\r
1332 )\r
1333{\r
1334 EFI_STATUS Status;\r
1335 CC_EVENT_HDR NewEventHdr;\r
1336 TPML_DIGEST_VALUES DigestList;\r
1337\r
1338 DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent ...\n"));\r
1339\r
1340 if ((This == NULL) || (CcEvent == NULL)) {\r
1341 return EFI_INVALID_PARAMETER;\r
1342 }\r
1343\r
1344 //\r
1345 // Do not check hash data size for EV_NO_ACTION event.\r
1346 //\r
1347 if ((CcEvent->Header.EventType != EV_NO_ACTION) && (DataToHash == 0)) {\r
1348 return EFI_INVALID_PARAMETER;\r
1349 }\r
1350\r
1351 if (CcEvent->Size < CcEvent->Header.HeaderSize + sizeof (UINT32)) {\r
1352 return EFI_INVALID_PARAMETER;\r
1353 }\r
1354\r
fb91d6cb
MX
1355 if (CcEvent->Header.MrIndex == CC_MR_INDEX_0_MRTD) {\r
1356 DEBUG ((DEBUG_ERROR, "%a: MRTD cannot be extended in TDVF.\n", __FUNCTION__));\r
1357 return EFI_INVALID_PARAMETER;\r
1358 }\r
1359\r
1360 if (CcEvent->Header.MrIndex >= CC_MR_INDEX_INVALID) {\r
1361 DEBUG ((DEBUG_ERROR, "%a: MrIndex is invalid. (%d)\n", __FUNCTION__, CcEvent->Header.MrIndex));\r
57a6ee34
MX
1362 return EFI_INVALID_PARAMETER;\r
1363 }\r
1364\r
1365 NewEventHdr.MrIndex = CcEvent->Header.MrIndex;\r
1366 NewEventHdr.EventType = CcEvent->Header.EventType;\r
1367 NewEventHdr.EventSize = CcEvent->Size - sizeof (UINT32) - CcEvent->Header.HeaderSize;\r
1368 if ((Flags & EFI_CC_FLAG_PE_COFF_IMAGE) != 0) {\r
fb91d6cb
MX
1369 //\r
1370 // According to UEFI Spec 2.10 Section 38.4.1 the mapping between MrIndex and Intel\r
1371 // TDX Measurement Register is:\r
1372 // MrIndex 0 <--> MRTD\r
1373 // MrIndex 1-3 <--> RTMR[0-2]\r
1374 // Only the RMTR registers can be extended in TDVF by HashAndExtend. So MrIndex will\r
1375 // decreased by 1 before it is sent to MeasurePeImageAndExtend.\r
1376 //\r
57a6ee34 1377 Status = MeasurePeImageAndExtend (\r
fb91d6cb 1378 NewEventHdr.MrIndex - 1,\r
57a6ee34
MX
1379 DataToHash,\r
1380 (UINTN)DataToHashLen,\r
1381 &DigestList\r
1382 );\r
1383 if (!EFI_ERROR (Status)) {\r
1384 if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
1385 Status = TdxDxeLogHashEvent (&DigestList, &NewEventHdr, CcEvent->Event);\r
1386 }\r
1387 }\r
1388 } else {\r
1389 Status = TdxDxeHashLogExtendEvent (\r
1390 Flags,\r
1391 (UINT8 *)(UINTN)DataToHash,\r
1392 DataToHashLen,\r
1393 &NewEventHdr,\r
1394 CcEvent->Event\r
1395 );\r
1396 }\r
1397\r
1398 DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent - %r\n", Status));\r
1399 return Status;\r
1400}\r
1401\r
1402EFI_CC_MEASUREMENT_PROTOCOL mTdProtocol = {\r
1403 TdGetCapability,\r
1404 TdGetEventLog,\r
1405 TdHashLogExtendEvent,\r
1406 TdMapPcrToMrIndex,\r
1407};\r
1408\r
1409#define TD_HASH_COUNT 1\r
1410#define TEMP_BUF_LEN (sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) \\r
1411 + (TD_HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8))\r
1412\r
1413/**\r
1414 Initialize the TD Event Log and log events passed from the PEI phase.\r
1415\r
1416 @retval EFI_SUCCESS Operation completed successfully.\r
1417 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1418\r
1419**/\r
1420EFI_STATUS\r
1421SetupCcEventLog (\r
1422 VOID\r
1423 )\r
1424{\r
1425 EFI_STATUS Status;\r
1426 EFI_PHYSICAL_ADDRESS Lasa;\r
1427 UINTN Index;\r
1428 TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
1429 UINT8 TempBuf[TEMP_BUF_LEN];\r
1430 TCG_PCR_EVENT_HDR SpecIdEvent;\r
1431 TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
1432 TCG_EfiSpecIdEventAlgorithmSize *TempDigestSize;\r
1433 UINT8 *VendorInfoSize;\r
1434 UINT32 NumberOfAlgorithms;\r
1435 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
1436 EFI_PEI_HOB_POINTERS GuidHob;\r
1437 CC_EVENT_HDR NoActionEvent;\r
1438\r
1439 Status = EFI_SUCCESS;\r
1440 DEBUG ((DEBUG_INFO, "SetupCcEventLog\n"));\r
1441\r
1442 Index = 0;\r
1443 LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
1444\r
1445 //\r
1446 // 1. Create Log Area\r
1447 //\r
1448 mTdxDxeData.EventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
1449\r
1450 // allocate pages for TD Event log\r
1451 Status = gBS->AllocatePages (\r
1452 AllocateAnyPages,\r
1453 EfiACPIMemoryNVS,\r
1454 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
1455 &Lasa\r
1456 );\r
1457 if (EFI_ERROR (Status)) {\r
1458 return Status;\r
1459 }\r
1460\r
1461 mTdxDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
1462 mTdxDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
1463 mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = 0;\r
1464\r
1465 //\r
1466 // Report TD event log address and length, so that they can be reported in\r
1467 // TD ACPI table. Ignore the return status, because those fields are optional.\r
1468 //\r
1469 PcdSet32S (PcdCcEventlogAcpiTableLaml, (UINT32)mTdxDxeData.EventLogAreaStruct[Index].Laml);\r
1470 PcdSet64S (PcdCcEventlogAcpiTableLasa, mTdxDxeData.EventLogAreaStruct[Index].Lasa);\r
1471\r
1472 //\r
1473 // To initialize them as 0xFF is recommended\r
1474 // because the OS can know the last entry for that.\r
1475 //\r
1476 SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
1477\r
1478 //\r
1479 // Create first entry for Log Header Entry Data\r
1480 //\r
1481\r
1482 //\r
1483 // TcgEfiSpecIdEventStruct\r
1484 //\r
1485 TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)TempBuf;\r
1486 CopyMem (TcgEfiSpecIdEventStruct->signature, TCG_EfiSpecIDEventStruct_SIGNATURE_03, sizeof (TcgEfiSpecIdEventStruct->signature));\r
1487\r
1488 TcgEfiSpecIdEventStruct->platformClass = PcdGet8 (PcdTpmPlatformClass);\r
1489\r
1490 TcgEfiSpecIdEventStruct->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2;\r
1491 TcgEfiSpecIdEventStruct->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2;\r
1492 TcgEfiSpecIdEventStruct->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2;\r
1493 TcgEfiSpecIdEventStruct->uintnSize = sizeof (UINTN)/sizeof (UINT32);\r
1494 NumberOfAlgorithms = 0;\r
1495 DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct\r
1496 + sizeof (*TcgEfiSpecIdEventStruct)\r
1497 + sizeof (NumberOfAlgorithms));\r
1498\r
1499 TempDigestSize = DigestSize;\r
1500 TempDigestSize += NumberOfAlgorithms;\r
1501 TempDigestSize->algorithmId = TPM_ALG_SHA384;\r
1502 TempDigestSize->digestSize = SHA384_DIGEST_SIZE;\r
1503 NumberOfAlgorithms++;\r
1504\r
1505 CopyMem (TcgEfiSpecIdEventStruct + 1, &NumberOfAlgorithms, sizeof (NumberOfAlgorithms));\r
1506 TempDigestSize = DigestSize;\r
1507 TempDigestSize += NumberOfAlgorithms;\r
1508 VendorInfoSize = (UINT8 *)TempDigestSize;\r
1509 *VendorInfoSize = 0;\r
1510\r
1511 SpecIdEvent.PCRIndex = 1; // PCRIndex 0 maps to MrIndex 1\r
1512 SpecIdEvent.EventType = EV_NO_ACTION;\r
1513 ZeroMem (&SpecIdEvent.Digest, sizeof (SpecIdEvent.Digest));\r
1514 SpecIdEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct);\r
1515\r
1516 //\r
1517 // TD Event log re-use the spec of TCG2 Event log.\r
1518 // Log TcgEfiSpecIdEventStruct as the first Event. Event format is TCG_PCR_EVENT.\r
1519 // TCG EFI Protocol Spec. Section 5.3 Event Log Header\r
1520 // TCG PC Client PFP spec. Section 9.2 Measurement Event Entries and Log\r
1521 //\r
1522 Status = TdxDxeLogEvent (\r
1523 LogFormat,\r
1524 &SpecIdEvent,\r
1525 sizeof (SpecIdEvent),\r
1526 (UINT8 *)TcgEfiSpecIdEventStruct,\r
1527 SpecIdEvent.EventSize\r
1528 );\r
1529 //\r
1530 // record the offset at the end of 800-155 event.\r
1531 // the future 800-155 event can be inserted here.\r
1532 //\r
1533 mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = mTdxDxeData.EventLogAreaStruct[Index].EventLogSize;\r
1534\r
1535 //\r
1536 // Tcg800155PlatformIdEvent. Event format is TCG_PCR_EVENT2\r
1537 //\r
1538 GuidHob.Guid = GetFirstGuidHob (&gTcg800155PlatformIdEventHobGuid);\r
1539 while (GuidHob.Guid != NULL) {\r
1540 InitNoActionEvent (&NoActionEvent, GET_GUID_HOB_DATA_SIZE (GuidHob.Guid));\r
1541\r
1542 Status = TdxDxeLogEvent (\r
1543 LogFormat,\r
1544 &NoActionEvent,\r
1545 sizeof (NoActionEvent.MrIndex) + sizeof (NoActionEvent.EventType) + GetDigestListBinSize (&NoActionEvent.Digests) + sizeof (NoActionEvent.EventSize),\r
1546 GET_GUID_HOB_DATA (GuidHob.Guid),\r
1547 GET_GUID_HOB_DATA_SIZE (GuidHob.Guid)\r
1548 );\r
1549\r
1550 GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
1551 GuidHob.Guid = GetNextGuidHob (&gTcg800155PlatformIdEventHobGuid, GuidHob.Guid);\r
1552 }\r
1553\r
1554 //\r
1555 // 2. Create Final Log Area\r
1556 //\r
1557 Status = gBS->AllocatePages (\r
1558 AllocateAnyPages,\r
1559 EfiACPIMemoryNVS,\r
1560 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcg2FinalLogAreaLen)),\r
1561 &Lasa\r
1562 );\r
1563 if (EFI_ERROR (Status)) {\r
1564 return Status;\r
1565 }\r
1566\r
1567 SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcg2FinalLogAreaLen), 0xFF);\r
1568\r
1569 //\r
1570 // Initialize\r
1571 //\r
1572 mTdxDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa;\r
1573 (mTdxDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION;\r
1574 (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents = 0;\r
1575\r
1576 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
1577 mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
1578 mTdxDxeData.FinalEventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcg2FinalLogAreaLen) - sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
1579 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0;\r
1580 mTdxDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa;\r
1581 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE;\r
1582 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE;\r
1583 mTdxDxeData.FinalEventLogAreaStruct[Index].Next800155EventOffset = 0;\r
1584\r
1585 //\r
1586 // Install to configuration table for EFI_CC_EVENT_LOG_FORMAT_TCG_2\r
1587 //\r
1588 Status = gBS->InstallConfigurationTable (&gEfiCcFinalEventsTableGuid, (VOID *)mTdxDxeData.FinalEventsTable[Index]);\r
1589 if (EFI_ERROR (Status)) {\r
1590 return Status;\r
1591 }\r
1592\r
1593 return Status;\r
1594}\r
1595\r
1596/**\r
1597 Measure and log an action string, and extend the measurement result into RTMR.\r
1598\r
1599 @param[in] MrIndex MrIndex to extend\r
1600 @param[in] String A specific string that indicates an Action event.\r
1601\r
1602 @retval EFI_SUCCESS Operation completed successfully.\r
1603 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1604\r
1605**/\r
1606EFI_STATUS\r
1607TdMeasureAction (\r
1608 IN UINT32 MrIndex,\r
1609 IN CHAR8 *String\r
1610 )\r
1611{\r
1612 CC_EVENT_HDR CcEvent;\r
1613\r
1614 CcEvent.MrIndex = MrIndex;\r
1615 CcEvent.EventType = EV_EFI_ACTION;\r
1616 CcEvent.EventSize = (UINT32)AsciiStrLen (String);\r
1617 return TdxDxeHashLogExtendEvent (\r
1618 0,\r
1619 (UINT8 *)String,\r
1620 CcEvent.EventSize,\r
1621 &CcEvent,\r
1622 (UINT8 *)String\r
1623 );\r
1624}\r
1625\r
1626/**\r
1627 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
1628\r
1629 @retval EFI_SUCCESS Operation completed successfully.\r
1630 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1631\r
1632**/\r
1633EFI_STATUS\r
1634MeasureHandoffTables (\r
1635 VOID\r
1636 )\r
1637{\r
1638 EFI_STATUS Status;\r
1639 CC_EVENT_HDR CcEvent;\r
1640 EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
1641 UINTN ProcessorNum;\r
1642 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
1643\r
1644 ProcessorLocBuf = NULL;\r
1645 Status = EFI_SUCCESS;\r
1646\r
1647 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
1648 //\r
1649 // Tcg Server spec.\r
1650 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
1651 //\r
1652 Status = GetProcessorsCpuLocation (&ProcessorLocBuf, &ProcessorNum);\r
1653\r
1654 if (!EFI_ERROR (Status)) {\r
1655 CcEvent.MrIndex = MapPcrToMrIndex (1);\r
1656 CcEvent.EventType = EV_TABLE_OF_DEVICES;\r
1657 CcEvent.EventSize = sizeof (HandoffTables);\r
1658\r
1659 HandoffTables.NumberOfTables = 1;\r
1660 HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
1661 HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
1662\r
1663 Status = TdxDxeHashLogExtendEvent (\r
1664 0,\r
1665 (UINT8 *)(UINTN)ProcessorLocBuf,\r
1666 sizeof (EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
1667 &CcEvent,\r
1668 (UINT8 *)&HandoffTables\r
1669 );\r
1670\r
1671 FreePool (ProcessorLocBuf);\r
1672 }\r
1673 }\r
1674\r
1675 return Status;\r
1676}\r
1677\r
1678/**\r
1679 Measure and log Separator event, and extend the measurement result into a specific PCR.\r
1680\r
1681 @param[in] PCRIndex PCR index.\r
1682\r
1683 @retval EFI_SUCCESS Operation completed successfully.\r
1684 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1685\r
1686**/\r
1687EFI_STATUS\r
1688MeasureSeparatorEvent (\r
1689 IN UINT32 MrIndex\r
1690 )\r
1691{\r
1692 CC_EVENT_HDR CcEvent;\r
1693 UINT32 EventData;\r
1694\r
1695 DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent to Rtmr - %d\n", MrIndex));\r
1696\r
1697 EventData = 0;\r
1698 CcEvent.MrIndex = MrIndex;\r
1699 CcEvent.EventType = EV_SEPARATOR;\r
1700 CcEvent.EventSize = (UINT32)sizeof (EventData);\r
1701\r
1702 return TdxDxeHashLogExtendEvent (\r
1703 0,\r
1704 (UINT8 *)&EventData,\r
1705 sizeof (EventData),\r
1706 &CcEvent,\r
1707 (UINT8 *)&EventData\r
1708 );\r
1709}\r
1710\r
1711/**\r
1712 Measure and log an EFI variable, and extend the measurement result into a specific RTMR.\r
1713\r
1714 @param[in] MrIndex RTMR Index.\r
1715 @param[in] EventType Event type.\r
1716 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1717 @param[in] VendorGuid A unique identifier for the vendor.\r
1718 @param[in] VarData The content of the variable data.\r
1719 @param[in] VarSize The size of the variable data.\r
1720\r
1721 @retval EFI_SUCCESS Operation completed successfully.\r
1722 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1723 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1724\r
1725**/\r
1726EFI_STATUS\r
1727MeasureVariable (\r
1728 IN UINT32 MrIndex,\r
1729 IN TCG_EVENTTYPE EventType,\r
1730 IN CHAR16 *VarName,\r
1731 IN EFI_GUID *VendorGuid,\r
1732 IN VOID *VarData,\r
1733 IN UINTN VarSize\r
1734 )\r
1735{\r
1736 EFI_STATUS Status;\r
1737 CC_EVENT_HDR CcEvent;\r
1738 UINTN VarNameLength;\r
1739 UEFI_VARIABLE_DATA *VarLog;\r
1740\r
1741 DEBUG ((DEBUG_INFO, "TdTcg2Dxe: MeasureVariable (Rtmr - %x, EventType - %x, ", (UINTN)MrIndex, (UINTN)EventType));\r
1742 DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
1743\r
1744 VarNameLength = StrLen (VarName);\r
1745 CcEvent.MrIndex = MrIndex;\r
1746 CcEvent.EventType = EventType;\r
1747\r
1748 CcEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
1749 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
1750\r
1751 VarLog = (UEFI_VARIABLE_DATA *)AllocatePool (CcEvent.EventSize);\r
1752 if (VarLog == NULL) {\r
1753 return EFI_OUT_OF_RESOURCES;\r
1754 }\r
1755\r
1756 VarLog->VariableName = *VendorGuid;\r
1757 VarLog->UnicodeNameLength = VarNameLength;\r
1758 VarLog->VariableDataLength = VarSize;\r
1759 CopyMem (\r
1760 VarLog->UnicodeName,\r
1761 VarName,\r
1762 VarNameLength * sizeof (*VarName)\r
1763 );\r
1764 if ((VarSize != 0) && (VarData != NULL)) {\r
1765 CopyMem (\r
1766 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
1767 VarData,\r
1768 VarSize\r
1769 );\r
1770 }\r
1771\r
1772 if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
1773 //\r
1774 // Digest is the event data (UEFI_VARIABLE_DATA)\r
1775 //\r
1776 Status = TdxDxeHashLogExtendEvent (\r
1777 0,\r
1778 (UINT8 *)VarLog,\r
1779 CcEvent.EventSize,\r
1780 &CcEvent,\r
1781 (UINT8 *)VarLog\r
1782 );\r
1783 } else {\r
1784 ASSERT (VarData != NULL);\r
1785 Status = TdxDxeHashLogExtendEvent (\r
1786 0,\r
1787 (UINT8 *)VarData,\r
1788 VarSize,\r
1789 &CcEvent,\r
1790 (UINT8 *)VarLog\r
1791 );\r
1792 }\r
1793\r
1794 FreePool (VarLog);\r
1795 return Status;\r
1796}\r
1797\r
1798/**\r
1799 Read then Measure and log an EFI variable, and extend the measurement result into a specific RTMR.\r
1800\r
1801 @param[in] MrIndex RTMR Index.\r
1802 @param[in] EventType Event type.\r
1803 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1804 @param[in] VendorGuid A unique identifier for the vendor.\r
1805 @param[out] VarSize The size of the variable data.\r
1806 @param[out] VarData Pointer to the content of the variable.\r
1807\r
1808 @retval EFI_SUCCESS Operation completed successfully.\r
1809 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1810 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1811\r
1812**/\r
1813EFI_STATUS\r
1814ReadAndMeasureVariable (\r
1815 IN UINT32 MrIndex,\r
1816 IN TCG_EVENTTYPE EventType,\r
1817 IN CHAR16 *VarName,\r
1818 IN EFI_GUID *VendorGuid,\r
1819 OUT UINTN *VarSize,\r
1820 OUT VOID **VarData\r
1821 )\r
1822{\r
1823 EFI_STATUS Status;\r
1824\r
1825 Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);\r
1826 if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
1827 if (EFI_ERROR (Status)) {\r
1828 //\r
1829 // It is valid case, so we need handle it.\r
1830 //\r
1831 *VarData = NULL;\r
1832 *VarSize = 0;\r
1833 }\r
1834 } else {\r
1835 //\r
1836 // if status error, VarData is freed and set NULL by GetVariable2\r
1837 //\r
1838 if (EFI_ERROR (Status)) {\r
1839 return EFI_NOT_FOUND;\r
1840 }\r
1841 }\r
1842\r
1843 Status = MeasureVariable (\r
1844 MrIndex,\r
1845 EventType,\r
1846 VarName,\r
1847 VendorGuid,\r
1848 *VarData,\r
1849 *VarSize\r
1850 );\r
1851 return Status;\r
1852}\r
1853\r
1854/**\r
1855 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[1].\r
1856according to TCG PC Client PFP spec 0021 Section 2.4.4.2\r
1857\r
1858 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1859 @param[in] VendorGuid A unique identifier for the vendor.\r
1860 @param[out] VarSize The size of the variable data.\r
1861 @param[out] VarData Pointer to the content of the variable.\r
1862\r
1863 @retval EFI_SUCCESS Operation completed successfully.\r
1864 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1865 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1866\r
1867**/\r
1868EFI_STATUS\r
1869ReadAndMeasureBootVariable (\r
1870 IN CHAR16 *VarName,\r
1871 IN EFI_GUID *VendorGuid,\r
1872 OUT UINTN *VarSize,\r
1873 OUT VOID **VarData\r
1874 )\r
1875{\r
57a6ee34 1876 return ReadAndMeasureVariable (\r
e0dcfb31 1877 MapPcrToMrIndex (1),\r
57a6ee34
MX
1878 EV_EFI_VARIABLE_BOOT,\r
1879 VarName,\r
1880 VendorGuid,\r
1881 VarSize,\r
1882 VarData\r
1883 );\r
1884}\r
1885\r
1886/**\r
1887 Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].\r
1888\r
1889 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1890 @param[in] VendorGuid A unique identifier for the vendor.\r
1891 @param[out] VarSize The size of the variable data.\r
1892 @param[out] VarData Pointer to the content of the variable.\r
1893\r
1894 @retval EFI_SUCCESS Operation completed successfully.\r
1895 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1896 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1897\r
1898**/\r
1899EFI_STATUS\r
1900ReadAndMeasureSecureVariable (\r
1901 IN CHAR16 *VarName,\r
1902 IN EFI_GUID *VendorGuid,\r
1903 OUT UINTN *VarSize,\r
1904 OUT VOID **VarData\r
1905 )\r
1906{\r
1907 return ReadAndMeasureVariable (\r
1908 MapPcrToMrIndex (7),\r
1909 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
1910 VarName,\r
1911 VendorGuid,\r
1912 VarSize,\r
1913 VarData\r
1914 );\r
1915}\r
1916\r
1917/**\r
1918 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
1919\r
1920 The EFI boot variables are BootOrder and Boot#### variables.\r
1921\r
1922 @retval EFI_SUCCESS Operation completed successfully.\r
1923 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1924 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1925\r
1926**/\r
1927EFI_STATUS\r
1928MeasureAllBootVariables (\r
1929 VOID\r
1930 )\r
1931{\r
1932 EFI_STATUS Status;\r
1933 UINT16 *BootOrder;\r
1934 UINTN BootCount;\r
1935 UINTN Index;\r
1936 VOID *BootVarData;\r
1937 UINTN Size;\r
1938\r
1939 Status = ReadAndMeasureBootVariable (\r
1940 mBootVarName,\r
1941 &gEfiGlobalVariableGuid,\r
1942 &BootCount,\r
1943 (VOID **)&BootOrder\r
1944 );\r
1945 if ((Status == EFI_NOT_FOUND) || (BootOrder == NULL)) {\r
1946 return EFI_SUCCESS;\r
1947 }\r
1948\r
1949 if (EFI_ERROR (Status)) {\r
1950 //\r
1951 // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
1952 //\r
1953 FreePool (BootOrder);\r
1954 return Status;\r
1955 }\r
1956\r
1957 BootCount /= sizeof (*BootOrder);\r
1958 for (Index = 0; Index < BootCount; Index++) {\r
1959 UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
1960 Status = ReadAndMeasureBootVariable (\r
1961 mBootVarName,\r
1962 &gEfiGlobalVariableGuid,\r
1963 &Size,\r
1964 &BootVarData\r
1965 );\r
1966 if (!EFI_ERROR (Status)) {\r
1967 FreePool (BootVarData);\r
1968 }\r
1969 }\r
1970\r
1971 FreePool (BootOrder);\r
1972 return EFI_SUCCESS;\r
1973}\r
1974\r
1975/**\r
1976 Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.\r
1977\r
1978 The EFI boot variables are BootOrder and Boot#### variables.\r
1979\r
1980 @retval EFI_SUCCESS Operation completed successfully.\r
1981 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1982 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1983\r
1984**/\r
1985EFI_STATUS\r
1986MeasureAllSecureVariables (\r
1987 VOID\r
1988 )\r
1989{\r
1990 EFI_STATUS Status;\r
1991 VOID *Data;\r
1992 UINTN DataSize;\r
1993 UINTN Index;\r
1994\r
1995 Status = EFI_NOT_FOUND;\r
1996 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {\r
1997 Status = ReadAndMeasureSecureVariable (\r
1998 mVariableType[Index].VariableName,\r
1999 mVariableType[Index].VendorGuid,\r
2000 &DataSize,\r
2001 &Data\r
2002 );\r
2003 if (!EFI_ERROR (Status)) {\r
2004 if (Data != NULL) {\r
2005 FreePool (Data);\r
2006 }\r
2007 }\r
2008 }\r
2009\r
2010 //\r
2011 // Measure DBT if present and not empty\r
2012 //\r
2013 Status = GetVariable2 (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, &Data, &DataSize);\r
2014 if (!EFI_ERROR (Status)) {\r
2015 Status = MeasureVariable (\r
2016 MapPcrToMrIndex (7),\r
2017 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
2018 EFI_IMAGE_SECURITY_DATABASE2,\r
2019 &gEfiImageSecurityDatabaseGuid,\r
2020 Data,\r
2021 DataSize\r
2022 );\r
2023 FreePool (Data);\r
2024 } else {\r
2025 DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));\r
2026 }\r
2027\r
2028 return EFI_SUCCESS;\r
2029}\r
2030\r
2031/**\r
2032 Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.\r
2033\r
2034 @retval EFI_SUCCESS Operation completed successfully.\r
2035 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
2036 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
2037\r
2038**/\r
2039EFI_STATUS\r
2040MeasureLaunchOfFirmwareDebugger (\r
2041 VOID\r
2042 )\r
2043{\r
2044 CC_EVENT_HDR CcEvent;\r
2045\r
2046 CcEvent.MrIndex = MapPcrToMrIndex (7);\r
2047 CcEvent.EventType = EV_EFI_ACTION;\r
2048 CcEvent.EventSize = sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
2049 return TdxDxeHashLogExtendEvent (\r
2050 0,\r
2051 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
2052 sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
2053 &CcEvent,\r
2054 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING\r
2055 );\r
2056}\r
2057\r
2058/**\r
2059 Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.\r
2060\r
2061 Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)\r
2062 - The contents of the SecureBoot variable\r
2063 - The contents of the PK variable\r
2064 - The contents of the KEK variable\r
2065 - The contents of the EFI_IMAGE_SECURITY_DATABASE variable\r
2066 - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable\r
2067 - Separator\r
2068 - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path\r
2069\r
2070 NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,\r
2071 EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].\r
2072\r
2073 @param[in] Event Event whose notification function is being invoked\r
2074 @param[in] Context Pointer to the notification function's context\r
2075**/\r
2076VOID\r
2077EFIAPI\r
2078MeasureSecureBootPolicy (\r
2079 IN EFI_EVENT Event,\r
2080 IN VOID *Context\r
2081 )\r
2082{\r
2083 EFI_STATUS Status;\r
2084 VOID *Protocol;\r
2085\r
2086 Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);\r
2087 if (EFI_ERROR (Status)) {\r
2088 return;\r
2089 }\r
2090\r
2091 if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {\r
2092 Status = MeasureLaunchOfFirmwareDebugger ();\r
2093 DEBUG ((DEBUG_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
2094 }\r
2095\r
2096 Status = MeasureAllSecureVariables ();\r
2097 DEBUG ((DEBUG_INFO, "MeasureAllSecureVariables - %r\n", Status));\r
2098\r
2099 //\r
2100 // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)\r
2101 // and ImageVerification (Authority)\r
2102 // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So\r
2103 // the Authority measurement happen before ReadToBoot event.\r
2104 //\r
2105 Status = MeasureSeparatorEvent (MapPcrToMrIndex (7));\r
2106 DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent - %r\n", Status));\r
2107 return;\r
2108}\r
2109\r
2110/**\r
2111 Ready to Boot Event notification handler.\r
2112\r
2113 Sequence of OS boot events is measured in this event notification handler.\r
2114\r
2115 @param[in] Event Event whose notification function is being invoked\r
2116 @param[in] Context Pointer to the notification function's context\r
2117\r
2118**/\r
2119VOID\r
2120EFIAPI\r
2121OnReadyToBoot (\r
2122 IN EFI_EVENT Event,\r
2123 IN VOID *Context\r
2124 )\r
2125{\r
2126 EFI_STATUS Status;\r
2127\r
2128 PERF_START_EX (mImageHandle, "EventRec", "TdTcg2Dxe", 0, PERF_ID_CC_TCG2_DXE);\r
2129 if (mBootAttempts == 0) {\r
2130 //\r
2131 // Measure handoff tables.\r
2132 //\r
2133 Status = MeasureHandoffTables ();\r
2134 if (EFI_ERROR (Status)) {\r
2135 DEBUG ((DEBUG_ERROR, "HOBs not Measured. Error!\n"));\r
2136 }\r
2137\r
2138 //\r
2139 // Measure BootOrder & Boot#### variables.\r
2140 //\r
2141 Status = MeasureAllBootVariables ();\r
2142 if (EFI_ERROR (Status)) {\r
2143 DEBUG ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n"));\r
2144 }\r
2145\r
2146 //\r
2147 // 1. This is the first boot attempt.\r
2148 //\r
2149 Status = TdMeasureAction (\r
2150 MapPcrToMrIndex (4),\r
2151 EFI_CALLING_EFI_APPLICATION\r
2152 );\r
2153 if (EFI_ERROR (Status)) {\r
2154 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
2155 }\r
2156\r
2157 //\r
2158 // 2. Draw a line between pre-boot env and entering post-boot env.\r
2159 // PCR[7] (is RTMR[0]) is already done.\r
2160 //\r
2161 Status = MeasureSeparatorEvent (1);\r
2162 if (EFI_ERROR (Status)) {\r
2163 DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n"));\r
2164 }\r
2165\r
2166 //\r
2167 // 3. Measure GPT. It would be done in SAP driver.\r
2168 //\r
2169\r
2170 //\r
2171 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
2172 //\r
2173\r
2174 //\r
2175 // 5. Read & Measure variable. BootOrder already measured.\r
2176 //\r
2177 } else {\r
2178 //\r
2179 // 6. Not first attempt, meaning a return from last attempt\r
2180 //\r
2181 Status = TdMeasureAction (\r
2182 MapPcrToMrIndex (4),\r
2183 EFI_RETURNING_FROM_EFI_APPLICATION\r
2184 );\r
2185 if (EFI_ERROR (Status)) {\r
2186 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION));\r
2187 }\r
2188\r
2189 //\r
2190 // 7. Next boot attempt, measure "Calling EFI Application from Boot Option" again\r
2191 // TCG PC Client PFP spec Section 2.4.4.5 Step 4\r
2192 //\r
2193 Status = TdMeasureAction (\r
2194 MapPcrToMrIndex (4),\r
2195 EFI_CALLING_EFI_APPLICATION\r
2196 );\r
2197 if (EFI_ERROR (Status)) {\r
2198 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
2199 }\r
2200 }\r
2201\r
2202 DEBUG ((DEBUG_INFO, "TdTcg2Dxe Measure Data when ReadyToBoot\n"));\r
2203 //\r
2204 // Increase boot attempt counter.\r
2205 //\r
2206 mBootAttempts++;\r
2207 PERF_END_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_CC_TCG2_DXE + 1);\r
2208}\r
2209\r
2210/**\r
2211 Exit Boot Services Event notification handler.\r
2212\r
2213 Measure invocation and success of ExitBootServices.\r
2214\r
2215 @param[in] Event Event whose notification function is being invoked\r
2216 @param[in] Context Pointer to the notification function's context\r
2217\r
2218**/\r
2219VOID\r
2220EFIAPI\r
2221OnExitBootServices (\r
2222 IN EFI_EVENT Event,\r
2223 IN VOID *Context\r
2224 )\r
2225{\r
2226 EFI_STATUS Status;\r
2227\r
2228 //\r
2229 // Measure invocation of ExitBootServices,\r
2230 //\r
2231 Status = TdMeasureAction (\r
2232 MapPcrToMrIndex (5),\r
2233 EFI_EXIT_BOOT_SERVICES_INVOCATION\r
2234 );\r
2235 if (EFI_ERROR (Status)) {\r
2236 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
2237 }\r
2238\r
2239 //\r
2240 // Measure success of ExitBootServices\r
2241 //\r
2242 Status = TdMeasureAction (\r
2243 MapPcrToMrIndex (5),\r
2244 EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
2245 );\r
2246 if (EFI_ERROR (Status)) {\r
2247 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
2248 }\r
2249}\r
2250\r
2251/**\r
2252 Exit Boot Services Failed Event notification handler.\r
2253\r
2254 Measure Failure of ExitBootServices.\r
2255\r
2256 @param[in] Event Event whose notification function is being invoked\r
2257 @param[in] Context Pointer to the notification function's context\r
2258\r
2259**/\r
2260VOID\r
2261EFIAPI\r
2262OnExitBootServicesFailed (\r
2263 IN EFI_EVENT Event,\r
2264 IN VOID *Context\r
2265 )\r
2266{\r
2267 EFI_STATUS Status;\r
2268\r
2269 //\r
2270 // Measure Failure of ExitBootServices,\r
2271 //\r
2272 Status = TdMeasureAction (\r
2273 MapPcrToMrIndex (5),\r
2274 EFI_EXIT_BOOT_SERVICES_FAILED\r
2275 );\r
2276 if (EFI_ERROR (Status)) {\r
2277 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
2278 }\r
2279}\r
2280\r
2281EFI_STATUS\r
2282SyncCcEvent (\r
2283 VOID\r
2284 )\r
2285{\r
2286 EFI_STATUS Status;\r
2287 EFI_PEI_HOB_POINTERS GuidHob;\r
2288 VOID *CcEvent;\r
2289 VOID *DigestListBin;\r
2290 UINT32 DigestListBinSize;\r
2291 UINT8 *Event;\r
2292 UINT32 EventSize;\r
2293 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
2294\r
2295 DEBUG ((DEBUG_INFO, "Sync Cc event from SEC\n"));\r
2296\r
2297 Status = EFI_SUCCESS;\r
2298 LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
2299 GuidHob.Guid = GetFirstGuidHob (&gCcEventEntryHobGuid);\r
2300\r
2301 while (!EFI_ERROR (Status) && GuidHob.Guid != NULL) {\r
2302 CcEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid));\r
2303 if (CcEvent == NULL) {\r
2304 return EFI_OUT_OF_RESOURCES;\r
2305 }\r
2306\r
2307 GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
2308 GuidHob.Guid = GetNextGuidHob (&gCcEventEntryHobGuid, GuidHob.Guid);\r
2309\r
2310 DigestListBin = (UINT8 *)CcEvent + sizeof (UINT32) + sizeof (TCG_EVENTTYPE);\r
2311 DigestListBinSize = GetDigestListBinSize (DigestListBin);\r
2312\r
2313 //\r
2314 // Event size.\r
2315 //\r
2316 EventSize = *(UINT32 *)((UINT8 *)DigestListBin + DigestListBinSize);\r
2317 Event = (UINT8 *)DigestListBin + DigestListBinSize + sizeof (UINT32);\r
2318\r
2319 //\r
2320 // Log the event\r
2321 //\r
2322 Status = TdxDxeLogEvent (\r
2323 LogFormat,\r
2324 CcEvent,\r
2325 sizeof (UINT32) + sizeof (TCG_EVENTTYPE) + DigestListBinSize + sizeof (UINT32),\r
2326 Event,\r
2327 EventSize\r
2328 );\r
2329\r
2330 DumpCcEvent ((CC_EVENT *)CcEvent);\r
2331 FreePool (CcEvent);\r
2332 }\r
2333\r
2334 return Status;\r
2335}\r
2336\r
2337/**\r
2338 Install TDVF ACPI Table when ACPI Table Protocol is available.\r
2339\r
2340 @param[in] Event Event whose notification function is being invoked\r
2341 @param[in] Context Pointer to the notification function's context\r
2342**/\r
2343VOID\r
2344EFIAPI\r
2345InstallAcpiTable (\r
2346 IN EFI_EVENT Event,\r
2347 IN VOID *Context\r
2348 )\r
2349{\r
2350 UINTN TableKey;\r
2351 EFI_STATUS Status;\r
2352 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
2353 UINT64 OemTableId;\r
2354\r
2355 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
2356 if (EFI_ERROR (Status)) {\r
2357 DEBUG ((DEBUG_ERROR, "TD: AcpiTableProtocol is not installed. %r\n", Status));\r
2358 return;\r
2359 }\r
2360\r
2361 mTdxEventlogAcpiTemplate.Laml = (UINT64)PcdGet32 (PcdCcEventlogAcpiTableLaml);\r
2362 mTdxEventlogAcpiTemplate.Lasa = PcdGet64 (PcdCcEventlogAcpiTableLasa);\r
2363 CopyMem (mTdxEventlogAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTdxEventlogAcpiTemplate.Header.OemId));\r
2364 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
2365 CopyMem (&mTdxEventlogAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
2366 mTdxEventlogAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
2367 mTdxEventlogAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
2368 mTdxEventlogAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
2369\r
2370 //\r
2371 // Construct ACPI Table\r
2372 Status = AcpiTable->InstallAcpiTable (\r
2373 AcpiTable,\r
2374 &mTdxEventlogAcpiTemplate,\r
2375 mTdxEventlogAcpiTemplate.Header.Length,\r
2376 &TableKey\r
2377 );\r
2378 ASSERT_EFI_ERROR (Status);\r
2379\r
2380 DEBUG ((DEBUG_INFO, "TDVF Eventlog ACPI Table is installed.\n"));\r
2381}\r
2382\r
2383/**\r
2384 The function install TdTcg2 protocol.\r
2385\r
2386 @retval EFI_SUCCESS TdTcg2 protocol is installed.\r
2387 @retval other Some error occurs.\r
2388**/\r
2389EFI_STATUS\r
2390InstallCcMeasurementProtocol (\r
2391 VOID\r
2392 )\r
2393{\r
2394 EFI_STATUS Status;\r
2395 EFI_HANDLE Handle;\r
2396\r
2397 Handle = NULL;\r
2398 Status = gBS->InstallMultipleProtocolInterfaces (\r
2399 &Handle,\r
2400 &gEfiCcMeasurementProtocolGuid,\r
2401 &mTdProtocol,\r
2402 NULL\r
2403 );\r
2404 DEBUG ((DEBUG_INFO, "CcProtocol: Install %r\n", Status));\r
2405 return Status;\r
2406}\r
2407\r
2408/**\r
2409 The driver's entry point. It publishes EFI Tcg2 Protocol.\r
2410\r
2411 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
2412 @param[in] SystemTable A pointer to the EFI System Table.\r
2413\r
2414 @retval EFI_SUCCESS The entry point is executed successfully.\r
2415 @retval other Some error occurs when executing this entry point.\r
2416**/\r
2417EFI_STATUS\r
2418EFIAPI\r
2419DriverEntry (\r
2420 IN EFI_HANDLE ImageHandle,\r
2421 IN EFI_SYSTEM_TABLE *SystemTable\r
2422 )\r
2423{\r
2424 EFI_STATUS Status;\r
2425 EFI_EVENT Event;\r
2426 VOID *Registration;\r
2427\r
2428 if (!TdIsEnabled ()) {\r
2429 return EFI_UNSUPPORTED;\r
2430 }\r
2431\r
2432 mImageHandle = ImageHandle;\r
2433\r
2434 //\r
2435 // Fill information\r
2436 //\r
2437 // ASSERT (TD_EVENT_LOG_AREA_COUNT_MAX == sizeof(mTEventInfo)/sizeof(mTcg2EventInfo[0]));\r
2438\r
2439 mTdxDxeData.BsCap.Size = sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY);\r
2440 mTdxDxeData.BsCap.ProtocolVersion.Major = 1;\r
19f7c63e 2441 mTdxDxeData.BsCap.ProtocolVersion.Minor = 0;\r
57a6ee34 2442 mTdxDxeData.BsCap.StructureVersion.Major = 1;\r
19f7c63e 2443 mTdxDxeData.BsCap.StructureVersion.Minor = 0;\r
57a6ee34
MX
2444\r
2445 //\r
2446 // Get supported PCR and current Active PCRs\r
2447 // For TD gueset HA384 is supported.\r
2448 //\r
2449 mTdxDxeData.BsCap.HashAlgorithmBitmap = HASH_ALG_SHA384;\r
2450\r
2451 // TD guest only supports EFI_TCG2_EVENT_LOG_FORMAT_TCG_2\r
2452 mTdxDxeData.BsCap.SupportedEventLogs = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
2453\r
2454 //\r
2455 // Setup the log area and copy event log from hob list to it\r
2456 //\r
2457 Status = SetupCcEventLog ();\r
2458 ASSERT_EFI_ERROR (Status);\r
2459\r
2460 if (!EFI_ERROR (Status)) {\r
2461 Status = SyncCcEvent ();\r
2462 ASSERT_EFI_ERROR (Status);\r
2463 }\r
2464\r
2465 //\r
2466 // Measure handoff tables, Boot#### variables etc.\r
2467 //\r
2468 Status = EfiCreateEventReadyToBootEx (\r
2469 TPL_CALLBACK,\r
2470 OnReadyToBoot,\r
2471 NULL,\r
2472 &Event\r
2473 );\r
2474\r
2475 Status = gBS->CreateEventEx (\r
2476 EVT_NOTIFY_SIGNAL,\r
2477 TPL_NOTIFY,\r
2478 OnExitBootServices,\r
2479 NULL,\r
2480 &gEfiEventExitBootServicesGuid,\r
2481 &Event\r
2482 );\r
2483\r
2484 //\r
2485 // Measure Exit Boot Service failed\r
2486 //\r
2487 Status = gBS->CreateEventEx (\r
2488 EVT_NOTIFY_SIGNAL,\r
2489 TPL_NOTIFY,\r
2490 OnExitBootServicesFailed,\r
2491 NULL,\r
2492 &gEventExitBootServicesFailedGuid,\r
2493 &Event\r
2494 );\r
2495\r
2496 //\r
2497 // Create event callback, because we need access variable on SecureBootPolicyVariable\r
2498 // We should use VariableWriteArch instead of VariableArch, because Variable driver\r
2499 // may update SecureBoot value based on last setting.\r
2500 //\r
2501 EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);\r
2502\r
2503 //\r
2504 // Install CcMeasurementProtocol\r
2505 //\r
2506 Status = InstallCcMeasurementProtocol ();\r
2507 DEBUG ((DEBUG_INFO, "InstallCcMeasurementProtocol - %r\n", Status));\r
2508\r
2509 if (Status == EFI_SUCCESS) {\r
2510 //\r
2511 // Create event callback to install CC EventLog ACPI Table\r
2512 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
ff848517
MX
2513 } else {\r
2514 //\r
2515 // Cc measurement feature is crucial to a td-guest and it shall stop running immediately\r
2516 // when it is failed to be installed.\r
2517 DEBUG ((DEBUG_ERROR, "%a: CcMeasurement protocol failed to be installed - %r\n", __FUNCTION__, Status));\r
2518 CpuDeadLoop ();\r
57a6ee34
MX
2519 }\r
2520\r
2521 return Status;\r
2522}\r