Coverage Report

Created: 2026-06-17 06:13

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