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