424 lines
16 KiB
C
424 lines
16 KiB
C
// 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;
|
|
}
|