]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/SecMeasurementLib/SecMeasurementLibTdx.c
OvmfPkg: Introduce SecMeasurementLib
[mirror_edk2.git] / OvmfPkg / Library / SecMeasurementLib / SecMeasurementLibTdx.c
CommitLineData
a708536d
MX
1/** @file\r
2*\r
3* Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
4* SPDX-License-Identifier: BSD-2-Clause-Patent\r
5*\r
6**/\r
7\r
8#include <PiPei.h>\r
9#include <Guid/CcEventHob.h>\r
10#include <Library/BaseMemoryLib.h>\r
11#include <Library/DebugLib.h>\r
12#include <Library/HashLib.h>\r
13#include <Library/HobLib.h>\r
14#include <Library/PrintLib.h>\r
15#include <IndustryStandard/Tpm20.h>\r
16#include <Protocol/CcMeasurement.h>\r
17#include <Library/SecMeasurementLib.h>\r
18\r
19#pragma pack(1)\r
20\r
21typedef struct {\r
22 UINT32 count;\r
23 TPMI_ALG_HASH hashAlg;\r
24 BYTE sha384[SHA384_DIGEST_SIZE];\r
25} TDX_DIGEST_VALUE;\r
26\r
27#define HANDOFF_TABLE_DESC "TdxTable"\r
28typedef struct {\r
29 UINT8 TableDescriptionSize;\r
30 UINT8 TableDescription[sizeof (HANDOFF_TABLE_DESC)];\r
31 UINT64 NumberOfTables;\r
32 EFI_CONFIGURATION_TABLE TableEntry[1];\r
33} TDX_HANDOFF_TABLE_POINTERS2;\r
34\r
35#define FV_HANDOFF_TABLE_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"\r
36typedef struct {\r
37 UINT8 BlobDescriptionSize;\r
38 UINT8 BlobDescription[sizeof (FV_HANDOFF_TABLE_DESC)];\r
39 EFI_PHYSICAL_ADDRESS BlobBase;\r
40 UINT64 BlobLength;\r
41} FV_HANDOFF_TABLE_POINTERS2;\r
42\r
43#pragma pack()\r
44\r
45#define INVALID_PCR2MR_INDEX 0xFF\r
46\r
47/**\r
48 RTMR[0] => PCR[1,7]\r
49 RTMR[1] => PCR[2,3,4,5]\r
50 RTMR[2] => PCR[8~15]\r
51 RTMR[3] => NA\r
52 Note:\r
53 PCR[0] is mapped to MRTD and should not appear here.\r
54 PCR[6] is reserved for OEM. It is not used.\r
55**/\r
56UINT8\r
57GetMappedRtmrIndex (\r
58 UINT32 PCRIndex\r
59 )\r
60{\r
61 UINT8 RtmrIndex;\r
62\r
63 if ((PCRIndex == 6) || (PCRIndex == 0) || (PCRIndex > 15)) {\r
64 DEBUG ((DEBUG_ERROR, "Invalid PCRIndex(%d) map to MR Index.\n", PCRIndex));\r
65 ASSERT (FALSE);\r
66 return INVALID_PCR2MR_INDEX;\r
67 }\r
68\r
69 RtmrIndex = 0;\r
70 if ((PCRIndex == 1) || (PCRIndex == 7)) {\r
71 RtmrIndex = 0;\r
72 } else if ((PCRIndex >= 2) && (PCRIndex < 6)) {\r
73 RtmrIndex = 1;\r
74 } else if ((PCRIndex >= 8) && (PCRIndex <= 15)) {\r
75 RtmrIndex = 2;\r
76 }\r
77\r
78 return RtmrIndex;\r
79}\r
80\r
81/**\r
82 Tpm measure and log data, and extend the measurement result into a specific PCR.\r
83\r
84 @param[in] PcrIndex PCR Index.\r
85 @param[in] EventType Event type.\r
86 @param[in] EventLog Measurement event log.\r
87 @param[in] LogLen Event log length in bytes.\r
88 @param[in] HashData The start of the data buffer to be hashed, extended.\r
89 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
90 @retval EFI_SUCCESS Operation completed successfully.\r
91 @retval EFI_UNSUPPORTED TPM device not available.\r
92 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
93 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
94**/\r
95EFI_STATUS\r
96EFIAPI\r
97TdxMeasureAndLogData (\r
98 IN UINT32 PcrIndex,\r
99 IN UINT32 EventType,\r
100 IN VOID *EventLog,\r
101 IN UINT32 LogLen,\r
102 IN VOID *HashData,\r
103 IN UINT64 HashDataLen\r
104 )\r
105{\r
106 EFI_STATUS Status;\r
107 UINT32 RtmrIndex;\r
108 VOID *EventHobData;\r
109 TCG_PCR_EVENT2 *TcgPcrEvent2;\r
110 UINT8 *DigestBuffer;\r
111 TDX_DIGEST_VALUE *TdxDigest;\r
112 TPML_DIGEST_VALUES DigestList;\r
113 UINT8 *Ptr;\r
114\r
115 RtmrIndex = GetMappedRtmrIndex (PcrIndex);\r
116 if (RtmrIndex == INVALID_PCR2MR_INDEX) {\r
117 return EFI_INVALID_PARAMETER;\r
118 }\r
119\r
120 DEBUG ((DEBUG_INFO, "Creating TdTcg2PcrEvent PCR[%d]/RTMR[%d] EventType 0x%x\n", PcrIndex, RtmrIndex, EventType));\r
121\r
122 Status = HashAndExtend (\r
123 RtmrIndex,\r
124 (VOID *)HashData,\r
125 HashDataLen,\r
126 &DigestList\r
127 );\r
128\r
129 if (EFI_ERROR (Status)) {\r
130 DEBUG ((DEBUG_INFO, "Failed to HashAndExtend. %r\n", Status));\r
131 return Status;\r
132 }\r
133\r
134 //\r
135 // Use TDX_DIGEST_VALUE in the GUID HOB DataLength calculation\r
136 // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary\r
137 // which is limited to a SHA384 digest list\r
138 //\r
139 EventHobData = BuildGuidHob (\r
140 &gCcEventEntryHobGuid,\r
141 sizeof (TcgPcrEvent2->PCRIndex) + sizeof (TcgPcrEvent2->EventType) +\r
142 sizeof (TDX_DIGEST_VALUE) +\r
143 sizeof (TcgPcrEvent2->EventSize) + LogLen\r
144 );\r
145\r
146 if (EventHobData == NULL) {\r
147 return EFI_OUT_OF_RESOURCES;\r
148 }\r
149\r
150 Ptr = (UINT8 *)EventHobData;\r
151 //\r
152 // Initialize PcrEvent data now\r
153 //\r
154 RtmrIndex++;\r
155 CopyMem (Ptr, &RtmrIndex, sizeof (UINT32));\r
156 Ptr += sizeof (UINT32);\r
157 CopyMem (Ptr, &EventType, sizeof (TCG_EVENTTYPE));\r
158 Ptr += sizeof (TCG_EVENTTYPE);\r
159\r
160 DigestBuffer = Ptr;\r
161\r
162 TdxDigest = (TDX_DIGEST_VALUE *)DigestBuffer;\r
163 TdxDigest->count = 1;\r
164 TdxDigest->hashAlg = TPM_ALG_SHA384;\r
165 CopyMem (\r
166 TdxDigest->sha384,\r
167 DigestList.digests[0].digest.sha384,\r
168 SHA384_DIGEST_SIZE\r
169 );\r
170\r
171 Ptr += sizeof (TDX_DIGEST_VALUE);\r
172\r
173 CopyMem (Ptr, &LogLen, sizeof (UINT32));\r
174 Ptr += sizeof (UINT32);\r
175 CopyMem (Ptr, EventLog, LogLen);\r
176 Ptr += LogLen;\r
177\r
178 Status = EFI_SUCCESS;\r
179 return Status;\r
180}\r
181\r
182/**\r
183 Measure the Hoblist passed from the VMM.\r
184\r
185 @param[in] VmmHobList The Hoblist pass the firmware\r
186\r
187 @retval EFI_SUCCESS Fv image is measured successfully\r
188 or it has been already measured.\r
189 @retval Others Other errors as indicated\r
190**/\r
191EFI_STATUS\r
192EFIAPI\r
193MeasureHobList (\r
194 IN CONST VOID *VmmHobList\r
195 )\r
196{\r
197 EFI_PEI_HOB_POINTERS Hob;\r
198 TDX_HANDOFF_TABLE_POINTERS2 HandoffTables;\r
199 EFI_STATUS Status;\r
200\r
201 if (!TdIsEnabled ()) {\r
202 ASSERT (FALSE);\r
203 return EFI_UNSUPPORTED;\r
204 }\r
205\r
206 Hob.Raw = (UINT8 *)VmmHobList;\r
207\r
208 //\r
209 // Parse the HOB list until end of list.\r
210 //\r
211 while (!END_OF_HOB_LIST (Hob)) {\r
212 Hob.Raw = GET_NEXT_HOB (Hob);\r
213 }\r
214\r
215 //\r
216 // Init the log event for HOB measurement\r
217 //\r
218\r
219 HandoffTables.TableDescriptionSize = sizeof (HandoffTables.TableDescription);\r
220 CopyMem (HandoffTables.TableDescription, HANDOFF_TABLE_DESC, sizeof (HandoffTables.TableDescription));\r
221 HandoffTables.NumberOfTables = 1;\r
222 CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gUefiOvmfPkgTokenSpaceGuid);\r
223 HandoffTables.TableEntry[0].VendorTable = (VOID *)VmmHobList;\r
224\r
225 Status = TdxMeasureAndLogData (\r
226 1, // PCRIndex\r
227 EV_EFI_HANDOFF_TABLES2, // EventType\r
228 (VOID *)&HandoffTables, // EventData\r
229 sizeof (HandoffTables), // EventSize\r
230 (UINT8 *)(UINTN)VmmHobList, // HashData\r
231 (UINTN)((UINT8 *)Hob.Raw - (UINT8 *)VmmHobList) // HashDataLen\r
232 );\r
233\r
234 if (EFI_ERROR (Status)) {\r
235 ASSERT (FALSE);\r
236 }\r
237\r
238 return Status;\r
239}\r
240\r
241/**\r
242 Get the FvName from the FV header.\r
243\r
244 Causion: The FV is untrusted input.\r
245\r
246 @param[in] FvBase Base address of FV image.\r
247 @param[in] FvLength Length of FV image.\r
248\r
249 @return FvName pointer\r
250 @retval NULL FvName is NOT found\r
251**/\r
252VOID *\r
253GetFvName (\r
254 IN EFI_PHYSICAL_ADDRESS FvBase,\r
255 IN UINT64 FvLength\r
256 )\r
257{\r
258 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
259 EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;\r
260\r
261 if (FvBase >= MAX_ADDRESS) {\r
262 return NULL;\r
263 }\r
264\r
265 if (FvLength >= MAX_ADDRESS - FvBase) {\r
266 return NULL;\r
267 }\r
268\r
269 if (FvLength < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {\r
270 return NULL;\r
271 }\r
272\r
273 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;\r
274 if (FvHeader->ExtHeaderOffset < sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {\r
275 return NULL;\r
276 }\r
277\r
278 if (FvHeader->ExtHeaderOffset + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {\r
279 return NULL;\r
280 }\r
281\r
282 FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);\r
283\r
284 return &FvExtHeader->FvName;\r
285}\r
286\r
287/**\r
288 Measure FV image.\r
289\r
290 @param[in] FvBase Base address of FV image.\r
291 @param[in] FvLength Length of FV image.\r
292 @param[in] PcrIndex Index of PCR\r
293\r
294 @retval EFI_SUCCESS Fv image is measured successfully\r
295 or it has been already measured.\r
296 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
297 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
298\r
299**/\r
300EFI_STATUS\r
301EFIAPI\r
302MeasureFvImage (\r
303 IN EFI_PHYSICAL_ADDRESS FvBase,\r
304 IN UINT64 FvLength,\r
305 IN UINT8 PcrIndex\r
306 )\r
307{\r
308 EFI_STATUS Status;\r
309 FV_HANDOFF_TABLE_POINTERS2 FvBlob2;\r
310 VOID *FvName;\r
311\r
312 //\r
313 // Init the log event for FV measurement\r
314 //\r
315 FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription);\r
316 CopyMem (FvBlob2.BlobDescription, FV_HANDOFF_TABLE_DESC, sizeof (FvBlob2.BlobDescription));\r
317 FvName = GetFvName (FvBase, FvLength);\r
318 if (FvName != NULL) {\r
319 AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName);\r
320 }\r
321\r
322 FvBlob2.BlobBase = FvBase;\r
323 FvBlob2.BlobLength = FvLength;\r
324\r
325 Status = TdxMeasureAndLogData (\r
326 1, // PCRIndex\r
327 EV_EFI_PLATFORM_FIRMWARE_BLOB2, // EventType\r
328 (VOID *)&FvBlob2, // EventData\r
329 sizeof (FvBlob2), // EventSize\r
330 (UINT8 *)(UINTN)FvBase, // HashData\r
331 (UINTN)(FvLength) // HashDataLen\r
332 );\r
333\r
334 if (EFI_ERROR (Status)) {\r
335 DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));\r
336 ASSERT (FALSE);\r
337 }\r
338\r
339 return Status;\r
340}\r