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