aboutsummaryrefslogtreecommitdiff
path: root/PropertyCap.c
blob: c05cc033f344994db12dabe87d844ee05a6fd3c3 (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
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 4: Supporting Routines
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include "InternalRoutines.h"
//
//
//          Functions
//
//         PCRGetProperty()
//
//     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 Value                      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
           *value = (1 << (sizeof(CONTEXT_SLOT) * 8)) - 1;
            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
        {
            TPMA_MEMORY         attributes = {0};
            attributes.sharedNV = SET;
            attributes.objectCopiedToRam = SET;
             // Note: Different compilers may require a different method to cast
             // a bit field structure to a UINT32.
             memcpy(value, &attributes, sizeof(UINT32));
             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:
            // 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) +
                        CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
              // Add fingerprint size, which is the same as sequence size
              *value += sizeof(UINT64);
            // Add OBJECT structure size
            *value += sizeof(OBJECT);
            break;
        case TPM_PT_MAX_SESSION_CONTEXT:
            // 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) +
                        CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
              // Add fingerprint size, which is the same as sequence size
              *value += sizeof(UINT64);
           // Add SESSION structure size
           *value += sizeof(SESSION);
           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 = 0;
           break;
       case TPM_PT_PS_LEVEL:
           // level of the platform-specific specification
           *value = 0;
           break;
       case TPM_PT_PS_REVISION:
           // specification Revision times 100 for the platform-specific
           // specification
           *value = 0;
           break;
       case TPM_PT_PS_DAY_OF_YEAR:
           // platform-specific specification day of year using TCG calendar
           *value = 0;
           break;
       case TPM_PT_PS_YEAR:
           // platform-specific specification year using the CE
           *value = 0;
           break;
       case TPM_PT_SPLIT_MAX:
           // number of split signing operations supported by the TPM
           *value = 0;
   #ifdef TPM_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.
        {
             UINT32 i;
             *value = 0;
             // calculate implemented command numbers
             for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
             {
                 if(CommandIsImplemented(i)) (*value)++;
             }
             break;
        }
        case TPM_PT_LIBRARY_COMMANDS:
            // number of commands from the TPM library that are implemented
        {
            UINT32 i;
            *value = 0;
             // calculate implemented command numbers
             for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
             {
                 if(CommandIsImplemented(i)) (*value)++;
             }
             break;
        }
        case TPM_PT_VENDOR_COMMANDS:
            // number of vendor commands that are implemented
            *value = 0;
            break;
        case TPM_PT_PERMANENT:
            // TPMA_PERMANENT
        {
            TPMA_PERMANENT           flags = {0};
            if(gp.ownerAuth.t.size != 0)
                flags.ownerAuthSet = SET;
            if(gp.endorsementAuth.t.size != 0)
                flags.endorsementAuthSet = SET;
            if(gp.lockoutAuth.t.size != 0)
                flags.lockoutAuthSet = SET;
            if(gp.disableClear)
                flags.disableClear = SET;
            if(gp.failedTries >= gp.maxTries)
                flags.inLockout = SET;
            // In this implementation, EPS is always generated by TPM
            flags.tpmGeneratedEPS = SET;
             // Note: Different compilers may require a different method to cast
             // a bit field structure to a UINT32.
             memcpy(value, &flags, sizeof(UINT32));
             break;
        }
        case TPM_PT_STARTUP_CLEAR:
            // TPMA_STARTUP_CLEAR
        {
            TPMA_STARTUP_CLEAR      flags = {0};
            if(g_phEnable)
                flags.phEnable = SET;
            if(gc.shEnable)
                flags.shEnable = SET;
            if(gc.ehEnable)
                flags.ehEnable = SET;
            if(gc.phEnableNV)
                flags.phEnableNV = SET;
            if(g_prevOrderlyState != SHUTDOWN_NONE)
                  flags.orderly = SET;
              // Note: Different compilers may require a different method to cast
              // a bit field structure to a UINT32.
              memcpy(value, &flags, sizeof(UINT32));
              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:
   #ifdef TPM_ALG_ECC
           // number of loaded ECC curves
           *value = CryptCapGetEccCurveNumber();
   #else // TPM_ALG_ECC
             *value = 0;
     #endif // TPM_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_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;
}
//
//
//           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 Value                      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
                                                             //     propertie
     TPML_TAGGED_TPM_PROPERTY           *propertyList        // OUT: property list
     )
{
     TPMI_YES_NO        more = NO;
     UINT32             i;
     // 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;
      // Scan through the TPM properties of the requested group.
      // The size of TPM property group is PT_GROUP * 2 for fix and
      // variable groups.
      for(i = property; i <= PT_FIXED + PT_GROUP * 2; i++)
      {
          UINT32          value;
          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;
}