aboutsummaryrefslogtreecommitdiff
path: root/Object.c
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2015-05-20 10:32:25 -0700
committerVadim Bendebury <vbendeb@chromium.org>2015-05-20 22:32:05 -0700
commit5679752bf24c21135884e987c4077e2f71848971 (patch)
tree3e680dd91a7af84c45ea1170ee88225bd4ad32c8 /Object.c
downloadtpm2-5679752bf24c21135884e987c4077e2f71848971.tar.gz
Initial commit to seed TPM2.0 source code directory
LICENSE file text copied from TCG library specification. README describes the procedure used to extract source code from parts 3 and 4 of the specification. The python scripts and part{34}.txt files will be removed in the following commits. Change-Id: Ie281e6e988481831f33483053455e8aff8f3f75f Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'Object.c')
-rw-r--r--Object.c893
1 files changed, 893 insertions, 0 deletions
diff --git a/Object.c b/Object.c
new file mode 100644
index 0000000..66a23fe
--- /dev/null
+++ b/Object.c
@@ -0,0 +1,893 @@
+// 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
+
+#define OBJECT_C
+#include "InternalRoutines.h"
+#include <Platform.h>
+//
+//
+// Functions
+//
+// ObjectStartup()
+//
+// This function is called at TPM2_Startup() to initialize the object subsystem.
+//
+void
+ObjectStartup(
+ void
+ )
+{
+ UINT32 i;
+ // object slots initialization
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ //Set the slot to not occupied
+ s_objects[i].occupied = FALSE;
+ }
+ return;
+}
+//
+//
+// ObjectCleanupEvict()
+//
+// In this implementation, a persistent object is moved from NV into an object slot for processing. It is
+// flushed after command execution. This function is called from ExecuteCommand().
+//
+void
+ObjectCleanupEvict(
+ void
+ )
+{
+ UINT32 i;
+ // This has to be iterated because a command may have two handles
+ // and they may both be persistent.
+ // This could be made to be more efficient so that a search is not needed.
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ // If an object is a temporary evict object, flush it from slot
+ if(s_objects[i].object.entity.attributes.evict == SET)
+ s_objects[i].occupied = FALSE;
+ }
+ return;
+}
+//
+//
+// ObjectIsPresent()
+//
+// This function checks to see if a transient handle references a loaded object. This routine should not be
+// called if the handle is not a transient handle. The function validates that the handle is in the
+// implementation-dependent allowed in range for loaded transient objects.
+//
+// Return Value Meaning
+//
+// TRUE if the handle references a loaded object
+// FALSE if the handle is not an object handle, or it does not reference to a
+// loaded object
+//
+BOOL
+ObjectIsPresent(
+ TPMI_DH_OBJECT handle // IN: handle to be checked
+ )
+{
+ UINT32 slotIndex; // index of object slot
+ pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
+ // The index in the loaded object array is found by subtracting the first
+ // object handle number from the input handle number. If the indicated
+ // slot is occupied, then indicate that there is already is a loaded
+ // object associated with the handle.
+ slotIndex = handle - TRANSIENT_FIRST;
+ if(slotIndex >= MAX_LOADED_OBJECTS)
+ return FALSE;
+ return s_objects[slotIndex].occupied;
+}
+//
+//
+// ObjectIsSequence()
+//
+// This function is used to check if the object is a sequence object. This function should not be called if the
+// handle does not reference a loaded object.
+//
+// Return Value Meaning
+//
+// TRUE object is an HMAC, hash, or event sequence object
+// FALSE object is not an HMAC, hash, or event sequence object
+//
+BOOL
+ObjectIsSequence(
+ OBJECT *object // IN: handle to be checked
+ )
+{
+ pAssert (object != NULL);
+ if( object->attributes.hmacSeq == SET
+ || object->attributes.hashSeq == SET
+ || object->attributes.eventSeq == SET)
+ return TRUE;
+ else
+ return FALSE;
+}
+//
+//
+// ObjectGet()
+//
+// This function is used to find the object structure associated with a handle.
+// This function requires that handle references a loaded object.
+//
+OBJECT*
+ObjectGet(
+ TPMI_DH_OBJECT handle // IN: handle of the object
+ )
+{
+ pAssert( handle >= TRANSIENT_FIRST
+ && handle - TRANSIENT_FIRST < MAX_LOADED_OBJECTS);
+ pAssert(s_objects[handle - TRANSIENT_FIRST].occupied == TRUE);
+ // In this implementation, the handle is determined by the slot occupied by the
+ // object.
+ return &s_objects[handle - TRANSIENT_FIRST].object.entity;
+}
+//
+//
+// ObjectGetName()
+//
+// This function is used to access the Name of the object. In this implementation, the Name is computed
+// when the object is loaded and is saved in the internal representation of the object. This function copies
+// the Name data from the object into the buffer at name and returns the number of octets copied.
+// This function requires that handle references a loaded object.
+//
+UINT16
+ObjectGetName(
+ TPMI_DH_OBJECT handle, // IN: handle of the object
+ NAME *name // OUT: name of the object
+ )
+{
+ OBJECT *object = ObjectGet(handle);
+ if(object->publicArea.nameAlg == TPM_ALG_NULL)
+ return 0;
+ // Copy the Name data to the output
+ MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME));
+ return object->name.t.size;
+}
+//
+//
+// ObjectGetNameAlg()
+//
+// This function is used to get the Name algorithm of a object.
+// This function requires that handle references a loaded object.
+//
+TPMI_ALG_HASH
+ObjectGetNameAlg(
+ TPMI_DH_OBJECT handle // IN: handle of the object
+ )
+{
+ OBJECT *object = ObjectGet(handle);
+ return object->publicArea.nameAlg;
+}
+//
+//
+//
+// ObjectGetQualifiedName()
+//
+// This function returns the Qualified Name of the object. In this implementation, the Qualified Name is
+// computed when the object is loaded and is saved in the internal representation of the object. The
+// alternative would be to retain the Name of the parent and compute the QN when needed. This would take
+// the same amount of space so it is not recommended that the alternate be used.
+// This function requires that handle references a loaded object.
+//
+void
+ObjectGetQualifiedName(
+ TPMI_DH_OBJECT handle, // IN: handle of the object
+ TPM2B_NAME *qualifiedName // OUT: qualified name of the object
+ )
+{
+ OBJECT *object = ObjectGet(handle);
+ if(object->publicArea.nameAlg == TPM_ALG_NULL)
+ qualifiedName->t.size = 0;
+ else
+ // Copy the name
+ *qualifiedName = object->qualifiedName;
+ return;
+}
+//
+//
+// ObjectDataGetHierarchy()
+//
+// This function returns the handle for the hierarchy of an object.
+//
+TPMI_RH_HIERARCHY
+ObjectDataGetHierarchy(
+ OBJECT *object // IN :object
+ )
+{
+ if(object->attributes.spsHierarchy)
+ {
+ return TPM_RH_OWNER;
+ }
+ else if(object->attributes.epsHierarchy)
+ {
+ return TPM_RH_ENDORSEMENT;
+ }
+ else if(object->attributes.ppsHierarchy)
+ {
+ return TPM_RH_PLATFORM;
+ }
+ else
+ {
+ return TPM_RH_NULL;
+ }
+}
+//
+//
+// ObjectGetHierarchy()
+//
+// This function returns the handle of the hierarchy to which a handle belongs. This function is similar to
+// ObjectDataGetHierarchy() but this routine takes a handle but ObjectDataGetHierarchy() takes an pointer
+// to an object.
+// This function requires that handle references a loaded object.
+//
+TPMI_RH_HIERARCHY
+ObjectGetHierarchy(
+ TPMI_DH_OBJECT handle // IN :object handle
+ )
+{
+ OBJECT *object = ObjectGet(handle);
+ return ObjectDataGetHierarchy(object);
+}
+//
+//
+// ObjectAllocateSlot()
+//
+// This function is used to allocate a slot in internal object array.
+//
+// Return Value Meaning
+//
+// TRUE allocate success
+// FALSE do not have free slot
+//
+static BOOL
+ObjectAllocateSlot(
+ TPMI_DH_OBJECT *handle, // OUT: handle of allocated object
+ OBJECT **object // OUT: points to the allocated object
+ )
+{
+ UINT32 i;
+ // find an unoccupied handle slot
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ if(!s_objects[i].occupied) // If found a free slot
+ {
+ // Mark the slot as occupied
+ s_objects[i].occupied = TRUE;
+ break;
+ }
+ }
+ // If we reach the end of object slot without finding a free one, return
+ // error.
+ if(i == MAX_LOADED_OBJECTS) return FALSE;
+ *handle = i + TRANSIENT_FIRST;
+ *object = &s_objects[i].object.entity;
+ // Initialize the object attributes
+ MemorySet(&((*object)->attributes), 0, sizeof(OBJECT_ATTRIBUTES));
+ return TRUE;
+}
+//
+//
+// ObjectLoad()
+//
+// This function loads an object into an internal object structure. If an error is returned, the internal state is
+// unchanged.
+//
+//
+//
+//
+// Error Returns Meaning
+//
+// TPM_RC_BINDING if the public and sensitive parts of the object are not matched
+// TPM_RC_KEY if the parameters in the public area of the object are not consistent
+// TPM_RC_OBJECT_MEMORY if there is no free slot for an object
+// TPM_RC_TYPE the public and private parts are not the same type
+//
+TPM_RC
+ObjectLoad(
+ TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy to which the object belongs
+ TPMT_PUBLIC *publicArea, // IN: public area
+ TPMT_SENSITIVE *sensitive, // IN: sensitive area (may be null)
+ TPM2B_NAME *name, // IN: object's name (may be null)
+ TPM_HANDLE parentHandle, // IN: handle of parent
+ BOOL skipChecks, // IN: flag to indicate if it is OK to skip
+ // consistency checks.
+ TPMI_DH_OBJECT *handle // OUT: object handle
+ )
+{
+ OBJECT *object = NULL;
+ OBJECT *parent = NULL;
+ TPM_RC result = TPM_RC_SUCCESS;
+ TPM2B_NAME parentQN; // Parent qualified name
+ // Try to allocate a slot for new object
+ if(!ObjectAllocateSlot(handle, &object))
+ return TPM_RC_OBJECT_MEMORY;
+ // Initialize public
+ object->publicArea = *publicArea;
+ if(sensitive != NULL)
+ object->sensitive = *sensitive;
+ // Are the consistency checks needed
+ if(!skipChecks)
+ {
+ // Check if key size matches
+ if(!CryptObjectIsPublicConsistent(&object->publicArea))
+ {
+ result = TPM_RC_KEY;
+ goto ErrorExit;
+ }
+ if(sensitive != NULL)
+ {
+ // Check if public type matches sensitive type
+ result = CryptObjectPublicPrivateMatch(object);
+ if(result != TPM_RC_SUCCESS)
+ goto ErrorExit;
+ }
+ }
+ object->attributes.publicOnly = (sensitive == NULL);
+ // If 'name' is NULL, then there is nothing left to do for this
+ // object as it has no qualified name and it is not a member of any
+ // hierarchy and it is temporary
+ if(name == NULL || name->t.size == 0)
+ {
+ object->qualifiedName.t.size = 0;
+ object->name.t.size = 0;
+ object->attributes.temporary = SET;
+ return TPM_RC_SUCCESS;
+ }
+ // If parent handle is a permanent handle, it is a primary or temporary
+ // object
+ if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
+ {
+ // initialize QN
+ parentQN.t.size = 4;
+ // for a primary key, parent qualified name is the handle of hierarchy
+ UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name);
+ }
+ else
+ {
+ // Get hierarchy and qualified name of parent
+ ObjectGetQualifiedName(parentHandle, &parentQN);
+ // Check for stClear object
+ parent = ObjectGet(parentHandle);
+ if( publicArea->objectAttributes.stClear == SET
+ || parent->attributes.stClear == SET)
+ object->attributes.stClear = SET;
+ }
+ object->name = *name;
+ // Compute object qualified name
+ ObjectComputeQualifiedName(&parentQN, publicArea->nameAlg,
+ name, &object->qualifiedName);
+ // Any object in TPM_RH_NULL hierarchy is temporary
+ if(hierarchy == TPM_RH_NULL)
+ {
+ object->attributes.temporary = SET;
+ }
+ else if(parentQN.t.size == sizeof(TPM_HANDLE))
+ {
+ // Otherwise, if the size of parent's qualified name is the size of a
+ // handle, this object is a primary object
+ object->attributes.primary = SET;
+ }
+ switch(hierarchy)
+ {
+ case TPM_RH_PLATFORM:
+ object->attributes.ppsHierarchy = SET;
+ break;
+ case TPM_RH_OWNER:
+ object->attributes.spsHierarchy = SET;
+ break;
+ case TPM_RH_ENDORSEMENT:
+ object->attributes.epsHierarchy = SET;
+ break;
+ case TPM_RH_NULL:
+ break;
+ default:
+ pAssert(FALSE);
+ break;
+ }
+ return TPM_RC_SUCCESS;
+ErrorExit:
+ ObjectFlush(*handle);
+ return result;
+}
+//
+//
+//
+// AllocateSequenceSlot()
+//
+// This function allocates a sequence slot and initializes the parts that are used by the normal objects so
+// that a sequence object is not inadvertently used for an operation that is not appropriate for a sequence.
+//
+static BOOL
+AllocateSequenceSlot(
+ TPM_HANDLE *newHandle, // OUT: receives the allocated handle
+ HASH_OBJECT **object, // OUT: receives pointer to allocated object
+ TPM2B_AUTH *auth // IN: the authValue for the slot
+ )
+{
+ OBJECT *objectHash; // the hash as an object
+ if(!ObjectAllocateSlot(newHandle, &objectHash))
+ return FALSE;
+ *object = (HASH_OBJECT *)objectHash;
+ // Validate that the proper location of the hash state data relative to the
+ // object state data.
+ pAssert(&((*object)->auth) == &objectHash->publicArea.authPolicy);
+ // Set the common values that a sequence object shares with an ordinary object
+ // The type is TPM_ALG_NULL
+ (*object)->type = TPM_ALG_NULL;
+ // This has no name algorithm and the name is the Empty Buffer
+ (*object)->nameAlg = TPM_ALG_NULL;
+ // Clear the attributes
+ MemorySet(&((*object)->objectAttributes), 0, sizeof(TPMA_OBJECT));
+ // A sequence object is considered to be in the NULL hierarchy so it should
+ // be marked as temporary so that it can't be persisted
+ (*object)->attributes.temporary = SET;
+ // A sequence object is DA exempt.
+ (*object)->objectAttributes.noDA = SET;
+ if(auth != NULL)
+ {
+ MemoryRemoveTrailingZeros(auth);
+ (*object)->auth = *auth;
+ }
+ else
+ (*object)->auth.t.size = 0;
+ return TRUE;
+}
+//
+//
+// ObjectCreateHMACSequence()
+//
+// This function creates an internal HMAC sequence object.
+//
+// Error Returns Meaning
+//
+// TPM_RC_OBJECT_MEMORY if there is no free slot for an object
+//
+TPM_RC
+ObjectCreateHMACSequence(
+ TPMI_ALG_HASH hashAlg, // IN: hash algorithm
+ TPM_HANDLE handle, // IN: the handle associated with sequence
+ // object
+ TPM2B_AUTH *auth, // IN: authValue
+ TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle
+ )
+{
+ HASH_OBJECT *hmacObject;
+ OBJECT *keyObject;
+ // Try to allocate a slot for new object
+ if(!AllocateSequenceSlot(newHandle, &hmacObject, auth))
+ return TPM_RC_OBJECT_MEMORY;
+ // Set HMAC sequence bit
+ hmacObject->attributes.hmacSeq = SET;
+ // Get pointer to the HMAC key object
+ keyObject = ObjectGet(handle);
+ CryptStartHMACSequence2B(hashAlg, &keyObject->sensitive.sensitive.bits.b,
+ &hmacObject->state.hmacState);
+ return TPM_RC_SUCCESS;
+}
+//
+//
+// ObjectCreateHashSequence()
+//
+// This function creates a hash sequence object.
+//
+// Error Returns Meaning
+//
+// TPM_RC_OBJECT_MEMORY if there is no free slot for an object
+//
+TPM_RC
+ObjectCreateHashSequence(
+ TPMI_ALG_HASH hashAlg, // IN: hash algorithm
+ TPM2B_AUTH *auth, // IN: authValue
+ TPMI_DH_OBJECT *newHandle // OUT: sequence object handle
+ )
+{
+ HASH_OBJECT *hashObject;
+ // Try to allocate a slot for new object
+ if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
+ return TPM_RC_OBJECT_MEMORY;
+ // Set hash sequence bit
+ hashObject->attributes.hashSeq = SET;
+ // Start hash for hash sequence
+ CryptStartHashSequence(hashAlg, &hashObject->state.hashState[0]);
+ return TPM_RC_SUCCESS;
+}
+//
+//
+// ObjectCreateEventSequence()
+//
+// This function creates an event sequence object.
+//
+// Error Returns Meaning
+//
+// TPM_RC_OBJECT_MEMORY if there is no free slot for an object
+//
+TPM_RC
+ObjectCreateEventSequence(
+ TPM2B_AUTH *auth, // IN: authValue
+ TPMI_DH_OBJECT *newHandle // OUT: sequence object handle
+ )
+{
+ HASH_OBJECT *hashObject;
+ UINT32 count;
+ TPM_ALG_ID hash;
+ // Try to allocate a slot for new object
+ if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
+ return TPM_RC_OBJECT_MEMORY;
+ // Set the event sequence attribute
+ hashObject->attributes.eventSeq = SET;
+ // Initialize hash states for each implemented PCR algorithms
+ for(count = 0; (hash = CryptGetHashAlgByIndex(count)) != TPM_ALG_NULL; count++)
+ {
+ // If this is a _TPM_Init or _TPM_HashStart, the sequence object will
+ // not leave the TPM so it doesn't need the sequence handling
+ if(auth == NULL)
+ CryptStartHash(hash, &hashObject->state.hashState[count]);
+ else
+ CryptStartHashSequence(hash, &hashObject->state.hashState[count]);
+ }
+ return TPM_RC_SUCCESS;
+}
+//
+//
+// ObjectTerminateEvent()
+//
+// This function is called to close out the event sequence and clean up the hash context states.
+//
+void
+ObjectTerminateEvent(
+ void
+ )
+{
+ HASH_OBJECT *hashObject;
+ int count;
+ BYTE buffer[MAX_DIGEST_SIZE];
+ hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
+ // Don't assume that this is a proper sequence object
+ if(hashObject->attributes.eventSeq)
+ {
+ // If it is, close any open hash contexts. This is done in case
+ // the crypto implementation has some context values that need to be
+ // cleaned up (hygiene).
+ //
+ for(count = 0; CryptGetHashAlgByIndex(count) != TPM_ALG_NULL; count++)
+ {
+ CryptCompleteHash(&hashObject->state.hashState[count], 0, buffer);
+ }
+ // Flush sequence object
+ ObjectFlush(g_DRTMHandle);
+ }
+ g_DRTMHandle = TPM_RH_UNASSIGNED;
+}
+//
+//
+//
+// ObjectContextLoad()
+//
+// This function loads an object from a saved object context.
+//
+// Error Returns Meaning
+//
+// TPM_RC_OBJECT_MEMORY if there is no free slot for an object
+//
+TPM_RC
+ObjectContextLoad(
+ OBJECT *object, // IN: object structure from saved context
+ TPMI_DH_OBJECT *handle // OUT: object handle
+ )
+{
+ OBJECT *newObject;
+ // Try to allocate a slot for new object
+ if(!ObjectAllocateSlot(handle, &newObject))
+ return TPM_RC_OBJECT_MEMORY;
+ // Copy input object data to internal structure
+ *newObject = *object;
+ return TPM_RC_SUCCESS;
+}
+//
+//
+// ObjectFlush()
+//
+// This function frees an object slot.
+// This function requires that the object is loaded.
+//
+void
+ObjectFlush(
+ TPMI_DH_OBJECT handle // IN: handle to be freed
+ )
+{
+ UINT32 index = handle - TRANSIENT_FIRST;
+ pAssert(ObjectIsPresent(handle));
+ // Mark the handle slot as unoccupied
+ s_objects[index].occupied = FALSE;
+ // With no attributes
+ MemorySet((BYTE*)&(s_objects[index].object.entity.attributes),
+ 0, sizeof(OBJECT_ATTRIBUTES));
+ return;
+}
+//
+//
+// ObjectFlushHierarchy()
+//
+// This function is called to flush all the loaded transient objects associated with a hierarchy when the
+// hierarchy is disabled.
+//
+void
+ObjectFlushHierarchy(
+ TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush
+ )
+{
+ UINT16 i;
+ // iterate object slots
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ if(s_objects[i].occupied) // If found an occupied slot
+ {
+ switch(hierarchy)
+ {
+ case TPM_RH_PLATFORM:
+ if(s_objects[i].object.entity.attributes.ppsHierarchy == SET)
+ s_objects[i].occupied = FALSE;
+ break;
+ case TPM_RH_OWNER:
+ if(s_objects[i].object.entity.attributes.spsHierarchy == SET)
+ s_objects[i].occupied = FALSE;
+ break;
+ case TPM_RH_ENDORSEMENT:
+ if(s_objects[i].object.entity.attributes.epsHierarchy == SET)
+ s_objects[i].occupied = FALSE;
+ break;
+ default:
+ pAssert(FALSE);
+ break;
+ }
+ }
+ }
+ return;
+}
+//
+//
+// ObjectLoadEvict()
+//
+// This function loads a persistent object into a transient object slot.
+// This function requires that handle is associated with a persistent object.
+//
+// Error Returns Meaning
+//
+// TPM_RC_HANDLE the persistent object does not exist or the associated hierarchy is
+// disabled.
+// TPM_RC_OBJECT_MEMORY no object slot
+//
+TPM_RC
+ObjectLoadEvict(
+ TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it
+ // will be replace by the loaded object handle
+ TPM_CC commandCode // IN: the command being processed
+ )
+{
+ TPM_RC result;
+ TPM_HANDLE evictHandle = *handle; // Save the evict handle
+ OBJECT *object;
+ // If this is an index that references a persistent object created by
+ // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE
+ if(*handle >= PLATFORM_PERSISTENT)
+ {
+ // belongs to platform
+ if(g_phEnable == CLEAR)
+ return TPM_RC_HANDLE;
+ }
+ // belongs to owner
+ else if(gc.shEnable == CLEAR)
+ return TPM_RC_HANDLE;
+ // Try to allocate a slot for an object
+ if(!ObjectAllocateSlot(handle, &object))
+ return TPM_RC_OBJECT_MEMORY;
+ // Copy persistent object to transient object slot. A TPM_RC_HANDLE
+ // may be returned at this point. This will mark the slot as containing
+ // a transient object so that it will be flushed at the end of the
+ // command
+ result = NvGetEvictObject(evictHandle, object);
+ // Bail out if this failed
+ if(result != TPM_RC_SUCCESS)
+ return result;
+ // check the object to see if it is in the endorsement hierarchy
+ // if it is and this is not a TPM2_EvictControl() command, indicate
+ // that the hierarchy is disabled.
+ // If the associated hierarchy is disabled, make it look like the
+ // handle is not defined
+ if( ObjectDataGetHierarchy(object) == TPM_RH_ENDORSEMENT
+ && gc.ehEnable == CLEAR
+ && commandCode != TPM_CC_EvictControl
+ )
+ return TPM_RC_HANDLE;
+ return result;
+}
+//
+//
+// ObjectComputeName()
+//
+// This function computes the Name of an object from its public area.
+//
+void
+ObjectComputeName(
+ TPMT_PUBLIC *publicArea, // IN: public area of an object
+ TPM2B_NAME *name // OUT: name of the object
+ )
+{
+ TPM2B_PUBLIC marshalBuffer;
+ BYTE *buffer; // auxiliary marshal buffer pointer
+ HASH_STATE hashState; // hash state
+ // if the nameAlg is NULL then there is no name.
+ if(publicArea->nameAlg == TPM_ALG_NULL)
+ {
+ name->t.size = 0;
+ return;
+ }
+ // Start hash stack
+ name->t.size = CryptStartHash(publicArea->nameAlg, &hashState);
+ // Marshal the public area into its canonical form
+ buffer = marshalBuffer.b.buffer;
+ marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL);
+ // Adding public area
+ CryptUpdateDigest2B(&hashState, &marshalBuffer.b);
+ // Complete hash leaving room for the name algorithm
+ CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]);
+ // set the nameAlg
+ UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name);
+//
+ name->t.size += 2;
+ return;
+}
+//
+//
+// ObjectComputeQualifiedName()
+//
+// This function computes the qualified name of an object.
+//
+void
+ObjectComputeQualifiedName(
+ TPM2B_NAME *parentQN, // IN: parent's qualified name
+ TPM_ALG_ID nameAlg, // IN: name hash
+ TPM2B_NAME *name, // IN: name of the object
+ TPM2B_NAME *qualifiedName // OUT: qualified name of the object
+ )
+{
+ HASH_STATE hashState; // hash state
+ // QN_A = hash_A (QN of parent || NAME_A)
+ // Start hash
+ qualifiedName->t.size = CryptStartHash(nameAlg, &hashState);
+ // Add parent's qualified name
+ CryptUpdateDigest2B(&hashState, &parentQN->b);
+ // Add self name
+ CryptUpdateDigest2B(&hashState, &name->b);
+ // Complete hash leaving room for the name algorithm
+ CryptCompleteHash(&hashState, qualifiedName->t.size,
+ &qualifiedName->t.name[2]);
+ UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
+ qualifiedName->t.size += 2;
+ return;
+}
+//
+//
+// ObjectDataIsStorage()
+//
+// This function determines if a public area has the attributes associated with a storage key. A storage key is
+// an asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR.
+//
+// Return Value Meaning
+//
+// TRUE if the object is a storage key
+// FALSE if the object is not a storage key
+//
+BOOL
+ObjectDataIsStorage(
+ TPMT_PUBLIC *publicArea // IN: public area of the object
+ )
+{
+ if( CryptIsAsymAlgorithm(publicArea->type) // must be asymmetric,
+ && publicArea->objectAttributes.restricted == SET // restricted,
+ && publicArea->objectAttributes.decrypt == SET // decryption key
+ && publicArea->objectAttributes.sign == CLEAR // can not be sign key
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+//
+// ObjectIsStorage()
+//
+// This function determines if an object has the attributes associated with a storage key. A storage key is an
+// asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR.
+//
+// Return Value Meaning
+//
+// TRUE if the object is a storage key
+// FALSE if the object is not a storage key
+//
+BOOL
+ObjectIsStorage(
+ TPMI_DH_OBJECT handle // IN: object handle
+ )
+{
+ OBJECT *object = ObjectGet(handle);
+ return ObjectDataIsStorage(&object->publicArea);
+}
+//
+//
+// ObjectCapGetLoaded()
+//
+// This function returns a a list of handles of loaded object, starting from handle. Handle must be in the
+// range of valid transient object handles, but does not have to be the handle of a loaded transient object.
+//
+// Return Value Meaning
+//
+// YES if there are more handles available
+// NO all the available handles has been returned
+//
+TPMI_YES_NO
+ObjectCapGetLoaded(
+ TPMI_DH_OBJECT handle, // IN: start handle
+ UINT32 count, // IN: count of returned handles
+ TPML_HANDLE *handleList // OUT: list of handle
+ )
+{
+ TPMI_YES_NO more = NO;
+ UINT32 i;
+ pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
+ // Initialize output handle list
+ handleList->count = 0;
+ // The maximum count of handles we may return is MAX_CAP_HANDLES
+ if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
+ // Iterate object slots to get loaded object handles
+ for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
+ {
+ if(s_objects[i].occupied == TRUE)
+ {
+ // A valid transient object can not be the copy of a persistent object
+ pAssert(s_objects[i].object.entity.attributes.evict == CLEAR);
+ if(handleList->count < count)
+ {
+ // If we have not filled up the return list, add this object
+ // handle to it
+ handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
+ handleList->count++;
+//
+ }
+ else
+ {
+ // If the return list is full but we still have loaded object
+ // available, report this and stop iterating
+ more = YES;
+ break;
+ }
+ }
+ }
+ return more;
+}
+//
+//
+// ObjectCapGetTransientAvail()
+//
+// This function returns an estimate of the number of additional transient objects that could be loaded into
+// the TPM.
+//
+UINT32
+ObjectCapGetTransientAvail(
+ void
+ )
+{
+ UINT32 i;
+ UINT32 num = 0;
+ // Iterate object slot to get the number of unoccupied slots
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ if(s_objects[i].occupied == FALSE) num++;
+ }
+ return num;
+}