diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2015-05-20 10:32:25 -0700 |
---|---|---|
committer | Vadim Bendebury <vbendeb@chromium.org> | 2015-05-20 22:32:05 -0700 |
commit | 5679752bf24c21135884e987c4077e2f71848971 (patch) | |
tree | 3e680dd91a7af84c45ea1170ee88225bd4ad32c8 /Object.c | |
download | tpm2-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.c | 893 |
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; +} |