| // 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; |
| 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, NULL); |
| 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; |
| } |