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