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