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//
24static BOOL
25TPMPropertyIsDefined(
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//
434TPMI_YES_NO
435TPMCapGetProperties(
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