1 /** @file
2   Implement TPM2 Capability related command.
3 
4 Copyright (c) 2013, 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 = SwapBytes32 (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 command returns the information of TPM AlgorithmSet.
490 
491   This function parse the value got from TPM2_GetCapability and return the AlgorithmSet.
492 
493   @param[out] AlgorithmSet    The AlgorithmSet of TPM.
494 
495   @retval EFI_SUCCESS            Operation completed successfully.
496   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
497 **/
498 EFI_STATUS
499 EFIAPI
Tpm2GetCapabilityAlgorithmSet(OUT UINT32 * AlgorithmSet)500 Tpm2GetCapabilityAlgorithmSet (
501   OUT     UINT32      *AlgorithmSet
502   )
503 {
504   TPMS_CAPABILITY_DATA    TpmCap;
505   TPMI_YES_NO             MoreData;
506   EFI_STATUS              Status;
507 
508   Status = Tpm2GetCapability (
509              TPM_CAP_TPM_PROPERTIES,
510              TPM_PT_ALGORITHM_SET,
511              1,
512              &MoreData,
513              &TpmCap
514              );
515   if (EFI_ERROR (Status)) {
516     return Status;
517   }
518   *AlgorithmSet = SwapBytes32 (TpmCap.data.tpmProperties.tpmProperty->value);
519 
520   return EFI_SUCCESS;
521 }
522 
523 /**
524   This command is used to check to see if specific combinations of algorithm parameters are supported.
525 
526   @param[in]  Parameters              Algorithm parameters to be validated
527 
528   @retval EFI_SUCCESS      Operation completed successfully.
529   @retval EFI_DEVICE_ERROR Unexpected device behavior.
530 **/
531 EFI_STATUS
532 EFIAPI
Tpm2TestParms(IN TPMT_PUBLIC_PARMS * Parameters)533 Tpm2TestParms (
534   IN  TPMT_PUBLIC_PARMS           *Parameters
535   )
536 {
537   EFI_STATUS                        Status;
538   TPM2_TEST_PARMS_COMMAND           SendBuffer;
539   TPM2_TEST_PARMS_RESPONSE          RecvBuffer;
540   UINT32                            SendBufferSize;
541   UINT32                            RecvBufferSize;
542   UINT8                             *Buffer;
543 
544   //
545   // Construct command
546   //
547   SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
548   SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms);
549 
550   Buffer = (UINT8 *)&SendBuffer.Parameters;
551   WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type));
552   Buffer += sizeof(UINT16);
553   switch (Parameters->type) {
554   case TPM_ALG_KEYEDHASH:
555     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme));
556     Buffer += sizeof(UINT16);
557     switch (Parameters->parameters.keyedHashDetail.scheme.scheme) {
558     case TPM_ALG_HMAC:
559       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg));
560       Buffer += sizeof(UINT16);
561       break;
562     case TPM_ALG_XOR:
563       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg));
564       Buffer += sizeof(UINT16);
565       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf));
566       Buffer += sizeof(UINT16);
567       break;
568     default:
569       return EFI_INVALID_PARAMETER;
570     }
571   case TPM_ALG_SYMCIPHER:
572     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm));
573     Buffer += sizeof(UINT16);
574     switch (Parameters->parameters.symDetail.algorithm) {
575     case TPM_ALG_AES:
576       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes));
577       Buffer += sizeof(UINT16);
578       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes));
579       Buffer += sizeof(UINT16);
580       break;
581     case TPM_ALG_SM4:
582       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4));
583       Buffer += sizeof(UINT16);
584       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4));
585       Buffer += sizeof(UINT16);
586       break;
587     case TPM_ALG_XOR:
588       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor));
589       Buffer += sizeof(UINT16);
590       break;
591     case TPM_ALG_NULL:
592       break;
593     default:
594       return EFI_INVALID_PARAMETER;
595     }
596     break;
597   case TPM_ALG_RSA:
598     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm));
599     Buffer += sizeof(UINT16);
600     switch (Parameters->parameters.rsaDetail.symmetric.algorithm) {
601     case TPM_ALG_AES:
602       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes));
603       Buffer += sizeof(UINT16);
604       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes));
605       Buffer += sizeof(UINT16);
606       break;
607     case TPM_ALG_SM4:
608       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4));
609       Buffer += sizeof(UINT16);
610       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4));
611       Buffer += sizeof(UINT16);
612       break;
613     case TPM_ALG_NULL:
614       break;
615     default:
616       return EFI_INVALID_PARAMETER;
617     }
618     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme));
619     Buffer += sizeof(UINT16);
620     switch (Parameters->parameters.rsaDetail.scheme.scheme) {
621     case TPM_ALG_RSASSA:
622       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg));
623       Buffer += sizeof(UINT16);
624       break;
625     case TPM_ALG_RSAPSS:
626       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg));
627       Buffer += sizeof(UINT16);
628       break;
629     case TPM_ALG_RSAES:
630       break;
631     case TPM_ALG_OAEP:
632       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg));
633       Buffer += sizeof(UINT16);
634       break;
635     case TPM_ALG_NULL:
636       break;
637     default:
638       return EFI_INVALID_PARAMETER;
639     }
640     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits));
641     Buffer += sizeof(UINT16);
642     WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent));
643     Buffer += sizeof(UINT32);
644     break;
645   case TPM_ALG_ECC:
646     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm));
647     Buffer += sizeof(UINT16);
648     switch (Parameters->parameters.eccDetail.symmetric.algorithm) {
649     case TPM_ALG_AES:
650       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes));
651       Buffer += sizeof(UINT16);
652       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes));
653       Buffer += sizeof(UINT16);
654       break;
655     case TPM_ALG_SM4:
656       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4));
657       Buffer += sizeof(UINT16);
658       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4));
659       Buffer += sizeof(UINT16);
660       break;
661     case TPM_ALG_NULL:
662       break;
663     default:
664       return EFI_INVALID_PARAMETER;
665     }
666     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme));
667     Buffer += sizeof(UINT16);
668     switch (Parameters->parameters.eccDetail.scheme.scheme) {
669     case TPM_ALG_ECDSA:
670       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg));
671       Buffer += sizeof(UINT16);
672       break;
673     case TPM_ALG_ECDAA:
674       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg));
675       Buffer += sizeof(UINT16);
676       break;
677     case TPM_ALG_ECSCHNORR:
678       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg));
679       Buffer += sizeof(UINT16);
680       break;
681     case TPM_ALG_ECDH:
682       break;
683     case TPM_ALG_NULL:
684       break;
685     default:
686       return EFI_INVALID_PARAMETER;
687     }
688     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID));
689     Buffer += sizeof(UINT16);
690     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme));
691     Buffer += sizeof(UINT16);
692     switch (Parameters->parameters.eccDetail.kdf.scheme) {
693     case TPM_ALG_MGF1:
694       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg));
695       Buffer += sizeof(UINT16);
696       break;
697     case TPM_ALG_KDF1_SP800_108:
698       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg));
699       Buffer += sizeof(UINT16);
700       break;
701     case TPM_ALG_KDF1_SP800_56a:
702       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg));
703       Buffer += sizeof(UINT16);
704       break;
705     case TPM_ALG_KDF2:
706       WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg));
707       Buffer += sizeof(UINT16);
708       break;
709     case TPM_ALG_NULL:
710       break;
711     default:
712       return EFI_INVALID_PARAMETER;
713     }
714     break;
715   default:
716     return EFI_INVALID_PARAMETER;
717   }
718 
719   SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
720   SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
721 
722   //
723   // send Tpm command
724   //
725   RecvBufferSize = sizeof (RecvBuffer);
726   Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
727   if (EFI_ERROR (Status)) {
728     return Status;
729   }
730 
731   if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
732     DEBUG ((EFI_D_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize));
733     return EFI_DEVICE_ERROR;
734   }
735   if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
736     DEBUG ((EFI_D_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
737     return EFI_UNSUPPORTED;
738   }
739 
740   return EFI_SUCCESS;
741 }
742