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
Tpm2GetCapability(IN TPM_CAP Capability,IN UINT32 Property,IN UINT32 PropertyCount,OUT TPMI_YES_NO * MoreData,OUT TPMS_CAPABILITY_DATA * CapabilityData)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
Tpm2GetCapabilityFamily(OUT CHAR8 * Family)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
Tpm2GetCapabilityManufactureID(OUT UINT32 * ManufactureId)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
Tpm2GetCapabilityFirmwareVersion(OUT UINT32 * FirmwareVersion1,OUT UINT32 * FirmwareVersion2)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
Tpm2GetCapabilityMaxCommandResponseSize(OUT UINT32 * MaxCommandSize,OUT UINT32 * MaxResponseSize)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
Tpm2GetCapabilitySupportedAlg(OUT TPML_ALG_PROPERTY * AlgList)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
Tpm2GetCapabilityLockoutCounter(OUT UINT32 * LockoutCounter)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
Tpm2GetCapabilityLockoutInterval(OUT UINT32 * LockoutInterval)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
Tpm2GetCapabilityInputBufferSize(OUT UINT32 * InputBufferSize)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
Tpm2GetCapabilityPcrs(OUT TPML_PCR_SELECTION * Pcrs)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
Tpm2GetCapabilitySupportedAndActivePcrs(OUT UINT32 * TpmHashAlgorithmBitmap,OUT UINT32 * ActivePcrBanks)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
Tpm2GetCapabilityAlgorithmSet(OUT UINT32 * AlgorithmSet)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
Tpm2GetCapabilityIsCommandImplemented(IN TPM_CC Command,OUT BOOLEAN * IsCmdImpl)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
Tpm2TestParms(IN TPMT_PUBLIC_PARMS * Parameters)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 }
890