summaryrefslogtreecommitdiffstats
path: root/src/tpm2/PropertyCap.c
blob: db7d679c594172d9dd3710926b83eab55c84a12d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/********************************************************************************/
/*										*/
/*		For accessing the TPM_CAP_TPM_PROPERTY values	  		*/
/*			     Written by Ken Goldman				*/
/*		       IBM Thomas J. Watson Research Center			*/
/*            $Id: PropertyCap.c 1519 2019-11-15 20:43:51Z kgoldman $		*/
/*										*/
/*  Licenses and Notices							*/
/*										*/
/*  1. Copyright Licenses:							*/
/*										*/
/*  - Trusted Computing Group (TCG) grants to the user of the source code in	*/
/*    this specification (the "Source Code") a worldwide, irrevocable, 		*/
/*    nonexclusive, royalty free, copyright license to reproduce, create 	*/
/*    derivative works, distribute, display and perform the Source Code and	*/
/*    derivative works thereof, and to grant others the rights granted herein.	*/
/*										*/
/*  - The TCG grants to the user of the other parts of the specification 	*/
/*    (other than the Source Code) the rights to reproduce, distribute, 	*/
/*    display, and perform the specification solely for the purpose of 		*/
/*    developing products based on such documents.				*/
/*										*/
/*  2. Source Code Distribution Conditions:					*/
/*										*/
/*  - Redistributions of Source Code must retain the above copyright licenses, 	*/
/*    this list of conditions and the following disclaimers.			*/
/*										*/
/*  - Redistributions in binary form must reproduce the above copyright 	*/
/*    licenses, this list of conditions	and the following disclaimers in the 	*/
/*    documentation and/or other materials provided with the distribution.	*/
/*										*/
/*  3. Disclaimers:								*/
/*										*/
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF	*/
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH	*/
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)	*/
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.		*/
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for 		*/
/*  information on specification licensing rights available through TCG 	*/
/*  membership agreements.							*/
/*										*/
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED 	*/
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR 	*/
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR 		*/
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY 		*/
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.		*/
/*										*/
/*  - Without limitation, TCG and its members and licensors disclaim all 	*/
/*    liability, including liability for infringement of any proprietary 	*/
/*    rights, relating to use of information in this specification and to the	*/
/*    implementation of this specification, and TCG disclaims all liability for	*/
/*    cost of procurement of substitute goods or services, lost profits, loss 	*/
/*    of use, loss of data or any incidental, consequential, direct, indirect, 	*/
/*    or special damages, whether under contract, tort, warranty or otherwise, 	*/
/*    arising in any way out of use or reliance upon this specification or any 	*/
/*    information herein.							*/
/*										*/
/*  (c) Copyright IBM Corp. and others, 2016 - 2019				*/
/*										*/
/********************************************************************************/

/* 9.14 PropertyCap.c */
/* 9.14.1 Description */
/* This file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values. */
/* 9.14.2 Includes */
#include "Tpm.h"

#define TPM_HAVE_TPM2_DECLARATIONS
#include "tpm_library_intern.h"  // libtpms added
/* 9.14.3 Functions */
/* 9.14.3.1 TPMPropertyIsDefined() */
/* This function accepts a property selection and, if so, sets value to the value of the
   property. */
/* All the fixed values are vendor dependent or determined by a platform-specific specification. The
   values in the table below are examples and should be changed by the vendor. */
/* Return Values Meaning */
/* TRUE referenced property exists and value set */
/* FALSE referenced property does not exist */
static BOOL
TPMPropertyIsDefined(
		     TPM_PT           property,      // IN: property
		     UINT32          *value          // OUT: property value
		     )
{
    switch(property)
	{
	  case TPM_PT_FAMILY_INDICATOR:
	    // from the title page of the specification
	    // For this specification, the value is "2.0".
	    *value = TPM_SPEC_FAMILY;
	    break;
	  case TPM_PT_LEVEL:
	    // from the title page of the specification
	    *value = TPM_SPEC_LEVEL;
	    break;
	  case TPM_PT_REVISION:
	    // from the title page of the specification
	    *value = TPM_SPEC_VERSION;
	    break;
	  case TPM_PT_DAY_OF_YEAR:
	    // computed from the date value on the title page of the specification
	    *value = TPM_SPEC_DAY_OF_YEAR;
	    break;
	  case TPM_PT_YEAR:
	    // from the title page of the specification
	    *value = TPM_SPEC_YEAR;
	    break;
	  case TPM_PT_MANUFACTURER:
	    // vendor ID unique to each TPM manufacturer
	    *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER);
	    break;
	  case TPM_PT_VENDOR_STRING_1:
	    // first four characters of the vendor ID string
	    *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1);
	    break;
	  case TPM_PT_VENDOR_STRING_2:
	    // second four characters of the vendor ID string
#ifdef VENDOR_STRING_2
	    *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2);
#else
	    *value = 0;
#endif
	    break;
	  case TPM_PT_VENDOR_STRING_3:
	    // third four characters of the vendor ID string
#ifdef VENDOR_STRING_3
	    *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3);
#else
	    *value = 0;
#endif
	    break;
	  case TPM_PT_VENDOR_STRING_4:
	    // fourth four characters of the vendor ID string
#ifdef VENDOR_STRING_4
	    *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4);
#else
	    *value = 0;
#endif
	    break;
	  case TPM_PT_VENDOR_TPM_TYPE:
	    // vendor-defined value indicating the TPM model
	    *value = 1;
	    break;
	  case TPM_PT_FIRMWARE_VERSION_1:
	    // more significant 32-bits of a vendor-specific value
	    *value = gp.firmwareV1;
	    break;
	  case TPM_PT_FIRMWARE_VERSION_2:
	    // less significant 32-bits of a vendor-specific value
	    *value = gp.firmwareV2;
	    break;
	  case TPM_PT_INPUT_BUFFER:
	    // maximum size of TPM2B_MAX_BUFFER
	    *value = MAX_DIGEST_BUFFER;
	    break;
	  case TPM_PT_HR_TRANSIENT_MIN:
	    // minimum number of transient objects that can be held in TPM
	    // RAM
	    *value = MAX_LOADED_OBJECTS;
	    break;
	  case TPM_PT_HR_PERSISTENT_MIN:
	    // minimum number of persistent objects that can be held in
	    // TPM NV memory
	    // In this implementation, there is no minimum number of
	    // persistent objects.
	    *value = MIN_EVICT_OBJECTS;
	    break;
	  case TPM_PT_HR_LOADED_MIN:
	    // minimum number of authorization sessions that can be held in
	    // TPM RAM
	    *value = MAX_LOADED_SESSIONS;
	    break;
	  case TPM_PT_ACTIVE_SESSIONS_MAX:
	    // number of authorization sessions that may be active at a time
	    *value = MAX_ACTIVE_SESSIONS;
	    break;
	  case TPM_PT_PCR_COUNT:
	    // number of PCR implemented
	    *value = IMPLEMENTATION_PCR;
	    break;
	  case TPM_PT_PCR_SELECT_MIN:
	    // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect
	    *value = PCR_SELECT_MIN;
	    break;
	  case TPM_PT_CONTEXT_GAP_MAX:
	    // maximum allowed difference (unsigned) between the contextID
	    // values of two saved session contexts
#if 0
	    *value = ((UINT32)1 << (sizeof(CONTEXT_SLOT) * 8)) - 1;
#endif
	    *value = s_ContextSlotMask; // libtpms added; the mask is either 0xff (old state) or 0xffff
	    break;
	  case TPM_PT_NV_COUNTERS_MAX:
	    // maximum number of NV indexes that are allowed to have the
	    // TPMA_NV_COUNTER attribute SET
	    // In this implementation, there is no limitation on the number
	    // of counters, except for the size of the NV Index memory.
	    *value = 0;
	    break;
	  case TPM_PT_NV_INDEX_MAX:
	    // maximum size of an NV index data area
	    *value = MAX_NV_INDEX_SIZE;
	    break;
	  case TPM_PT_MEMORY:
	    // a TPMA_MEMORY indicating the memory management method for the TPM
	      {
		  union
		  {
		      TPMA_MEMORY     att;
		      UINT32          u32;
		  } attributes = { TPMA_ZERO_INITIALIZER() };
		  SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, sharedNV);
		  SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, objectCopiedToRam);
		  // Note: For a LSb0 machine, the bits in a bit field are in the correct
		  // order even if the machine is MSB0. For a MSb0 machine, a TPMA will
		  // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will
		  // NO) so the bits are manipulated correctly.
		  *value = attributes.u32;
		  break;
	      }
	  case TPM_PT_CLOCK_UPDATE:
	    // interval, in seconds, between updates to the copy of
	    // TPMS_TIME_INFO .clock in NV
	    *value = (1 << NV_CLOCK_UPDATE_INTERVAL);
	    break;
	  case TPM_PT_CONTEXT_HASH:
	    // algorithm used for the integrity hash on saved contexts and
	    // for digesting the fuData of TPM2_FirmwareRead()
	    *value = CONTEXT_INTEGRITY_HASH_ALG;
	    break;
	  case TPM_PT_CONTEXT_SYM:
	    // algorithm used for encryption of saved contexts
	    *value = CONTEXT_ENCRYPT_ALG;
	    break;
	  case TPM_PT_CONTEXT_SYM_SIZE:
	    // size of the key used for encryption of saved contexts
	    *value = CONTEXT_ENCRYPT_KEY_BITS;
	    break;
	  case TPM_PT_ORDERLY_COUNT:
	    // maximum difference between the volatile and non-volatile
	    // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET
	    *value = MAX_ORDERLY_COUNT;
	    break;
	  case TPM_PT_MAX_COMMAND_SIZE:
	    // maximum value for 'commandSize'
	    *value = MAX_COMMAND_SIZE;
	    break;
	  case TPM_PT_MAX_RESPONSE_SIZE:
	    // maximum value for 'responseSize'
	    *value = MAX_RESPONSE_SIZE;
	    break;
	  case TPM_PT_MAX_DIGEST:
	    // maximum size of a digest that can be produced by the TPM
	    *value = sizeof(TPMU_HA);
	    break;
	  case TPM_PT_MAX_OBJECT_CONTEXT:
	    // Header has 'sequence', 'handle' and 'hierarchy'
#define SIZE_OF_CONTEXT_HEADER						\
	    sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY)
#define SIZE_OF_CONTEXT_INTEGRITY (sizeof(UINT16) + CONTEXT_INTEGRITY_HASH_SIZE)
#define SIZE_OF_FINGERPRINT     sizeof(UINT64)
#define SIZE_OF_CONTEXT_BLOB_OVERHEAD					\
	    (sizeof(UINT16)  + SIZE_OF_CONTEXT_INTEGRITY + SIZE_OF_FINGERPRINT)
#define SIZE_OF_CONTEXT_OVERHEAD					\
	    (SIZE_OF_CONTEXT_HEADER + SIZE_OF_CONTEXT_BLOB_OVERHEAD)
#if 0
	    // maximum size of a TPMS_CONTEXT that will be returned by
	    // TPM2_ContextSave for object context
	    *value = 0;
	    // adding sequence, saved handle and hierarchy
	    *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +
		      sizeof(TPMI_RH_HIERARCHY);
	    // add size field in TPM2B_CONTEXT
	    *value += sizeof(UINT16);
	    // add integrity hash size
	    *value += sizeof(UINT16) +
		      CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
	    // Add fingerprint size, which is the same as sequence size
	    *value += sizeof(UINT64);
	    // Add OBJECT structure size
	    *value += sizeof(OBJECT);
#else
	    // the maximum size of a TPMS_CONTEXT that will be returned by
	    // TPM2_ContextSave for object context
	    *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(OBJECT);
#endif
	    break;
	  case TPM_PT_MAX_SESSION_CONTEXT:
#if 0
	    // the maximum size of a TPMS_CONTEXT that will be returned by
	    // TPM2_ContextSave for object context
	    *value = 0;
	    // adding sequence, saved handle and hierarchy
	    *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +
		      sizeof(TPMI_RH_HIERARCHY);
	    // Add size field in TPM2B_CONTEXT
	    *value += sizeof(UINT16);
	    // Add integrity hash size
	    *value += sizeof(UINT16) +
		      CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
	    // Add fingerprint size, which is the same as sequence size
	    *value += sizeof(UINT64);
	    // Add SESSION structure size
	    *value += sizeof(SESSION);
#else
	    // the maximum size of a TPMS_CONTEXT that will be returned by
	    // TPM2_ContextSave for object context
	    *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(SESSION);
#endif
	    break;
	  case TPM_PT_PS_FAMILY_INDICATOR:
	    // platform specific values for the TPM_PT_PS parameters from
	    // the relevant platform-specific specification
	    // In this reference implementation, all of these values are 0.
	    *value = PLATFORM_FAMILY;
	    break;
	  case TPM_PT_PS_LEVEL:
	    // level of the platform-specific specification
	    *value = PLATFORM_LEVEL;
	    break;
	  case TPM_PT_PS_REVISION:
	    // specification Revision times 100 for the platform-specific
	    // specification
	    *value = PLATFORM_VERSION;
	    break;
	  case TPM_PT_PS_DAY_OF_YEAR:
	    // platform-specific specification day of year using TCG calendar
	    *value = PLATFORM_DAY_OF_YEAR;
	    break;
	  case TPM_PT_PS_YEAR:
	    // platform-specific specification year using the CE
	    *value = PLATFORM_YEAR;
	    break;
	  case TPM_PT_SPLIT_MAX:
	    // number of split signing operations supported by the TPM
	    *value = 0;
#if ALG_ECC
	    *value = sizeof(gr.commitArray) * 8;
#endif
	    break;
	  case TPM_PT_TOTAL_COMMANDS:
	    // total number of commands implemented in the TPM
	    // Since the reference implementation does not have any
	    // vendor-defined commands, this will be the same as the
	    // number of library commands.
	      {
#if COMPRESSED_LISTS
		  (*value) = COMMAND_COUNT;
#else
		  COMMAND_INDEX       commandIndex;
		  *value = 0;
		  // scan all implemented commands
		  for(commandIndex = GetClosestCommandIndex(0);
		      commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
		      commandIndex = GetNextCommandIndex(commandIndex))
		      {
			  (*value)++;     // count of all implemented
		      }
#endif
		  break;
	      }
	  case TPM_PT_LIBRARY_COMMANDS:
	    // number of commands from the TPM library that are implemented
	      {
#if COMPRESSED_LISTS
		  *value = LIBRARY_COMMAND_ARRAY_SIZE;
#else
		  COMMAND_INDEX       commandIndex;
		  *value = 0;
		  // scan all implemented commands
		  for(commandIndex = GetClosestCommandIndex(0);
		      commandIndex < LIBRARY_COMMAND_ARRAY_SIZE;
		      commandIndex = GetNextCommandIndex(commandIndex))
		      {
			  (*value)++;
		      }
#endif
		  break;
	      }
	  case TPM_PT_VENDOR_COMMANDS:
	    // number of vendor commands that are implemented
	    *value = VENDOR_COMMAND_ARRAY_SIZE;
	    break;
	  case TPM_PT_NV_BUFFER_MAX:
	    // Maximum data size in an NV write command
	    *value = MAX_NV_BUFFER_SIZE;
	    break;
	  case TPM_PT_MODES:
#if FIPS_COMPLIANT
	    *value = 1;
#else
	    *value = 0;
#endif
	    break;
	  case TPM_PT_MAX_CAP_BUFFER:
	    *value = MAX_CAP_BUFFER;
	    break;
	    // Start of variable commands
	  case TPM_PT_PERMANENT:
	    // TPMA_PERMANENT
	      {
		  union {
		      TPMA_PERMANENT      attr;
		      UINT32              u32;
		  } flags = { TPMA_ZERO_INITIALIZER() };
		  if(gp.ownerAuth.t.size != 0)
		      SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, ownerAuthSet);
		  if(gp.endorsementAuth.t.size != 0)
		      SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, endorsementAuthSet);
		  if(gp.lockoutAuth.t.size != 0)
		      SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, lockoutAuthSet);
		  if(gp.disableClear)
		      SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, disableClear);
		  if(gp.failedTries >= gp.maxTries)
		      SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, inLockout);
		  // In this implementation, EPS is always generated by TPM
		  SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, tpmGeneratedEPS);
		  // Note: For a LSb0 machine, the bits in a bit field are in the correct
		  // order even if the machine is MSB0. For a MSb0 machine, a TPMA will
		  // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will
		  // be NO ) so the bits are manipulate correctly.
		  *value = flags.u32;
		  break;
	      }
	  case TPM_PT_STARTUP_CLEAR:
	    // TPMA_STARTUP_CLEAR
	      {
		  union {
		      TPMA_STARTUP_CLEAR  attr;
		      UINT32              u32;
		  } flags =  { TPMA_ZERO_INITIALIZER() };
		  //
		  if(g_phEnable)
		      SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnable);
		  if(gc.shEnable)
		      SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, shEnable);
		  if(gc.ehEnable)
		      SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, ehEnable);
		  if(gc.phEnableNV)
		      SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnableNV);
		  if(g_prevOrderlyState != SU_NONE_VALUE)
		      SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, orderly);
		  // Note: For a LSb0 machine, the bits in a bit field are in the correct
		  // order even if the machine is MSB0. For a MSb0 machine, a TPMA will
		  // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will
		  // be NO) so the bits are manipulate correctly.
		  *value = flags.u32;
		  break;
	      }
	  case TPM_PT_HR_NV_INDEX:
	    // number of NV indexes currently defined
	    *value = NvCapGetIndexNumber();
	    break;
	  case TPM_PT_HR_LOADED:
	    // number of authorization sessions currently loaded into TPM
	    // RAM
	    *value = SessionCapGetLoadedNumber();
	    break;
	  case TPM_PT_HR_LOADED_AVAIL:
	    // number of additional authorization sessions, of any type,
	    // that could be loaded into TPM RAM
	    *value = SessionCapGetLoadedAvail();
	    break;
	  case TPM_PT_HR_ACTIVE:
	    // number of active authorization sessions currently being
	    // tracked by the TPM
	    *value = SessionCapGetActiveNumber();
	    break;
	  case TPM_PT_HR_ACTIVE_AVAIL:
	    // number of additional authorization sessions, of any type,
	    // that could be created
	    *value = SessionCapGetActiveAvail();
	    break;
	  case TPM_PT_HR_TRANSIENT_AVAIL:
	    // estimate of the number of additional transient objects that
	    // could be loaded into TPM RAM
	    *value = ObjectCapGetTransientAvail();
	    break;
	  case TPM_PT_HR_PERSISTENT:
	    // number of persistent objects currently loaded into TPM
	    // NV memory
	    *value = NvCapGetPersistentNumber();
	    break;
	  case TPM_PT_HR_PERSISTENT_AVAIL:
	    // number of additional persistent objects that could be loaded
	    // into NV memory
	    *value = NvCapGetPersistentAvail();
	    break;
	  case TPM_PT_NV_COUNTERS:
	    // number of defined NV indexes that have NV TPMA_NV_COUNTER
	    // attribute SET
	    *value = NvCapGetCounterNumber();
	    break;
	  case TPM_PT_NV_COUNTERS_AVAIL:
	    // number of additional NV indexes that can be defined with their
	    // TPMA_NV_COUNTER attribute SET
	    *value = NvCapGetCounterAvail();
	    break;
	  case TPM_PT_ALGORITHM_SET:
	    // region code for the TPM
	    *value = gp.algorithmSet;
	    break;
	  case TPM_PT_LOADED_CURVES:
#if ALG_ECC
	    // number of loaded ECC curves
	    *value = ECC_CURVE_COUNT;
#else // ALG_ECC
	    *value = 0;
#endif // ALG_ECC
	    break;
	  case TPM_PT_LOCKOUT_COUNTER:
	    // current value of the lockout counter
	    *value = gp.failedTries;
	    break;
	  case TPM_PT_MAX_AUTH_FAIL:
	    // number of authorization failures before DA lockout is invoked
	    *value = gp.maxTries;
	    break;
	  case TPM_PT_LOCKOUT_INTERVAL:
	    // number of seconds before the value reported by
	    // TPM_PT_LOCKOUT_COUNTER is decremented
	    *value = gp.recoveryTime;
	    break;
	  case TPM_PT_LOCKOUT_RECOVERY:
	    // number of seconds after a lockoutAuth failure before use of
	    // lockoutAuth may be attempted again
	    *value = gp.lockoutRecovery;
	    break;
	  case TPM_PT_NV_WRITE_RECOVERY:
	    // number of milliseconds before the TPM will accept another command
	    // that will modify NV.
	    // This should make a call to the platform code that is doing rate
	    // limiting of NV. Rate limiting is not implemented in the reference
	    // code so no call is made.
	    *value = 0;
	    break;
	  case TPM_PT_AUDIT_COUNTER_0:
	    // high-order 32 bits of the command audit counter
	    *value = (UINT32)(gp.auditCounter >> 32);
	    break;
	  case TPM_PT_AUDIT_COUNTER_1:
	    // low-order 32 bits of the command audit counter
	    *value = (UINT32)(gp.auditCounter);
	    break;
	  default:
	    // property is not defined
	    return FALSE;
	    break;
	}
    return TRUE;
}
/* 9.14.3.2 TPMCapGetProperties() */
/* This function is used to get the TPM_PT values. The search of properties will start at property
   and continue until propertyList has as many values as will fit, or the last property has been
   reported, or the list has as many values as requested in count. */
/* Return Values Meaning */
/* YES more properties are available */
/* NO no more properties to be reported */
TPMI_YES_NO
TPMCapGetProperties(
		    TPM_PT                       property,      // IN: the starting TPM property
		    UINT32                       count,         // IN: maximum number of returned
		    //     properties
		    TPML_TAGGED_TPM_PROPERTY    *propertyList   // OUT: property list
		    )
{
    TPMI_YES_NO     more = NO;
    UINT32          i;
    UINT32          nextGroup;
    // initialize output property list
    propertyList->count = 0;
    // maximum count of properties we may return is MAX_PCR_PROPERTIES
    if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES;
    // if property is less than PT_FIXED, start from PT_FIXED
    if(property < PT_FIXED)
	property = PT_FIXED;
    // There is only the fixed and variable groups with the variable group coming
    // last
    if(property >= (PT_VAR + PT_GROUP))
	return more;
    // Don't read past the end of the selected group
    nextGroup = ((property / PT_GROUP) * PT_GROUP) + PT_GROUP;
    // Scan through the TPM properties of the requested group.
    for(i = property; i < nextGroup; i++)
	{
	    UINT32          value;
	    // if we have hit the end of the group, quit
	    if(i != property && ((i % PT_GROUP) == 0))
		break;
	    if(TPMPropertyIsDefined((TPM_PT)i, &value))
		{
		    if(propertyList->count < count)
			{
			    // If the list is not full, add this property
			    propertyList->tpmProperty[propertyList->count].property =
				(TPM_PT)i;
			    propertyList->tpmProperty[propertyList->count].value = value;
			    propertyList->count++;
			}
		    else
			{
			    // If the return list is full but there are more properties
			    // available, set the indication and exit the loop.
			    more = YES;
			    break;
			}
		}
	}
    return more;
}