]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
SecurityPkg: Fix GetSupportedAndActivePcrs counter calculation
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2Capability.c
CommitLineData
c1d93242
JY
1/** @file\r
2 Implement TPM2 Capability related command.\r
3\r
dd577319 4Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>\r
289b714b 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
c1d93242
JY
6\r
7**/\r
8\r
9#include <IndustryStandard/UefiTcgPlatform.h>\r
10#include <Library/Tpm2CommandLib.h>\r
11#include <Library/Tpm2DeviceLib.h>\r
12#include <Library/BaseMemoryLib.h>\r
13#include <Library/BaseLib.h>\r
14#include <Library/DebugLib.h>\r
15\r
16#pragma pack(1)\r
17\r
18typedef struct {\r
19 TPM2_COMMAND_HEADER Header;\r
20 TPM_CAP Capability;\r
21 UINT32 Property;\r
22 UINT32 PropertyCount;\r
23} TPM2_GET_CAPABILITY_COMMAND;\r
24\r
25typedef struct {\r
26 TPM2_RESPONSE_HEADER Header;\r
27 TPMI_YES_NO MoreData;\r
28 TPMS_CAPABILITY_DATA CapabilityData;\r
29} TPM2_GET_CAPABILITY_RESPONSE;\r
30\r
31typedef struct {\r
32 TPM2_COMMAND_HEADER Header;\r
33 TPMT_PUBLIC_PARMS Parameters;\r
34} TPM2_TEST_PARMS_COMMAND;\r
35\r
36typedef struct {\r
37 TPM2_RESPONSE_HEADER Header;\r
38} TPM2_TEST_PARMS_RESPONSE;\r
39\r
40#pragma pack()\r
41\r
1b0d659e
ZQ
42#define TPMA_CC_COMMANDINDEX_MASK 0x2000FFFF\r
43\r
c1d93242
JY
44/**\r
45 This command returns various information regarding the TPM and its current state.\r
46\r
b3548d32
LG
47 The capability parameter determines the category of data returned. The property parameter\r
48 selects the first value of the selected category to be returned. If there is no property\r
c1d93242 49 that corresponds to the value of property, the next higher value is returned, if it exists.\r
b3548d32 50 The moreData parameter will have a value of YES if there are more values of the requested\r
c1d93242 51 type that were not returned.\r
b3548d32 52 If no next capability exists, the TPM will return a zero-length list and moreData will have\r
c1d93242
JY
53 a value of NO.\r
54\r
b3548d32
LG
55 NOTE:\r
56 To simplify this function, leave returned CapabilityData for caller to unpack since there are\r
c1d93242 57 many capability categories and only few categories will be used in firmware. It means the caller\r
d6b926e7 58 need swap the byte order for the fields in CapabilityData.\r
c1d93242
JY
59\r
60 @param[in] Capability Group selection; determines the format of the response.\r
b3548d32 61 @param[in] Property Further definition of information.\r
c1d93242
JY
62 @param[in] PropertyCount Number of properties of the indicated type to return.\r
63 @param[out] MoreData Flag to indicate if there are more values of this type.\r
64 @param[out] CapabilityData The capability data.\r
b3548d32 65\r
c1d93242
JY
66 @retval EFI_SUCCESS Operation completed successfully.\r
67 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
68**/\r
69EFI_STATUS\r
70EFIAPI\r
71Tpm2GetCapability (\r
72 IN TPM_CAP Capability,\r
73 IN UINT32 Property,\r
74 IN UINT32 PropertyCount,\r
75 OUT TPMI_YES_NO *MoreData,\r
76 OUT TPMS_CAPABILITY_DATA *CapabilityData\r
77 )\r
78{\r
79 EFI_STATUS Status;\r
80 TPM2_GET_CAPABILITY_COMMAND SendBuffer;\r
81 TPM2_GET_CAPABILITY_RESPONSE RecvBuffer;\r
82 UINT32 SendBufferSize;\r
83 UINT32 RecvBufferSize;\r
84\r
85 //\r
86 // Construct command\r
87 //\r
88 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
89 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_GetCapability);\r
90\r
91 SendBuffer.Capability = SwapBytes32 (Capability);\r
92 SendBuffer.Property = SwapBytes32 (Property);\r
93 SendBuffer.PropertyCount = SwapBytes32 (PropertyCount);\r
b3548d32 94\r
c1d93242
JY
95 SendBufferSize = (UINT32) sizeof (SendBuffer);\r
96 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
b3548d32 97\r
c1d93242
JY
98 //\r
99 // send Tpm command\r
100 //\r
101 RecvBufferSize = sizeof (RecvBuffer);\r
102 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer );\r
103 if (EFI_ERROR (Status)) {\r
104 return Status;\r
105 }\r
106\r
107 if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT8)) {\r
108 return EFI_DEVICE_ERROR;\r
109 }\r
110\r
dd577319
ZC
111 //\r
112 // Fail if command failed\r
113 //\r
114 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
3c610775 115 DEBUG ((DEBUG_ERROR, "Tpm2GetCapability: Response Code error! 0x%08x\r\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
dd577319
ZC
116 return EFI_DEVICE_ERROR;\r
117 }\r
118\r
c1d93242
JY
119 //\r
120 // Return the response\r
121 //\r
122 *MoreData = RecvBuffer.MoreData;\r
123 //\r
d6b926e7 124 // Does not unpack all possible property here, the caller should unpack it and note the byte order.\r
c1d93242
JY
125 //\r
126 CopyMem (CapabilityData, &RecvBuffer.CapabilityData, RecvBufferSize - sizeof (TPM2_RESPONSE_HEADER) - sizeof (UINT8));\r
b3548d32 127\r
c1d93242
JY
128 return EFI_SUCCESS;\r
129}\r
130\r
131/**\r
132 This command returns the information of TPM Family.\r
133\r
134 This function parse the value got from TPM2_GetCapability and return the Family.\r
135\r
136 @param[out] Family The Family of TPM. (a 4-octet character string)\r
b3548d32 137\r
c1d93242
JY
138 @retval EFI_SUCCESS Operation completed successfully.\r
139 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
140**/\r
141EFI_STATUS\r
142EFIAPI\r
143Tpm2GetCapabilityFamily (\r
144 OUT CHAR8 *Family\r
145 )\r
146{\r
147 TPMS_CAPABILITY_DATA TpmCap;\r
148 TPMI_YES_NO MoreData;\r
b3548d32 149 EFI_STATUS Status;\r
c1d93242
JY
150\r
151 Status = Tpm2GetCapability (\r
b3548d32
LG
152 TPM_CAP_TPM_PROPERTIES,\r
153 TPM_PT_FAMILY_INDICATOR,\r
154 1,\r
155 &MoreData,\r
c1d93242
JY
156 &TpmCap\r
157 );\r
158 if (EFI_ERROR (Status)) {\r
159 return Status;\r
160 }\r
161 CopyMem (Family, &TpmCap.data.tpmProperties.tpmProperty->value, 4);\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166/**\r
167 This command returns the information of TPM manufacture ID.\r
168\r
169 This function parse the value got from TPM2_GetCapability and return the TPM manufacture ID.\r
170\r
171 @param[out] ManufactureId The manufacture ID of TPM.\r
b3548d32 172\r
c1d93242
JY
173 @retval EFI_SUCCESS Operation completed successfully.\r
174 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
175**/\r
176EFI_STATUS\r
177EFIAPI\r
178Tpm2GetCapabilityManufactureID (\r
179 OUT UINT32 *ManufactureId\r
180 )\r
181{\r
182 TPMS_CAPABILITY_DATA TpmCap;\r
183 TPMI_YES_NO MoreData;\r
b3548d32 184 EFI_STATUS Status;\r
c1d93242
JY
185\r
186 Status = Tpm2GetCapability (\r
b3548d32
LG
187 TPM_CAP_TPM_PROPERTIES,\r
188 TPM_PT_MANUFACTURER,\r
189 1,\r
190 &MoreData,\r
c1d93242
JY
191 &TpmCap\r
192 );\r
193 if (EFI_ERROR (Status)) {\r
194 return Status;\r
195 }\r
73126ac2 196 *ManufactureId = TpmCap.data.tpmProperties.tpmProperty->value;\r
c1d93242
JY
197\r
198 return EFI_SUCCESS;\r
199}\r
200\r
201/**\r
202 This command returns the information of TPM FirmwareVersion.\r
203\r
204 This function parse the value got from TPM2_GetCapability and return the TPM FirmwareVersion.\r
205\r
206 @param[out] FirmwareVersion1 The FirmwareVersion1.\r
207 @param[out] FirmwareVersion2 The FirmwareVersion2.\r
b3548d32 208\r
c1d93242
JY
209 @retval EFI_SUCCESS Operation completed successfully.\r
210 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
211**/\r
212EFI_STATUS\r
213EFIAPI\r
214Tpm2GetCapabilityFirmwareVersion (\r
215 OUT UINT32 *FirmwareVersion1,\r
216 OUT UINT32 *FirmwareVersion2\r
217 )\r
218{\r
219 TPMS_CAPABILITY_DATA TpmCap;\r
220 TPMI_YES_NO MoreData;\r
b3548d32 221 EFI_STATUS Status;\r
c1d93242
JY
222\r
223 Status = Tpm2GetCapability (\r
b3548d32
LG
224 TPM_CAP_TPM_PROPERTIES,\r
225 TPM_PT_FIRMWARE_VERSION_1,\r
226 1,\r
227 &MoreData,\r
c1d93242
JY
228 &TpmCap\r
229 );\r
230 if (EFI_ERROR (Status)) {\r
231 return Status;\r
232 }\r
233 *FirmwareVersion1 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
234\r
235 Status = Tpm2GetCapability (\r
b3548d32
LG
236 TPM_CAP_TPM_PROPERTIES,\r
237 TPM_PT_FIRMWARE_VERSION_2,\r
238 1,\r
239 &MoreData,\r
c1d93242
JY
240 &TpmCap\r
241 );\r
242 if (EFI_ERROR (Status)) {\r
243 return Status;\r
244 }\r
245 *FirmwareVersion2 = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
246\r
247 return EFI_SUCCESS;\r
248}\r
249\r
250/**\r
251 This command returns the information of the maximum value for commandSize and responseSize in a command.\r
252\r
253 This function parse the value got from TPM2_GetCapability and return the max command size and response size\r
254\r
255 @param[out] MaxCommandSize The maximum value for commandSize in a command.\r
256 @param[out] MaxResponseSize The maximum value for responseSize in a command.\r
b3548d32 257\r
c1d93242
JY
258 @retval EFI_SUCCESS Operation completed successfully.\r
259 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
260**/\r
261EFI_STATUS\r
262EFIAPI\r
263Tpm2GetCapabilityMaxCommandResponseSize (\r
264 OUT UINT32 *MaxCommandSize,\r
265 OUT UINT32 *MaxResponseSize\r
266 )\r
267{\r
268 TPMS_CAPABILITY_DATA TpmCap;\r
269 TPMI_YES_NO MoreData;\r
270 EFI_STATUS Status;\r
271\r
272 Status = Tpm2GetCapability (\r
b3548d32
LG
273 TPM_CAP_TPM_PROPERTIES,\r
274 TPM_PT_MAX_COMMAND_SIZE,\r
275 1,\r
276 &MoreData,\r
c1d93242
JY
277 &TpmCap\r
278 );\r
279 if (EFI_ERROR (Status)) {\r
280 return Status;\r
281 }\r
282\r
283 *MaxCommandSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
284\r
285 Status = Tpm2GetCapability (\r
b3548d32
LG
286 TPM_CAP_TPM_PROPERTIES,\r
287 TPM_PT_MAX_RESPONSE_SIZE,\r
288 1,\r
289 &MoreData,\r
c1d93242
JY
290 &TpmCap\r
291 );\r
292 if (EFI_ERROR (Status)) {\r
293 return Status;\r
294 }\r
295\r
296 *MaxResponseSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
b3548d32 297 return EFI_SUCCESS;\r
c1d93242
JY
298}\r
299\r
300/**\r
301 This command returns Returns a list of TPMS_ALG_PROPERTIES. Each entry is an\r
b3548d32 302 algorithm ID and a set of properties of the algorithm.\r
c1d93242
JY
303\r
304 This function parse the value got from TPM2_GetCapability and return the list.\r
305\r
306 @param[out] AlgList List of algorithm.\r
b3548d32 307\r
c1d93242
JY
308 @retval EFI_SUCCESS Operation completed successfully.\r
309 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
310**/\r
311EFI_STATUS\r
312EFIAPI\r
313Tpm2GetCapabilitySupportedAlg (\r
314 OUT TPML_ALG_PROPERTY *AlgList\r
315 )\r
316{\r
317 TPMS_CAPABILITY_DATA TpmCap;\r
318 TPMI_YES_NO MoreData;\r
319 UINTN Index;\r
320 EFI_STATUS Status;\r
b3548d32 321\r
c1d93242 322 Status = Tpm2GetCapability (\r
b3548d32
LG
323 TPM_CAP_ALGS,\r
324 1,\r
325 MAX_CAP_ALGS,\r
326 &MoreData,\r
c1d93242
JY
327 &TpmCap\r
328 );\r
329 if (EFI_ERROR (Status)) {\r
330 return Status;\r
331 }\r
b3548d32 332\r
c1d93242
JY
333 CopyMem (AlgList, &TpmCap.data.algorithms, sizeof (TPML_ALG_PROPERTY));\r
334\r
335 AlgList->count = SwapBytes32 (AlgList->count);\r
dd577319
ZC
336 if (AlgList->count > MAX_CAP_ALGS) {\r
337 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilitySupportedAlg - AlgList->count error %x\n", AlgList->count));\r
b3548d32 338 return EFI_DEVICE_ERROR;\r
dd577319
ZC
339 }\r
340\r
c1d93242
JY
341 for (Index = 0; Index < AlgList->count; Index++) {\r
342 AlgList->algProperties[Index].alg = SwapBytes16 (AlgList->algProperties[Index].alg);\r
343 WriteUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties)));\r
344 }\r
345\r
346 return EFI_SUCCESS;\r
347}\r
348\r
349/**\r
350 This command returns the information of TPM LockoutCounter.\r
351\r
352 This function parse the value got from TPM2_GetCapability and return the LockoutCounter.\r
353\r
354 @param[out] LockoutCounter The LockoutCounter of TPM.\r
b3548d32 355\r
c1d93242
JY
356 @retval EFI_SUCCESS Operation completed successfully.\r
357 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
358**/\r
359EFI_STATUS\r
360EFIAPI\r
361Tpm2GetCapabilityLockoutCounter (\r
362 OUT UINT32 *LockoutCounter\r
363 )\r
364{\r
365 TPMS_CAPABILITY_DATA TpmCap;\r
366 TPMI_YES_NO MoreData;\r
b3548d32 367 EFI_STATUS Status;\r
c1d93242
JY
368\r
369 Status = Tpm2GetCapability (\r
b3548d32
LG
370 TPM_CAP_TPM_PROPERTIES,\r
371 TPM_PT_LOCKOUT_COUNTER,\r
372 1,\r
373 &MoreData,\r
c1d93242
JY
374 &TpmCap\r
375 );\r
376 if (EFI_ERROR (Status)) {\r
377 return Status;\r
378 }\r
379 *LockoutCounter = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
380\r
381 return EFI_SUCCESS;\r
382}\r
383\r
384/**\r
385 This command returns the information of TPM LockoutInterval.\r
386\r
387 This function parse the value got from TPM2_GetCapability and return the LockoutInterval.\r
388\r
389 @param[out] LockoutInterval The LockoutInterval of TPM.\r
b3548d32 390\r
c1d93242
JY
391 @retval EFI_SUCCESS Operation completed successfully.\r
392 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
393**/\r
394EFI_STATUS\r
395EFIAPI\r
396Tpm2GetCapabilityLockoutInterval (\r
397 OUT UINT32 *LockoutInterval\r
398 )\r
399{\r
400 TPMS_CAPABILITY_DATA TpmCap;\r
401 TPMI_YES_NO MoreData;\r
b3548d32 402 EFI_STATUS Status;\r
c1d93242
JY
403\r
404 Status = Tpm2GetCapability (\r
b3548d32
LG
405 TPM_CAP_TPM_PROPERTIES,\r
406 TPM_PT_LOCKOUT_INTERVAL,\r
407 1,\r
408 &MoreData,\r
c1d93242
JY
409 &TpmCap\r
410 );\r
411 if (EFI_ERROR (Status)) {\r
412 return Status;\r
413 }\r
414 *LockoutInterval = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
415\r
416 return EFI_SUCCESS;\r
417}\r
418\r
419/**\r
420 This command returns the information of TPM InputBufferSize.\r
421\r
422 This function parse the value got from TPM2_GetCapability and return the InputBufferSize.\r
423\r
424 @param[out] InputBufferSize The InputBufferSize of TPM.\r
425 the maximum size of a parameter (typically, a TPM2B_MAX_BUFFER)\r
b3548d32 426\r
c1d93242
JY
427 @retval EFI_SUCCESS Operation completed successfully.\r
428 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
429**/\r
430EFI_STATUS\r
431EFIAPI\r
432Tpm2GetCapabilityInputBufferSize (\r
433 OUT UINT32 *InputBufferSize\r
434 )\r
435{\r
436 TPMS_CAPABILITY_DATA TpmCap;\r
437 TPMI_YES_NO MoreData;\r
b3548d32 438 EFI_STATUS Status;\r
c1d93242
JY
439\r
440 Status = Tpm2GetCapability (\r
b3548d32
LG
441 TPM_CAP_TPM_PROPERTIES,\r
442 TPM_PT_INPUT_BUFFER,\r
443 1,\r
444 &MoreData,\r
c1d93242
JY
445 &TpmCap\r
446 );\r
447 if (EFI_ERROR (Status)) {\r
448 return Status;\r
449 }\r
450 *InputBufferSize = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
451\r
452 return EFI_SUCCESS;\r
453}\r
454\r
455/**\r
456 This command returns the information of TPM PCRs.\r
457\r
458 This function parse the value got from TPM2_GetCapability and return the PcrSelection.\r
459\r
460 @param[out] Pcrs The Pcr Selection\r
b3548d32 461\r
c1d93242
JY
462 @retval EFI_SUCCESS Operation completed successfully.\r
463 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
464**/\r
465EFI_STATUS\r
466EFIAPI\r
467Tpm2GetCapabilityPcrs (\r
468 OUT TPML_PCR_SELECTION *Pcrs\r
469 )\r
470{\r
471 TPMS_CAPABILITY_DATA TpmCap;\r
472 TPMI_YES_NO MoreData;\r
473 EFI_STATUS Status;\r
474 UINTN Index;\r
475\r
476 Status = Tpm2GetCapability (\r
b3548d32
LG
477 TPM_CAP_PCRS,\r
478 0,\r
479 1,\r
480 &MoreData,\r
c1d93242
JY
481 &TpmCap\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 return Status;\r
485 }\r
486\r
487 Pcrs->count = SwapBytes32 (TpmCap.data.assignedPCR.count);\r
dd577319
ZC
488 if (Pcrs->count > HASH_COUNT) {\r
489 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - Pcrs->count error %x\n", Pcrs->count));\r
490 return EFI_DEVICE_ERROR;\r
491 }\r
492\r
c1d93242
JY
493 for (Index = 0; Index < Pcrs->count; Index++) {\r
494 Pcrs->pcrSelections[Index].hash = SwapBytes16 (TpmCap.data.assignedPCR.pcrSelections[Index].hash);\r
495 Pcrs->pcrSelections[Index].sizeofSelect = TpmCap.data.assignedPCR.pcrSelections[Index].sizeofSelect;\r
dd577319
ZC
496 if (Pcrs->pcrSelections[Index].sizeofSelect > PCR_SELECT_MAX) {\r
497 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - sizeofSelect error %x\n", Pcrs->pcrSelections[Index].sizeofSelect));\r
498 return EFI_DEVICE_ERROR;\r
499 }\r
c1d93242
JY
500 CopyMem (Pcrs->pcrSelections[Index].pcrSelect, TpmCap.data.assignedPCR.pcrSelections[Index].pcrSelect, Pcrs->pcrSelections[Index].sizeofSelect);\r
501 }\r
502\r
503 return EFI_SUCCESS;\r
504}\r
505\r
07cdba18
JY
506/**\r
507 This function will query the TPM to determine which hashing algorithms\r
508 are supported and which PCR banks are currently active.\r
509\r
510 @param[out] TpmHashAlgorithmBitmap A bitmask containing the algorithms supported by the TPM.\r
511 @param[out] ActivePcrBanks A bitmask containing the PCRs currently allocated.\r
512\r
513 @retval EFI_SUCCESS TPM was successfully queried and return values can be trusted.\r
514 @retval Others An error occurred, likely in communication with the TPM.\r
515\r
516**/\r
517EFI_STATUS\r
518EFIAPI\r
519Tpm2GetCapabilitySupportedAndActivePcrs (\r
520 OUT UINT32 *TpmHashAlgorithmBitmap,\r
521 OUT UINT32 *ActivePcrBanks\r
522 )\r
523{\r
524 EFI_STATUS Status;\r
525 TPML_PCR_SELECTION Pcrs;\r
526 UINTN Index;\r
3c610775 527 UINT8 ActivePcrBankCount;\r
07cdba18
JY
528\r
529 //\r
3c610775 530 // Get supported PCR\r
07cdba18
JY
531 //\r
532 Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
3c610775
RGC
533 DEBUG ((DEBUG_INFO, "Supported PCRs - Count = %08x\n", Pcrs.count));\r
534 ActivePcrBankCount = 0;\r
07cdba18
JY
535 //\r
536 // If error, assume that we have at least SHA-1 (and return the error.)\r
537 //\r
538 if (EFI_ERROR (Status)) {\r
3c610775 539 DEBUG ((DEBUG_ERROR, "GetSupportedAndActivePcrs - Tpm2GetCapabilityPcrs fail!\n"));\r
07cdba18
JY
540 *TpmHashAlgorithmBitmap = HASH_ALG_SHA1;\r
541 *ActivePcrBanks = HASH_ALG_SHA1;\r
3c610775 542 ActivePcrBankCount = 1;\r
07cdba18
JY
543 }\r
544 //\r
545 // Otherwise, process the return data to determine what algorithms are supported\r
546 // and currently allocated.\r
547 //\r
548 else {\r
07cdba18
JY
549 *TpmHashAlgorithmBitmap = 0;\r
550 *ActivePcrBanks = 0;\r
551 for (Index = 0; Index < Pcrs.count; Index++) {\r
552 switch (Pcrs.pcrSelections[Index].hash) {\r
553 case TPM_ALG_SHA1:\r
3c610775 554 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA1 present.\n"));\r
07cdba18
JY
555 *TpmHashAlgorithmBitmap |= HASH_ALG_SHA1;\r
556 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
3c610775 557 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA1 active.\n"));\r
07cdba18 558 *ActivePcrBanks |= HASH_ALG_SHA1;\r
3c610775 559 ActivePcrBankCount++;\r
07cdba18
JY
560 }\r
561 break;\r
562 case TPM_ALG_SHA256:\r
3c610775 563 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA256 present.\n"));\r
07cdba18
JY
564 *TpmHashAlgorithmBitmap |= HASH_ALG_SHA256;\r
565 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
3c610775 566 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA256 active.\n"));\r
07cdba18 567 *ActivePcrBanks |= HASH_ALG_SHA256;\r
3c610775 568 ActivePcrBankCount++;\r
07cdba18
JY
569 }\r
570 break;\r
571 case TPM_ALG_SHA384:\r
3c610775 572 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA384 present.\n"));\r
07cdba18
JY
573 *TpmHashAlgorithmBitmap |= HASH_ALG_SHA384;\r
574 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
3c610775 575 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA384 active.\n"));\r
07cdba18 576 *ActivePcrBanks |= HASH_ALG_SHA384;\r
3c610775 577 ActivePcrBankCount++;\r
07cdba18
JY
578 }\r
579 break;\r
580 case TPM_ALG_SHA512:\r
3c610775 581 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA512 present.\n"));\r
07cdba18
JY
582 *TpmHashAlgorithmBitmap |= HASH_ALG_SHA512;\r
583 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
3c610775 584 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SHA512 active.\n"));\r
07cdba18 585 *ActivePcrBanks |= HASH_ALG_SHA512;\r
3c610775 586 ActivePcrBankCount++;\r
07cdba18
JY
587 }\r
588 break;\r
589 case TPM_ALG_SM3_256:\r
3c610775 590 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SM3_256 present.\n"));\r
07cdba18
JY
591 *TpmHashAlgorithmBitmap |= HASH_ALG_SM3_256;\r
592 if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
3c610775 593 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - HASH_ALG_SM3_256 active.\n"));\r
07cdba18 594 *ActivePcrBanks |= HASH_ALG_SM3_256;\r
3c610775 595 ActivePcrBankCount++;\r
07cdba18
JY
596 }\r
597 break;\r
3c610775
RGC
598 default:\r
599 DEBUG ((DEBUG_VERBOSE, "GetSupportedAndActivePcrs - Unsupported bank 0x%04x.\n", Pcrs.pcrSelections[Index].hash));\r
600 continue;\r
601 break;\r
07cdba18
JY
602 }\r
603 }\r
604 }\r
605\r
3c610775 606 DEBUG ((DEBUG_INFO, "GetSupportedAndActivePcrs - Count = %08x\n", ActivePcrBankCount));\r
07cdba18
JY
607 return Status;\r
608}\r
609\r
c1d93242
JY
610/**\r
611 This command returns the information of TPM AlgorithmSet.\r
612\r
613 This function parse the value got from TPM2_GetCapability and return the AlgorithmSet.\r
614\r
615 @param[out] AlgorithmSet The AlgorithmSet of TPM.\r
b3548d32 616\r
c1d93242
JY
617 @retval EFI_SUCCESS Operation completed successfully.\r
618 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
619**/\r
620EFI_STATUS\r
621EFIAPI\r
622Tpm2GetCapabilityAlgorithmSet (\r
623 OUT UINT32 *AlgorithmSet\r
624 )\r
625{\r
626 TPMS_CAPABILITY_DATA TpmCap;\r
627 TPMI_YES_NO MoreData;\r
b3548d32 628 EFI_STATUS Status;\r
c1d93242
JY
629\r
630 Status = Tpm2GetCapability (\r
b3548d32
LG
631 TPM_CAP_TPM_PROPERTIES,\r
632 TPM_PT_ALGORITHM_SET,\r
633 1,\r
634 &MoreData,\r
c1d93242
JY
635 &TpmCap\r
636 );\r
637 if (EFI_ERROR (Status)) {\r
638 return Status;\r
639 }\r
640 *AlgorithmSet = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);\r
641\r
642 return EFI_SUCCESS;\r
643}\r
644\r
1b0d659e
ZQ
645/**\r
646 This function will query if the command is supported.\r
647\r
648 @param[In] Command TPM_CC command starts from TPM_CC_FIRST.\r
649 @param[out] IsCmdImpl The command is supported or not.\r
650\r
651 @retval EFI_SUCCESS Operation completed successfully.\r
652 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
653**/\r
654EFI_STATUS\r
655EFIAPI\r
656Tpm2GetCapabilityIsCommandImplemented (\r
657 IN TPM_CC Command,\r
658 OUT BOOLEAN *IsCmdImpl\r
659 )\r
660{\r
661 TPMS_CAPABILITY_DATA TpmCap;\r
662 TPMI_YES_NO MoreData;\r
663 EFI_STATUS Status;\r
664 UINT32 Attribute;\r
665\r
666 Status = Tpm2GetCapability (\r
667 TPM_CAP_COMMANDS,\r
668 Command,\r
669 1,\r
670 &MoreData,\r
671 &TpmCap\r
672 );\r
673 if (EFI_ERROR (Status)) {\r
674 return Status;\r
675 }\r
676\r
677 CopyMem (&Attribute, &TpmCap.data.command.commandAttributes[0], sizeof (UINT32));\r
678 *IsCmdImpl = (Command == (SwapBytes32(Attribute) & TPMA_CC_COMMANDINDEX_MASK));\r
679\r
680 return EFI_SUCCESS;\r
681}\r
682\r
c1d93242
JY
683/**\r
684 This command is used to check to see if specific combinations of algorithm parameters are supported.\r
685\r
686 @param[in] Parameters Algorithm parameters to be validated\r
687\r
688 @retval EFI_SUCCESS Operation completed successfully.\r
689 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
690**/\r
691EFI_STATUS\r
692EFIAPI\r
693Tpm2TestParms (\r
694 IN TPMT_PUBLIC_PARMS *Parameters\r
695 )\r
696{\r
697 EFI_STATUS Status;\r
698 TPM2_TEST_PARMS_COMMAND SendBuffer;\r
699 TPM2_TEST_PARMS_RESPONSE RecvBuffer;\r
700 UINT32 SendBufferSize;\r
701 UINT32 RecvBufferSize;\r
702 UINT8 *Buffer;\r
703\r
704 //\r
705 // Construct command\r
706 //\r
707 SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
708 SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms);\r
709\r
710 Buffer = (UINT8 *)&SendBuffer.Parameters;\r
711 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type));\r
712 Buffer += sizeof(UINT16);\r
713 switch (Parameters->type) {\r
714 case TPM_ALG_KEYEDHASH:\r
715 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme));\r
716 Buffer += sizeof(UINT16);\r
717 switch (Parameters->parameters.keyedHashDetail.scheme.scheme) {\r
718 case TPM_ALG_HMAC:\r
719 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg));\r
720 Buffer += sizeof(UINT16);\r
721 break;\r
722 case TPM_ALG_XOR:\r
723 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg));\r
724 Buffer += sizeof(UINT16);\r
725 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf));\r
726 Buffer += sizeof(UINT16);\r
727 break;\r
728 default:\r
729 return EFI_INVALID_PARAMETER;\r
730 }\r
731 case TPM_ALG_SYMCIPHER:\r
732 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm));\r
733 Buffer += sizeof(UINT16);\r
734 switch (Parameters->parameters.symDetail.algorithm) {\r
735 case TPM_ALG_AES:\r
736 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes));\r
737 Buffer += sizeof(UINT16);\r
738 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes));\r
739 Buffer += sizeof(UINT16);\r
740 break;\r
741 case TPM_ALG_SM4:\r
742 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4));\r
743 Buffer += sizeof(UINT16);\r
744 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4));\r
745 Buffer += sizeof(UINT16);\r
746 break;\r
747 case TPM_ALG_XOR:\r
748 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor));\r
749 Buffer += sizeof(UINT16);\r
750 break;\r
751 case TPM_ALG_NULL:\r
752 break;\r
753 default:\r
754 return EFI_INVALID_PARAMETER;\r
755 }\r
756 break;\r
757 case TPM_ALG_RSA:\r
758 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm));\r
759 Buffer += sizeof(UINT16);\r
760 switch (Parameters->parameters.rsaDetail.symmetric.algorithm) {\r
761 case TPM_ALG_AES:\r
762 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes));\r
763 Buffer += sizeof(UINT16);\r
764 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes));\r
765 Buffer += sizeof(UINT16);\r
766 break;\r
767 case TPM_ALG_SM4:\r
768 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4));\r
769 Buffer += sizeof(UINT16);\r
770 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4));\r
771 Buffer += sizeof(UINT16);\r
772 break;\r
773 case TPM_ALG_NULL:\r
774 break;\r
775 default:\r
776 return EFI_INVALID_PARAMETER;\r
777 }\r
778 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme));\r
779 Buffer += sizeof(UINT16);\r
780 switch (Parameters->parameters.rsaDetail.scheme.scheme) {\r
781 case TPM_ALG_RSASSA:\r
782 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg));\r
783 Buffer += sizeof(UINT16);\r
784 break;\r
785 case TPM_ALG_RSAPSS:\r
786 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg));\r
787 Buffer += sizeof(UINT16);\r
788 break;\r
789 case TPM_ALG_RSAES:\r
790 break;\r
791 case TPM_ALG_OAEP:\r
792 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg));\r
793 Buffer += sizeof(UINT16);\r
794 break;\r
795 case TPM_ALG_NULL:\r
796 break;\r
797 default:\r
798 return EFI_INVALID_PARAMETER;\r
799 }\r
800 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits));\r
801 Buffer += sizeof(UINT16);\r
802 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent));\r
803 Buffer += sizeof(UINT32);\r
804 break;\r
805 case TPM_ALG_ECC:\r
806 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm));\r
807 Buffer += sizeof(UINT16);\r
808 switch (Parameters->parameters.eccDetail.symmetric.algorithm) {\r
809 case TPM_ALG_AES:\r
810 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes));\r
811 Buffer += sizeof(UINT16);\r
812 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes));\r
813 Buffer += sizeof(UINT16);\r
814 break;\r
815 case TPM_ALG_SM4:\r
816 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4));\r
817 Buffer += sizeof(UINT16);\r
818 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4));\r
819 Buffer += sizeof(UINT16);\r
820 break;\r
821 case TPM_ALG_NULL:\r
822 break;\r
823 default:\r
824 return EFI_INVALID_PARAMETER;\r
825 }\r
826 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme));\r
827 Buffer += sizeof(UINT16);\r
828 switch (Parameters->parameters.eccDetail.scheme.scheme) {\r
829 case TPM_ALG_ECDSA:\r
830 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg));\r
831 Buffer += sizeof(UINT16);\r
832 break;\r
833 case TPM_ALG_ECDAA:\r
834 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg));\r
835 Buffer += sizeof(UINT16);\r
836 break;\r
837 case TPM_ALG_ECSCHNORR:\r
838 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg));\r
839 Buffer += sizeof(UINT16);\r
840 break;\r
841 case TPM_ALG_ECDH:\r
842 break;\r
843 case TPM_ALG_NULL:\r
844 break;\r
845 default:\r
846 return EFI_INVALID_PARAMETER;\r
847 }\r
848 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID));\r
849 Buffer += sizeof(UINT16);\r
850 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme));\r
851 Buffer += sizeof(UINT16);\r
852 switch (Parameters->parameters.eccDetail.kdf.scheme) {\r
853 case TPM_ALG_MGF1:\r
854 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg));\r
855 Buffer += sizeof(UINT16);\r
856 break;\r
857 case TPM_ALG_KDF1_SP800_108:\r
858 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg));\r
859 Buffer += sizeof(UINT16);\r
860 break;\r
861 case TPM_ALG_KDF1_SP800_56a:\r
862 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg));\r
863 Buffer += sizeof(UINT16);\r
864 break;\r
865 case TPM_ALG_KDF2:\r
866 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg));\r
867 Buffer += sizeof(UINT16);\r
868 break;\r
869 case TPM_ALG_NULL:\r
870 break;\r
871 default:\r
872 return EFI_INVALID_PARAMETER;\r
873 }\r
874 break;\r
875 default:\r
876 return EFI_INVALID_PARAMETER;\r
877 }\r
878\r
879 SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);\r
880 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);\r
881\r
882 //\r
883 // send Tpm command\r
884 //\r
885 RecvBufferSize = sizeof (RecvBuffer);\r
886 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);\r
887 if (EFI_ERROR (Status)) {\r
888 return Status;\r
889 }\r
890\r
891 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {\r
3c610775 892 DEBUG ((DEBUG_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize));\r
c1d93242
JY
893 return EFI_DEVICE_ERROR;\r
894 }\r
895 if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {\r
3c610775 896 DEBUG ((DEBUG_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));\r
c1d93242
JY
897 return EFI_UNSUPPORTED;\r
898 }\r
899\r
900 return EFI_SUCCESS;\r
901}\r