1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 4: Supporting Routines
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 //
10 //
11 //          Functions
12 //
13 //         PCRGetProperty()
14 //
15 //     This function accepts a property selection and, if so, sets value to the value of the property.
16 //     All the fixed values are vendor dependent or determined by a platform-specific specification. The values
17 //     in the table below are examples and should be changed by the vendor.
18 //
19 //     Return Value                      Meaning
20 //
21 //     TRUE                              referenced property exists and value set
22 //     FALSE                             referenced property does not exist
23 //
24 static BOOL
TPMPropertyIsDefined(TPM_PT property,UINT32 * value)25 TPMPropertyIsDefined(
26     TPM_PT               property,           // IN: property
27     UINT32              *value               // OUT: property value
28     )
29 {
30    switch(property)
31    {
32        case TPM_PT_FAMILY_INDICATOR:
33            // from the title page of the specification
34            // For this specification, the value is "2.0".
35            *value = TPM_SPEC_FAMILY;
36            break;
37        case TPM_PT_LEVEL:
38            // from the title page of the specification
39            *value = TPM_SPEC_LEVEL;
40            break;
41        case TPM_PT_REVISION:
42            // from the title page of the specification
43            *value = TPM_SPEC_VERSION;
44            break;
45        case TPM_PT_DAY_OF_YEAR:
46            // computed from the date value on the title page of the specification
47            *value = TPM_SPEC_DAY_OF_YEAR;
48            break;
49        case TPM_PT_YEAR:
50            // from the title page of the specification
51            *value = TPM_SPEC_YEAR;
52            break;
53        case TPM_PT_MANUFACTURER:
54            // vendor ID unique to each TPM manufacturer
55            *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER);
56            break;
57        case TPM_PT_VENDOR_STRING_1:
58            // first four characters of the vendor ID string
59            *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1);
60            break;
61        case TPM_PT_VENDOR_STRING_2:
62            // second four characters of the vendor ID string
63 #ifdef VENDOR_STRING_2
64            *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2);
65 #else
66            *value = 0;
67 #endif
68            break;
69        case TPM_PT_VENDOR_STRING_3:
70            // third four characters of the vendor ID string
71 #ifdef VENDOR_STRING_3
72            *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3);
73 #else
74            *value = 0;
75 #endif
76            break;
77        case TPM_PT_VENDOR_STRING_4:
78            // fourth four characters of the vendor ID string
79 #ifdef VENDOR_STRING_4
80            *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4);
81 #else
82            *value = 0;
83 #endif
84            break;
85        case TPM_PT_VENDOR_TPM_TYPE:
86            // vendor-defined value indicating the TPM model
87            *value = 1;
88            break;
89        case TPM_PT_FIRMWARE_VERSION_1:
90            // more significant 32-bits of a vendor-specific value
91            *value = gp.firmwareV1;
92            break;
93        case TPM_PT_FIRMWARE_VERSION_2:
94            // less significant 32-bits of a vendor-specific value
95            *value = gp.firmwareV2;
96            break;
97        case TPM_PT_INPUT_BUFFER:
98            // maximum size of TPM2B_MAX_BUFFER
99            *value = MAX_DIGEST_BUFFER;
100            break;
101        case TPM_PT_HR_TRANSIENT_MIN:
102            // minimum number of transient objects that can be held in TPM
103            // RAM
104            *value = MAX_LOADED_OBJECTS;
105            break;
106        case TPM_PT_HR_PERSISTENT_MIN:
107            // minimum number of persistent objects that can be held in
108            // TPM NV memory
109            // In this implementation, there is no minimum number of
110            // persistent objects.
111            *value = MIN_EVICT_OBJECTS;
112            break;
113        case TPM_PT_HR_LOADED_MIN:
114            // minimum number of authorization sessions that can be held in
115            // TPM RAM
116            *value = MAX_LOADED_SESSIONS;
117            break;
118        case TPM_PT_ACTIVE_SESSIONS_MAX:
119            // number of authorization sessions that may be active at a time
120            *value = MAX_ACTIVE_SESSIONS;
121            break;
122        case TPM_PT_PCR_COUNT:
123            // number of PCR implemented
124            *value = IMPLEMENTATION_PCR;
125            break;
126        case TPM_PT_PCR_SELECT_MIN:
127            // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect
128            *value = PCR_SELECT_MIN;
129            break;
130        case TPM_PT_CONTEXT_GAP_MAX:
131            // maximum allowed difference (unsigned) between the contextID
132            // values of two saved session contexts
133            *value = (1 << (sizeof(CONTEXT_SLOT) * 8)) - 1;
134             break;
135         case TPM_PT_NV_COUNTERS_MAX:
136             // maximum number of NV indexes that are allowed to have the
137             // TPMA_NV_COUNTER attribute SET
138             // In this implementation, there is no limitation on the number
139             // of counters, except for the size of the NV Index memory.
140             *value = 0;
141             break;
142         case TPM_PT_NV_INDEX_MAX:
143             // maximum size of an NV index data area
144             *value = MAX_NV_INDEX_SIZE;
145             break;
146         case TPM_PT_MEMORY:
147             // a TPMA_MEMORY indicating the memory management method for the TPM
148         {
149             TPMA_MEMORY         attributes = {0};
150             attributes.sharedNV = SET;
151             attributes.objectCopiedToRam = SET;
152              // Note: Different compilers may require a different method to cast
153              // a bit field structure to a UINT32.
154              memcpy(value, &attributes, sizeof(UINT32));
155              break;
156         }
157         case TPM_PT_CLOCK_UPDATE:
158             // interval, in seconds, between updates to the copy of
159             // TPMS_TIME_INFO .clock in NV
160             *value = (1 << NV_CLOCK_UPDATE_INTERVAL);
161             break;
162         case TPM_PT_CONTEXT_HASH:
163             // algorithm used for the integrity hash on saved contexts and
164             // for digesting the fuData of TPM2_FirmwareRead()
165             *value = CONTEXT_INTEGRITY_HASH_ALG;
166             break;
167         case TPM_PT_CONTEXT_SYM:
168             // algorithm used for encryption of saved contexts
169             *value = CONTEXT_ENCRYPT_ALG;
170             break;
171         case TPM_PT_CONTEXT_SYM_SIZE:
172             // size of the key used for encryption of saved contexts
173             *value = CONTEXT_ENCRYPT_KEY_BITS;
174             break;
175         case TPM_PT_ORDERLY_COUNT:
176             // maximum difference between the volatile and non-volatile
177             // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET
178             *value = MAX_ORDERLY_COUNT;
179             break;
180         case TPM_PT_MAX_COMMAND_SIZE:
181             // maximum value for 'commandSize'
182             *value = MAX_COMMAND_SIZE;
183             break;
184         case TPM_PT_MAX_RESPONSE_SIZE:
185             // maximum value for 'responseSize'
186             *value = MAX_RESPONSE_SIZE;
187             break;
188         case TPM_PT_MAX_DIGEST:
189             // maximum size of a digest that can be produced by the TPM
190             *value = sizeof(TPMU_HA);
191             break;
192         case TPM_PT_MAX_OBJECT_CONTEXT:
193             // maximum size of a TPMS_CONTEXT that will be returned by
194             // TPM2_ContextSave for object context
195             *value = 0;
196              // adding sequence, saved handle and hierarchy
197              *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +
198                         sizeof(TPMI_RH_HIERARCHY);
199               // add size field in TPM2B_CONTEXT
200               *value += sizeof(UINT16);
201               // add integrity hash size
202               *value += sizeof(UINT16) +
203                         CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
204               // Add fingerprint size, which is the same as sequence size
205               *value += sizeof(UINT64);
206             // Add OBJECT structure size
207             *value += sizeof(OBJECT);
208             break;
209         case TPM_PT_MAX_SESSION_CONTEXT:
210             // the maximum size of a TPMS_CONTEXT that will be returned by
211             // TPM2_ContextSave for object context
212             *value = 0;
213               // adding sequence, saved handle and hierarchy
214               *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) +
215                         sizeof(TPMI_RH_HIERARCHY);
216               // Add size field in TPM2B_CONTEXT
217               *value += sizeof(UINT16);
218               // Add integrity hash size
219               *value += sizeof(UINT16) +
220                         CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
221               // Add fingerprint size, which is the same as sequence size
222               *value += sizeof(UINT64);
223            // Add SESSION structure size
224            *value += sizeof(SESSION);
225            break;
226        case TPM_PT_PS_FAMILY_INDICATOR:
227            // platform specific values for the TPM_PT_PS parameters from
228            // the relevant platform-specific specification
229            // In this reference implementation, all of these values are 0.
230            *value = 0;
231            break;
232        case TPM_PT_PS_LEVEL:
233            // level of the platform-specific specification
234            *value = 0;
235            break;
236        case TPM_PT_PS_REVISION:
237            // specification Revision times 100 for the platform-specific
238            // specification
239            *value = 0;
240            break;
241        case TPM_PT_PS_DAY_OF_YEAR:
242            // platform-specific specification day of year using TCG calendar
243            *value = 0;
244            break;
245        case TPM_PT_PS_YEAR:
246            // platform-specific specification year using the CE
247            *value = 0;
248            break;
249        case TPM_PT_SPLIT_MAX:
250            // number of split signing operations supported by the TPM
251            *value = 0;
252    #ifdef TPM_ALG_ECC
253            *value = sizeof(gr.commitArray) * 8;
254    #endif
255            break;
256        case TPM_PT_TOTAL_COMMANDS:
257            // total number of commands implemented in the TPM
258              // Since the reference implementation does not have any
259              // vendor-defined commands, this will be the same as the
260              // number of library commands.
261         {
262              UINT32 i;
263              *value = 0;
264              // calculate implemented command numbers
265              for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
266              {
267                  if(CommandIsImplemented(i)) (*value)++;
268              }
269              break;
270         }
271         case TPM_PT_LIBRARY_COMMANDS:
272             // number of commands from the TPM library that are implemented
273         {
274             UINT32 i;
275             *value = 0;
276              // calculate implemented command numbers
277              for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
278              {
279                  if(CommandIsImplemented(i)) (*value)++;
280              }
281              break;
282         }
283         case TPM_PT_VENDOR_COMMANDS:
284             // number of vendor commands that are implemented
285             *value = 0;
286             break;
287         case TPM_PT_PERMANENT:
288             // TPMA_PERMANENT
289         {
290             TPMA_PERMANENT           flags = {0};
291             if(gp.ownerAuth.t.size != 0)
292                 flags.ownerAuthSet = SET;
293             if(gp.endorsementAuth.t.size != 0)
294                 flags.endorsementAuthSet = SET;
295             if(gp.lockoutAuth.t.size != 0)
296                 flags.lockoutAuthSet = SET;
297             if(gp.disableClear)
298                 flags.disableClear = SET;
299             if(gp.failedTries >= gp.maxTries)
300                 flags.inLockout = SET;
301             // In this implementation, EPS is always generated by TPM
302             flags.tpmGeneratedEPS = SET;
303              // Note: Different compilers may require a different method to cast
304              // a bit field structure to a UINT32.
305              memcpy(value, &flags, sizeof(UINT32));
306              break;
307         }
308         case TPM_PT_STARTUP_CLEAR:
309             // TPMA_STARTUP_CLEAR
310         {
311             TPMA_STARTUP_CLEAR      flags = {0};
312             if(g_phEnable)
313                 flags.phEnable = SET;
314             if(gc.shEnable)
315                 flags.shEnable = SET;
316             if(gc.ehEnable)
317                 flags.ehEnable = SET;
318             if(gc.phEnableNV)
319                 flags.phEnableNV = SET;
320             if(g_prevOrderlyState != SHUTDOWN_NONE)
321                   flags.orderly = SET;
322               // Note: Different compilers may require a different method to cast
323               // a bit field structure to a UINT32.
324               memcpy(value, &flags, sizeof(UINT32));
325               break;
326         }
327         case TPM_PT_HR_NV_INDEX:
328             // number of NV indexes currently defined
329             *value = NvCapGetIndexNumber();
330             break;
331         case TPM_PT_HR_LOADED:
332             // number of authorization sessions currently loaded into TPM
333             // RAM
334             *value = SessionCapGetLoadedNumber();
335             break;
336         case TPM_PT_HR_LOADED_AVAIL:
337             // number of additional authorization sessions, of any type,
338             // that could be loaded into TPM RAM
339             *value = SessionCapGetLoadedAvail();
340             break;
341         case TPM_PT_HR_ACTIVE:
342             // number of active authorization sessions currently being
343             // tracked by the TPM
344             *value = SessionCapGetActiveNumber();
345             break;
346         case TPM_PT_HR_ACTIVE_AVAIL:
347             // number of additional authorization sessions, of any type,
348             // that could be created
349             *value = SessionCapGetActiveAvail();
350             break;
351         case TPM_PT_HR_TRANSIENT_AVAIL:
352             // estimate of the number of additional transient objects that
353             // could be loaded into TPM RAM
354             *value = ObjectCapGetTransientAvail();
355             break;
356         case TPM_PT_HR_PERSISTENT:
357             // number of persistent objects currently loaded into TPM
358             // NV memory
359             *value = NvCapGetPersistentNumber();
360             break;
361         case TPM_PT_HR_PERSISTENT_AVAIL:
362             // number of additional persistent objects that could be loaded
363             // into NV memory
364             *value = NvCapGetPersistentAvail();
365             break;
366         case TPM_PT_NV_COUNTERS:
367             // number of defined NV indexes that have NV TPMA_NV_COUNTER
368             // attribute SET
369             *value = NvCapGetCounterNumber();
370             break;
371         case TPM_PT_NV_COUNTERS_AVAIL:
372             // number of additional NV indexes that can be defined with their
373             // TPMA_NV_COUNTER attribute SET
374             *value = NvCapGetCounterAvail();
375             break;
376         case TPM_PT_ALGORITHM_SET:
377             // region code for the TPM
378             *value = gp.algorithmSet;
379             break;
380        case TPM_PT_LOADED_CURVES:
381    #ifdef TPM_ALG_ECC
382            // number of loaded ECC curves
383            *value = CryptCapGetEccCurveNumber();
384    #else // TPM_ALG_ECC
385              *value = 0;
386      #endif // TPM_ALG_ECC
387              break;
388           case TPM_PT_LOCKOUT_COUNTER:
389               // current value of the lockout counter
390               *value = gp.failedTries;
391               break;
392           case TPM_PT_MAX_AUTH_FAIL:
393               // number of authorization failures before DA lockout is invoked
394               *value = gp.maxTries;
395               break;
396           case TPM_PT_LOCKOUT_INTERVAL:
397               // number of seconds before the value reported by
398               // TPM_PT_LOCKOUT_COUNTER is decremented
399               *value = gp.recoveryTime;
400               break;
401           case TPM_PT_LOCKOUT_RECOVERY:
402               // number of seconds after a lockoutAuth failure before use of
403               // lockoutAuth may be attempted again
404               *value = gp.lockoutRecovery;
405               break;
406           case TPM_PT_AUDIT_COUNTER_0:
407               // high-order 32 bits of the command audit counter
408               *value = (UINT32) (gp.auditCounter >> 32);
409               break;
410           case TPM_PT_AUDIT_COUNTER_1:
411               // low-order 32 bits of the command audit counter
412               *value = (UINT32) (gp.auditCounter);
413               break;
414           default:
415               // property is not defined
416               return FALSE;
417               break;
418      }
419      return TRUE;
420 }
421 //
422 //
423 //           TPMCapGetProperties()
424 //
425 //      This function is used to get the TPM_PT values. The search of properties will start at property and
426 //      continue until propertyList has as many values as will fit, or the last property has been reported, or the list
427 //      has as many values as requested in count.
428 //
429 //      Return Value                      Meaning
430 //
431 //      YES                               more properties are available
432 //      NO                                no more properties to be reported
433 //
434 TPMI_YES_NO
TPMCapGetProperties(TPM_PT property,UINT32 count,TPML_TAGGED_TPM_PROPERTY * propertyList)435 TPMCapGetProperties(
436      TPM_PT                              property,           // IN: the starting TPM property
437      UINT32                              count,              // IN: maximum number of returned
438                                                              //     propertie
439      TPML_TAGGED_TPM_PROPERTY           *propertyList        // OUT: property list
440      )
441 {
442      TPMI_YES_NO        more = NO;
443      UINT32             i;
444      // initialize output property list
445      propertyList->count = 0;
446       // maximum count of properties we may return is MAX_PCR_PROPERTIES
447       if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES;
448       // If property is less than PT_FIXED, start from PT_FIXED.
449       if(property < PT_FIXED) property = PT_FIXED;
450       // Scan through the TPM properties of the requested group.
451       // The size of TPM property group is PT_GROUP * 2 for fix and
452       // variable groups.
453       for(i = property; i <= PT_FIXED + PT_GROUP * 2; i++)
454       {
455           UINT32          value;
456           if(TPMPropertyIsDefined((TPM_PT) i, &value))
457           {
458               if(propertyList->count < count)
459               {
460                     // If the list is not full, add this property
461                     propertyList->tpmProperty[propertyList->count].property =
462                         (TPM_PT) i;
463                     propertyList->tpmProperty[propertyList->count].value = value;
464                     propertyList->count++;
465               }
466               else
467               {
468                   // If the return list is full but there are more properties
469                   // available, set the indication and exit the loop.
470                   more = YES;
471                   break;
472               }
473           }
474       }
475       return more;
476 }
477