• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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