// 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; }