// 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 // // EntityGetLoadStatus() // // This function will indicate if the entity associated with a handle is present in TPM memory. If the handle is // a persistent object handle, and the object exists, the persistent object is moved from NV memory into a // RAM object slot and the persistent handle is replaced with the transient object handle for the slot. // // Error Returns Meaning // // TPM_RC_HANDLE handle type does not match // TPM_RC_REFERENCE_H0 entity is not present // TPM_RC_HIERARCHY entity belongs to a disabled hierarchy // TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM // TPM_RC EntityGetLoadStatus( TPM_HANDLE *handle, // IN/OUT: handle of the entity TPM_CC commandCode // IN: the commmandCode ) { TPM_RC result = TPM_RC_SUCCESS; switch(HandleGetType(*handle)) { // For handles associated with hierarchies, the entity is present // only if the associated enable is SET. case TPM_HT_PERMANENT: switch(*handle) { case TPM_RH_OWNER: if(!gc.shEnable) result = TPM_RC_HIERARCHY; break; #ifdef VENDOR_PERMANENT case VENDOR_PERMANENT: #endif case TPM_RH_ENDORSEMENT: if(!gc.ehEnable) result = TPM_RC_HIERARCHY; break; case TPM_RH_PLATFORM: if(!g_phEnable) result = TPM_RC_HIERARCHY; break; // null handle, PW session handle and lockout // handle are always available case TPM_RH_NULL: case TPM_RS_PW: case TPM_RH_LOCKOUT: break; default: // handling of the manufacture_specific handles if( ((TPM_RH)*handle >= TPM_RH_FIRST) && ((TPM_RH)*handle <= TPM_RH_LAST)) // use the value that would have been returned from // unmarshaling if it did the handle filtering result = TPM_RC_VALUE; else pAssert(FALSE); break; } break; case TPM_HT_TRANSIENT: // For a transient object, check if the handle is associated // with a loaded object. if(!ObjectIsPresent(*handle)) result = TPM_RC_REFERENCE_H0; break; case TPM_HT_PERSISTENT: // Persistent object // Copy the persistent object to RAM and replace the handle with the // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY, // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by // ObjectLoadEvict() result = ObjectLoadEvict(handle, commandCode); break; case TPM_HT_HMAC_SESSION: // For an HMAC session, see if the session is loaded // and if the session in the session slot is actually // an HMAC session. if(SessionIsLoaded(*handle)) { SESSION *session; session = SessionGet(*handle); // Check if the session is a HMAC session if(session->attributes.isPolicy == SET) result = TPM_RC_HANDLE; } else result = TPM_RC_REFERENCE_H0; break; case TPM_HT_POLICY_SESSION: // For a policy session, see if the session is loaded // and if the session in the session slot is actually // a policy session. if(SessionIsLoaded(*handle)) { SESSION *session; session = SessionGet(*handle); // Check if the session is a policy session if(session->attributes.isPolicy == CLEAR) result = TPM_RC_HANDLE; } else result = TPM_RC_REFERENCE_H0; break; case TPM_HT_NV_INDEX: // For an NV Index, use the platform-specific routine // to search the IN Index space. result = NvIndexIsAccessible(*handle, commandCode); break; case TPM_HT_PCR: // Any PCR handle that is unmarshaled successfully referenced // a PCR that is defined. break; default: // Any other handle type is a defect in the unmarshaling code. pAssert(FALSE); break; } return result; } // // // // EntityGetAuthValue() // // This function is used to access the authValue associated with a handle. This function assumes that the // handle references an entity that is accessible and the handle is not for a persistent objects. That is // EntityGetLoadStatus() should have been called. Also, the accessibility of the authValue should have been // verified by IsAuthValueAvailable(). // This function copies the authorization value of the entity to auth. // Return value is the number of octets copied to auth. // UINT16 EntityGetAuthValue( TPMI_DH_ENTITY handle, // IN: handle of entity AUTH_VALUE *auth // OUT: authValue of the entity ) { TPM2B_AUTH authValue = {}; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: switch(handle) { case TPM_RH_OWNER: // ownerAuth for TPM_RH_OWNER authValue = gp.ownerAuth; break; case TPM_RH_ENDORSEMENT: // endorsementAuth for TPM_RH_ENDORSEMENT authValue = gp.endorsementAuth; break; case TPM_RH_PLATFORM: // platformAuth for TPM_RH_PLATFORM authValue = gc.platformAuth; break; case TPM_RH_LOCKOUT: // lockoutAuth for TPM_RH_LOCKOUT authValue = gp.lockoutAuth; break; case TPM_RH_NULL: // nullAuth for TPM_RH_NULL. Return 0 directly here return 0; break; #ifdef VENDOR_PERMANENT case VENDOR_PERMANENT: // vendor auth value authValue = g_platformUniqueDetails; #endif default: // If any other permanent handle is present it is // a code defect. pAssert(FALSE); break; } break; case TPM_HT_TRANSIENT: // authValue for an object // A persistent object would have been copied into RAM // and would have an transient object handle here. { OBJECT *object; object = ObjectGet(handle); // special handling if this is a sequence object if(ObjectIsSequence(object)) { authValue = ((HASH_OBJECT *)object)->auth; } else { // Auth value is available only when the private portion of // the object is loaded. The check should be made before // this function is called pAssert(object->attributes.publicOnly == CLEAR); authValue = object->sensitive.authValue; } } break; case TPM_HT_NV_INDEX: // authValue for an NV index { NV_INDEX nvIndex; NvGetIndexInfo(handle, &nvIndex); authValue = nvIndex.authValue; } break; case TPM_HT_PCR: // authValue for PCR PCRGetAuthValue(handle, &authValue); break; default: // If any other handle type is present here, then there is a defect // in the unmarshaling code. pAssert(FALSE); break; } // Copy the authValue pAssert(authValue.t.size <= sizeof(authValue.t.buffer)); MemoryCopy(auth, authValue.t.buffer, authValue.t.size, sizeof(TPMU_HA)); return authValue.t.size; } // // // EntityGetAuthPolicy() // // This function is used to access the authPolicy associated with a handle. This function assumes that the // handle references an entity that is accessible and the handle is not for a persistent objects. That is // EntityGetLoadStatus() should have been called. Also, the accessibility of the authPolicy should have // been verified by IsAuthPolicyAvailable(). // This function copies the authorization policy of the entity to authPolicy. // The return value is the hash algorithm for the policy. // TPMI_ALG_HASH EntityGetAuthPolicy( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity ) { TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: switch(handle) { case TPM_RH_OWNER: // // ownerPolicy for TPM_RH_OWNER *authPolicy = gp.ownerPolicy; hashAlg = gp.ownerAlg; break; case TPM_RH_ENDORSEMENT: // endorsementPolicy for TPM_RH_ENDORSEMENT *authPolicy = gp.endorsementPolicy; hashAlg = gp.endorsementAlg; break; case TPM_RH_PLATFORM: // platformPolicy for TPM_RH_PLATFORM *authPolicy = gc.platformPolicy; hashAlg = gc.platformAlg; break; case TPM_RH_LOCKOUT: // lockoutPolicy for TPM_RH_LOCKOUT *authPolicy = gp.lockoutPolicy; hashAlg = gp.lockoutAlg; break; default: // If any other permanent handle is present it is // a code defect. pAssert(FALSE); break; } break; case TPM_HT_TRANSIENT: // authPolicy for an object { OBJECT *object = ObjectGet(handle); *authPolicy = object->publicArea.authPolicy; hashAlg = object->publicArea.nameAlg; } break; case TPM_HT_NV_INDEX: // authPolicy for a NV index { NV_INDEX nvIndex; NvGetIndexInfo(handle, &nvIndex); *authPolicy = nvIndex.publicArea.authPolicy; hashAlg = nvIndex.publicArea.nameAlg; } break; case TPM_HT_PCR: // authPolicy for a PCR hashAlg = PCRGetAuthPolicy(handle, authPolicy); break; default: // If any other handle type is present it is a code defect. pAssert(FALSE); break; } return hashAlg; } // // // EntityGetName() // // This function returns the Name associated with a handle. It will set name to the Name and return the size // of the Name string. // UINT16 EntityGetName( TPMI_DH_ENTITY handle, // IN: handle of entity NAME *name // OUT: name of entity ) { UINT16 nameSize; INT32 bufferSize = sizeof(TPM_HANDLE); switch(HandleGetType(handle)) { case TPM_HT_TRANSIENT: // Name for an object nameSize = ObjectGetName(handle, name); break; case TPM_HT_NV_INDEX: // Name for a NV index nameSize = NvGetName(handle, name); break; default: // For all other types, the handle is the Name nameSize = TPM_HANDLE_Marshal(&handle, (BYTE **)&name, &bufferSize); break; } return nameSize; } // // // EntityGetHierarchy() // // This function returns the hierarchy handle associated with an entity. // a) A handle that is a hierarchy handle is associated with itself. // b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET, // otherwise it belongs to TPM_RH_OWNER // c) An object handle belongs to its hierarchy. All other handles belong to the platform hierarchy. or an NV // Index. // TPMI_RH_HIERARCHY EntityGetHierarchy( TPMI_DH_ENTITY handle // IN :handle of entity ) { TPMI_RH_HIERARCHY hierarcy = TPM_RH_NULL; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: // hierarchy for a permanent handle switch(handle) { case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: case TPM_RH_NULL: hierarcy = handle; break; // all other permanent handles are associated with the owner // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) default: hierarcy = TPM_RH_OWNER; break; } break; case TPM_HT_NV_INDEX: // hierarchy for NV index { NV_INDEX nvIndex; NvGetIndexInfo(handle, &nvIndex); // If only the platform can delete the index, then it is // considered to be in the platform hierarchy, otherwise it // is in the owner hierarchy. if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == SET) hierarcy = TPM_RH_PLATFORM; else hierarcy = TPM_RH_OWNER; } break; case TPM_HT_TRANSIENT: // hierarchy for an object { OBJECT *object; object = ObjectGet(handle); if(object->attributes.ppsHierarchy) { hierarcy = TPM_RH_PLATFORM; } else if(object->attributes.epsHierarchy) { hierarcy = TPM_RH_ENDORSEMENT; } else if(object->attributes.spsHierarchy) { hierarcy = TPM_RH_OWNER; } } break; case TPM_HT_PCR: hierarcy = TPM_RH_OWNER; break; default: pAssert(0); break; } // this is unreachable but it provides a return value for the default // case which makes the complier happy return hierarcy; }