summaryrefslogtreecommitdiffstats
path: root/src/tpm2/Object.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tpm2/Object.c')
-rw-r--r--src/tpm2/Object.c970
1 files changed, 970 insertions, 0 deletions
diff --git a/src/tpm2/Object.c b/src/tpm2/Object.c
new file mode 100644
index 0000000..aa69a53
--- /dev/null
+++ b/src/tpm2/Object.c
@@ -0,0 +1,970 @@
+/********************************************************************************/
+/* */
+/* Manage the object store of the TPM. */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: Object.c 1658 2021-01-22 23:14:01Z kgoldman $ */
+/* */
+/* Licenses and Notices */
+/* */
+/* 1. Copyright Licenses: */
+/* */
+/* - Trusted Computing Group (TCG) grants to the user of the source code in */
+/* this specification (the "Source Code") a worldwide, irrevocable, */
+/* nonexclusive, royalty free, copyright license to reproduce, create */
+/* derivative works, distribute, display and perform the Source Code and */
+/* derivative works thereof, and to grant others the rights granted herein. */
+/* */
+/* - The TCG grants to the user of the other parts of the specification */
+/* (other than the Source Code) the rights to reproduce, distribute, */
+/* display, and perform the specification solely for the purpose of */
+/* developing products based on such documents. */
+/* */
+/* 2. Source Code Distribution Conditions: */
+/* */
+/* - Redistributions of Source Code must retain the above copyright licenses, */
+/* this list of conditions and the following disclaimers. */
+/* */
+/* - Redistributions in binary form must reproduce the above copyright */
+/* licenses, this list of conditions and the following disclaimers in the */
+/* documentation and/or other materials provided with the distribution. */
+/* */
+/* 3. Disclaimers: */
+/* */
+/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
+/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
+/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
+/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
+/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
+/* information on specification licensing rights available through TCG */
+/* membership agreements. */
+/* */
+/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
+/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
+/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
+/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
+/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
+/* */
+/* - Without limitation, TCG and its members and licensors disclaim all */
+/* liability, including liability for infringement of any proprietary */
+/* rights, relating to use of information in this specification and to the */
+/* implementation of this specification, and TCG disclaims all liability for */
+/* cost of procurement of substitute goods or services, lost profits, loss */
+/* of use, loss of data or any incidental, consequential, direct, indirect, */
+/* or special damages, whether under contract, tort, warranty or otherwise, */
+/* arising in any way out of use or reliance upon this specification or any */
+/* information herein. */
+/* */
+/* (c) Copyright IBM Corp. and others, 2016 - 2021 */
+/* */
+/********************************************************************************/
+
+/* 8.6 Object.c */
+/* 8.6.1 Introduction */
+/* This file contains the functions that manage the object store of the TPM. */
+/* 8.6.2 Includes and Data Definitions */
+#define OBJECT_C
+#include "Tpm.h"
+#include "NVMarshal.h" // libtpms added
+#include "BackwardsCompatibilityObject.h" // libtpms added
+/* 8.6.3 Functions */
+/* 8.6.3.1 ObjectFlush() */
+/* This function marks an object slot as available. Since there is no checking of the input
+ parameters, it should be used judiciously. */
+/* NOTE: This could be converted to a macro. */
+void
+ObjectFlush(
+ OBJECT *object
+ )
+{
+ object->attributes.occupied = CLEAR;
+}
+/* 8.6.3.2 ObjectSetInUse() */
+/* This access function sets the occupied attribute of an object slot. */
+void
+ObjectSetInUse(
+ OBJECT *object
+ )
+{
+ object->attributes.occupied = SET;
+}
+/* 8.6.3.3 ObjectStartup() */
+/* This function is called at TPM2_Startup() to initialize the object subsystem. */
+BOOL
+ObjectStartup(
+ void
+ )
+{
+ UINT32 i;
+ // object slots initialization
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ //Set the slot to not occupied
+ ObjectFlush(&s_objects[i]);
+ }
+ return TRUE;
+}
+/* 8.6.3.4 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
+ OBJECT *object = &s_objects[i];
+ if(object->attributes.evict == SET)
+ ObjectFlush(object);
+ }
+ return;
+}
+/* 8.6.3.5 IsObjectPresent() */
+/* 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 Values 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
+IsObjectPresent(
+ TPMI_DH_OBJECT handle // IN: handle to be checked
+ )
+{
+ UINT32 slotIndex = handle - TRANSIENT_FIRST;
+ // Since the handle is just an index into the array that is zero based, any
+ // handle value outsize of the range of:
+ // TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1)
+ // will now be greater than or equal to MAX_LOADED_OBJECTS
+ if(slotIndex >= MAX_LOADED_OBJECTS)
+ return FALSE;
+ // Indicate if the slot is occupied
+ return (s_objects[slotIndex].attributes.occupied == TRUE);
+}
+/* 8.6.3.6 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 Values 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);
+ return (object->attributes.hmacSeq == SET
+ || object->attributes.hashSeq == SET
+ || object->attributes.eventSeq == SET);
+}
+/* 8.6.3.7 HandleToObject() */
+/* This function is used to find the object structure associated with a handle. */
+/* This function requires that handle references a loaded object or a permanent handle. */
+OBJECT*
+HandleToObject(
+ TPMI_DH_OBJECT handle // IN: handle of the object
+ )
+{
+ UINT32 index;
+ // Return NULL if the handle references a permanent handle because there is no
+ // associated OBJECT.
+ if(HandleGetType(handle) == TPM_HT_PERMANENT)
+ return NULL;
+ // In this implementation, the handle is determined by the slot occupied by the
+ // object.
+ index = handle - TRANSIENT_FIRST;
+ pAssert(index < MAX_LOADED_OBJECTS);
+ pAssert(s_objects[index].attributes.occupied);
+ return &s_objects[index];
+}
+/* 8.6.3.9 GetQualifiedName() */
+/* 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
+GetQualifiedName(
+ TPMI_DH_OBJECT handle, // IN: handle of the object
+ TPM2B_NAME *qualifiedName // OUT: qualified name of the object
+ )
+{
+ OBJECT *object;
+ switch(HandleGetType(handle))
+ {
+ case TPM_HT_PERMANENT:
+ qualifiedName->t.size = sizeof(TPM_HANDLE);
+ UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name);
+ break;
+ case TPM_HT_TRANSIENT:
+ object = HandleToObject(handle);
+ if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL)
+ qualifiedName->t.size = 0;
+ else
+ // Copy the name
+ *qualifiedName = object->qualifiedName;
+ break;
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ }
+ return;
+}
+/* 8.6.3.10 ObjectGetHierarchy() */
+/* This function returns the handle for the hierarchy of an object. */
+TPMI_RH_HIERARCHY
+ObjectGetHierarchy(
+ 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;
+ }
+}
+/* 8.6.3.11 GetHierarchy() */
+/* This function returns the handle of the hierarchy to which a handle belongs. This function is
+ similar to ObjectGetHierarchy() but this routine takes a handle while ObjectGetHierarchy() takes
+ a pointer to an object. */
+/* This function requires that handle references a loaded object. */
+TPMI_RH_HIERARCHY
+GetHieriarchy(
+ TPMI_DH_OBJECT handle // IN :object handle
+ )
+{
+ OBJECT *object = HandleToObject(handle);
+ return ObjectGetHierarchy(object);
+}
+/* 8.6.3.12 FindEmptyObjectSlot() */
+/* This function finds an open object slot, if any. It will clear the attributes but will not set
+ the occupied attribute. This is so that a slot may be used and discarded if everything does not
+ go as planned. */
+/* Return Values Meaning */
+/* null no open slot found */
+/* !=null pointer to available slot */
+OBJECT *
+FindEmptyObjectSlot(
+ TPMI_DH_OBJECT *handle // OUT: (optional)
+ )
+{
+ UINT32 i;
+ OBJECT *object;
+ for(i = 0; i < MAX_LOADED_OBJECTS; i++)
+ {
+ object = &s_objects[i];
+ if(object->attributes.occupied == CLEAR)
+ {
+ if(handle)
+ *handle = i + TRANSIENT_FIRST;
+ // Initialize the object attributes
+ // MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES));
+ MemorySet(object, 0, sizeof(*object)); // libtpms added: Initialize the whole object
+ return object;
+ }
+ }
+ return NULL;
+}
+/* 8.6.3.13 ObjectAllocateSlot() */
+/* This function is used to allocate a slot in internal object array. */
+/* Return Values Meaning */
+OBJECT *
+ObjectAllocateSlot(
+ TPMI_DH_OBJECT *handle // OUT: handle of allocated object
+ )
+{
+ OBJECT *object = FindEmptyObjectSlot(handle);
+ if(object != NULL)
+ {
+ // if found, mark as occupied
+ ObjectSetInUse(object);
+ }
+ return object;
+}
+/* 8.6.3.14 ObjectSetLoadedAttributes() */
+/* This function sets the internal attributes for a loaded object. It is called to finalize the
+ OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded object. */
+void
+ObjectSetLoadedAttributes(
+ OBJECT *object, // IN: object attributes to finalize
+ TPM_HANDLE parentHandle, // IN: the parent handle
+ SEED_COMPAT_LEVEL seedCompatLevel // IN: seed compat level to use for children
+ )
+{
+ OBJECT *parent = HandleToObject(parentHandle);
+ TPMA_OBJECT objectAttributes = object->publicArea.objectAttributes;
+
+ object->seedCompatLevel = seedCompatLevel; // libtpms added
+ //
+ // Copy the stClear attribute from the public area. This could be overwritten
+ // if the parent has stClear SET
+ object->attributes.stClear =
+ IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear);
+ // If parent handle is a permanent handle, it is a primary (unless it is NULL
+ if(parent == NULL)
+ {
+ object->attributes.primary = SET;
+ switch(parentHandle)
+ {
+ case TPM_RH_ENDORSEMENT:
+ object->attributes.epsHierarchy = SET;
+ break;
+ case TPM_RH_OWNER:
+ object->attributes.spsHierarchy = SET;
+ break;
+ case TPM_RH_PLATFORM:
+ object->attributes.ppsHierarchy = SET;
+ break;
+ default:
+ // Treat the temporary attribute as a hierarchy
+ object->attributes.temporary = SET;
+ object->attributes.primary = CLEAR;
+ break;
+ }
+ }
+ else
+ {
+ // is this a stClear object
+ object->attributes.stClear =
+ (IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear)
+ || (parent->attributes.stClear == SET));
+ object->attributes.epsHierarchy = parent->attributes.epsHierarchy;
+ object->attributes.spsHierarchy = parent->attributes.spsHierarchy;
+ object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy;
+ // An object is temporary if its parent is temporary or if the object
+ // is external
+ object->attributes.temporary = parent->attributes.temporary
+ || object->attributes.external;
+ }
+ // If this is an external object, set the QN == name but don't SET other
+ // key properties ('parent' or 'derived')
+ if(object->attributes.external)
+ object->qualifiedName = object->name;
+ else
+ {
+ // check attributes for different types of parents
+ if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted)
+ && !object->attributes.publicOnly
+ && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt)
+ && object->publicArea.nameAlg != TPM_ALG_NULL)
+ {
+ // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent.
+ // Otherwise, it is a derivation parent.
+ if(object->publicArea.type == TPM_ALG_KEYEDHASH)
+ object->attributes.derivation = SET;
+ else
+ object->attributes.isParent = SET;
+ }
+ ComputeQualifiedName(parentHandle, object->publicArea.nameAlg,
+ &object->name, &object->qualifiedName);
+ }
+ // Set slot occupied
+ ObjectSetInUse(object);
+ return;
+}
+/* 8.6.3.15 ObjectLoad() */
+/* Common function to load an object. A loaded object has its public area validated (unless its
+ nameAlg is TPM_ALG_NULL). If a sensitive part is loaded, it is verified to be correct and if both
+ public and sensitive parts are loaded, then the cryptographic binding between the objects is
+ validated. This function does not cause the allocated slot to be marked as in use. */
+TPM_RC
+ObjectLoad(
+ OBJECT *object, // IN: pointer to object slot
+ // object
+ OBJECT *parent, // IN: (optional) the parent object
+ TPMT_PUBLIC *publicArea, // IN: public area to be installed in the object
+ TPMT_SENSITIVE *sensitive, // IN: (optional) sensitive area to be
+ // installed in the object
+ TPM_RC blamePublic, // IN: parameter number to associate with the
+ // publicArea errors
+ TPM_RC blameSensitive,// IN: parameter number to associate with the
+ // sensitive area errors
+ TPM2B_NAME *name // IN: (optional)
+ )
+{
+ TPM_RC result = TPM_RC_SUCCESS;
+ BOOL doCheck;
+ //
+ // Do validations of public area object descriptions
+ // Is this public only or a no-name object?
+ if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL)
+ {
+ // Need to have schemes checked so that we do the right thing with the
+ // public key.
+ result = SchemeChecks(NULL, publicArea);
+ }
+ else
+ {
+ // For any sensitive area, make sure that the seedSize is no larger than the
+ // digest size of nameAlg
+ if(sensitive->seedValue.t.size
+ > CryptHashGetDigestSize(publicArea->nameAlg))
+ return TPM_RCS_KEY_SIZE + blameSensitive;
+ // Check attributes and schemes for consistency
+ result = PublicAttributesValidation(parent, publicArea);
+ }
+ if(result != TPM_RC_SUCCESS)
+ return RcSafeAddToResult(result, blamePublic);
+ // If object == NULL, then this is am import. For import, load is not called
+ // unless the parent is fixedTPM.
+ if(object == NULL)
+ doCheck = TRUE;// //
+ // If the parent is not NULL, then this is an ordinary load and we only check
+ // if the parent is not fixedTPM
+ else if(parent != NULL)
+ doCheck = !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
+ TPMA_OBJECT, fixedTPM);
+ else
+ // This is a loadExternal. Check everything.
+ // Note: the check functions will filter things based on the name algorithm
+ // and whether or not both parts are loaded.
+ doCheck = TRUE;
+ // Note: the parent will be NULL if this is a load external. CryptValidateKeys()
+ // will only check the parts that need to be checked based on the settings
+ // of publicOnly and nameAlg.
+ // Note: For an RSA key, the keys sizes are checked but the binding is not
+ // checked.
+ if(doCheck)
+ {
+ // Do the cryptographic key validation
+ result = CryptValidateKeys(publicArea, sensitive, blamePublic,
+ blameSensitive);
+ }
+ // If this is an import, we are done
+ if(object == NULL || result != TPM_RC_SUCCESS)
+ return result;
+ // Set the name, if one was provided
+ if(name != NULL)
+ object->name = *name;
+ else
+ object->name.t.size = 0;
+ // Initialize public
+ object->publicArea = *publicArea;
+ // If there is a sensitive area, load it
+ if(sensitive == NULL)
+ object->attributes.publicOnly = SET;
+ else
+ {
+ object->sensitive = *sensitive;
+#if ALG_RSA
+ // If this is an RSA key that is not a parent, complete the load by
+ // computing the private exponent.
+ if(publicArea->type == ALG_RSA_VALUE)
+ result = CryptRsaLoadPrivateExponent(object);
+#endif
+ }
+ return result;
+}
+/* 8.6.3.16 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 HASH_OBJECT *
+AllocateSequenceSlot(
+ TPM_HANDLE *newHandle, // OUT: receives the allocated handle
+ TPM2B_AUTH *auth // IN: the authValue for the slot
+ )
+{
+ HASH_OBJECT *object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle);
+ //
+ // Validate that the proper location of the hash state data relative to the
+ // object state data. It would be good if this could have been done at compile
+ // time but it can't so do it in something that can be removed after debug.
+ cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy));
+ if(object != NULL)
+ {
+ // Set the common values that a sequence object shares with an ordinary object
+ // First, clear all attributes
+ MemorySet(&object->objectAttributes, 0, sizeof(TPMA_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;
+ // 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.
+ SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA);
+ // Copy the authorization value
+ if(auth != NULL)
+ object->auth = *auth;
+ else
+ object->auth.t.size = 0;
+ }
+ return object;
+}
+/* 8.6.3.17 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 */
+#if CC_HMAC_Start || CC_MAC_Start
+TPM_RC
+ObjectCreateHMACSequence(
+ TPMI_ALG_HASH hashAlg, // IN: hash algorithm
+ OBJECT *keyObject, // IN: the object containing the HMAC key
+ TPM2B_AUTH *auth, // IN: authValue
+ TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle
+ )
+{
+ HASH_OBJECT *hmacObject;
+ //
+ // Try to allocate a slot for new object
+ hmacObject = AllocateSequenceSlot(newHandle, auth);
+ if(hmacObject == NULL)
+ return TPM_RC_OBJECT_MEMORY;
+ // Set HMAC sequence bit
+ hmacObject->attributes.hmacSeq = SET;
+#if !SMAC_IMPLEMENTED
+ if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg,
+ keyObject->sensitive.sensitive.bits.b.size,
+ keyObject->sensitive.sensitive.bits.b.buffer) == 0)
+#else
+ if(CryptMacStart(&hmacObject->state.hmacState,
+ &keyObject->publicArea.parameters,
+ hashAlg, &keyObject->sensitive.sensitive.any.b) == 0)
+#endif // SMAC_IMPLEMENTED
+ return TPM_RC_FAILURE;
+ return TPM_RC_SUCCESS;
+}
+#endif
+
+/* 8.6.3.18 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 = AllocateSequenceSlot(newHandle, auth);
+ // See if slot allocated
+ if(hashObject == NULL)
+ return TPM_RC_OBJECT_MEMORY;
+ // Set hash sequence bit
+ hashObject->attributes.hashSeq = SET;
+ // Start hash for hash sequence
+ CryptHashStart(&hashObject->state.hashState[0], hashAlg);
+ return TPM_RC_SUCCESS;
+}
+/* 8.6.3.19 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 = AllocateSequenceSlot(newHandle, auth);
+ UINT32 count;
+ TPM_ALG_ID hash;
+ // See if slot allocated
+ if(hashObject == NULL)
+ 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 = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++)
+ CryptHashStart(&hashObject->state.hashState[count], hash);
+ return TPM_RC_SUCCESS;
+}
+/* 8.6.3.20 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 *)HandleToObject(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 cryptographic implementation has some context values that need to be
+ // cleaned up (hygiene).
+ //
+ for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++)
+ {
+ CryptHashEnd(&hashObject->state.hashState[count], 0, buffer);
+ }
+ // Flush sequence object
+ FlushObject(g_DRTMHandle);
+ }
+ g_DRTMHandle = TPM_RH_UNASSIGNED;
+}
+/* 8.6.3.21 ObjectContextLoad() */
+/* This function loads an object from a saved object context. */
+/* Return Values Meaning */
+/* NULL if there is no free slot for an object */
+/* NON_NULL points to the loaded object */
+#if 0 // libtpms added
+OBJECT *
+ObjectContextLoad(
+ ANY_OBJECT_BUFFER *object, // IN: pointer to object structure in saved
+ // context
+ TPMI_DH_OBJECT *handle // OUT: object handle
+ )
+{
+ OBJECT *newObject = ObjectAllocateSlot(handle);
+ // Try to allocate a slot for new object
+ if(newObject != NULL)
+ {
+ // Copy the first part of the object
+ MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state));
+ // See if this is a sequence object
+ if(ObjectIsSequence(newObject))
+ {
+ // If this is a sequence object, import the data
+ SequenceDataImport((HASH_OBJECT *)newObject,
+ (HASH_OBJECT_BUFFER *)object);
+ }
+ else
+ {
+ // Copy input object data to internal structure
+ MemoryCopy(newObject, object, sizeof(OBJECT));
+ }
+ }
+ return newObject;
+}
+#endif // libtpms added begin
+
+OBJECT *
+ObjectContextLoadLibtpms(BYTE *buffer,
+ INT32 size,
+ TPMI_DH_OBJECT *handle
+ )
+{
+ OBJECT *newObject = ObjectAllocateSlot(handle);
+ TPM_RC rc;
+ BYTE *mybuf = buffer;
+ INT32 mysize = size;
+
+ pAssert(handle);
+
+ // Try to allocate a slot for new object
+ if(newObject != NULL)
+ {
+ rc = ANY_OBJECT_Unmarshal(newObject, &mybuf, &mysize, false);
+ if (rc) {
+ /* Attempt to load an old OBJECT that was copied out directly from
+ * an older version of OBJECT.
+ */
+ rc = OLD_OBJECTToOBJECT(newObject, buffer, size);
+ if (rc) {
+ FlushObject(*handle);
+ newObject = NULL;
+ }
+ }
+ }
+ return newObject;
+} // libtpms added end
+
+/* 8.6.3.22 FlushObject() */
+/* This function frees an object slot. */
+/* This function requires that the object is loaded. */
+void
+FlushObject(
+ TPMI_DH_OBJECT handle // IN: handle to be freed
+ )
+{
+ UINT32 index = handle - TRANSIENT_FIRST;
+ pAssert(index < MAX_LOADED_OBJECTS);
+ // Clear all the object attributes
+ MemorySet((BYTE*)&(s_objects[index].attributes),
+ 0, sizeof(OBJECT_ATTRIBUTES));
+ return;
+}
+/* 8.6.3.23 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].attributes.occupied) // If found an occupied slot
+ {
+ switch(hierarchy)
+ {
+ case TPM_RH_PLATFORM:
+ if(s_objects[i].attributes.ppsHierarchy == SET)
+ s_objects[i].attributes.occupied = FALSE;
+ break;
+ case TPM_RH_OWNER:
+ if(s_objects[i].attributes.spsHierarchy == SET)
+ s_objects[i].attributes.occupied = FALSE;
+ break;
+ case TPM_RH_ENDORSEMENT:
+ if(s_objects[i].attributes.epsHierarchy == SET)
+ s_objects[i].attributes.occupied = FALSE;
+ break;
+ default:
+ FAIL(FATAL_ERROR_INTERNAL);
+ break;
+ }
+ }
+ }
+ return;
+}
+/* 8.6.3.24 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
+ COMMAND_INDEX commandIndex // 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
+ object = ObjectAllocateSlot(handle);
+ if(object == NULL)
+ 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(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT
+ && gc.ehEnable == CLEAR
+ && GetCommandCode(commandIndex) != TPM_CC_EvictControl)
+ return TPM_RC_HANDLE;
+ return result;
+}
+/* 8.6.3.25 ObjectComputeName() */
+/* This does the name computation from a public area (can be marshaled or not). */
+TPM2B_NAME *
+ObjectComputeName(
+ UINT32 size, // IN: the size of the area to digest
+ BYTE *publicArea, // IN: the public area to digest
+ TPM_ALG_ID nameAlg, // IN: the hash algorithm to use
+ TPM2B_NAME *name // OUT: Computed name
+ )
+{
+ // Hash the publicArea into the name buffer leaving room for the nameAlg
+ name->t.size = CryptHashBlock(nameAlg, size, publicArea,
+ sizeof(name->t.name) - 2,
+ &name->t.name[2]);
+ // set the nameAlg
+ UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name);
+ name->t.size += 2;
+ return name;
+}
+/* 8.6.3.26 PublicMarshalAndComputeName() */
+/* This function computes the Name of an object from its public area. */
+TPM2B_NAME *
+PublicMarshalAndComputeName(
+ TPMT_PUBLIC *publicArea, // IN: public area of an object
+ TPM2B_NAME *name // OUT: name of the object
+ )
+{
+ // Will marshal a public area into a template. This is because the internal
+ // format for a TPM2B_PUBLIC is a structure and not a simple BYTE buffer.
+ TPM2B_TEMPLATE marshaled; // this is big enough to hold a
+ // marshaled TPMT_PUBLIC
+ BYTE *buffer = (BYTE *)&marshaled.t.buffer;
+ // if the nameAlg is NULL then there is no name.
+ if(publicArea->nameAlg == TPM_ALG_NULL)
+ name->t.size = 0;
+ else
+ {
+ // Marshal the public area into its canonical form
+ marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL);
+ // and compute the name
+ ObjectComputeName(marshaled.t.size, marshaled.t.buffer,
+ publicArea->nameAlg, name);
+ }
+ return name;
+}
+/* 8.6.3.28 ComputeQualifiedName() */
+/* This function computes the qualified name of an object. */
+void
+ComputeQualifiedName(
+ TPM_HANDLE parentHandle, // IN: parent's handle
+ 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
+ TPM2B_NAME parentName;
+ if(parentHandle == TPM_RH_UNASSIGNED)
+ {
+ MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name));
+ *qualifiedName = *name;
+ }
+ else
+ {
+ GetQualifiedName(parentHandle, &parentName);
+ // QN_A = hash_A (QN of parent || NAME_A)
+ // Start hash
+ qualifiedName->t.size = CryptHashStart(&hashState, nameAlg);
+ // Add parent's qualified name
+ CryptDigestUpdate2B(&hashState, &parentName.b);
+ // Add self name
+ CryptDigestUpdate2B(&hashState, &name->b);
+ // Complete hash leaving room for the name algorithm
+ CryptHashEnd(&hashState, qualifiedName->t.size,
+ &qualifiedName->t.name[2]);
+ UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
+ qualifiedName->t.size += 2;
+ }
+ return;
+}
+/* 8.6.3.29 ObjectIsStorage() */
+/* This function determines if an object has the attributes associated with a parent. A parent is an
+ asymmetric or symmetric block cipher key that has its restricted and decrypt attributes SET, and
+ sign CLEAR. */
+/* Return Values 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 = HandleToObject(handle);
+ TPMT_PUBLIC *publicArea = ((object != NULL) ? &object->publicArea : NULL);
+ //
+ return (publicArea != NULL
+ && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
+ && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
+ && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
+ && (object->publicArea.type == ALG_RSA_VALUE
+ || object->publicArea.type == ALG_ECC_VALUE));
+}
+/* 8.6.3.30 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 Values 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].attributes.occupied == TRUE)
+ {
+ // A valid transient object can not be the copy of a persistent object
+ pAssert(s_objects[i].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;
+}
+/* 8.6.3.31 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].attributes.occupied == FALSE) num++;
+ }
+ return num;
+}
+/* 8.6.3.32 ObjectGetPublicAttributes() */
+/* Returns the attributes associated with an object handles. */
+TPMA_OBJECT
+ObjectGetPublicAttributes(
+ TPM_HANDLE handle
+ )
+{
+ return HandleToObject(handle)->publicArea.objectAttributes;
+}
+#if 0 /* libtpms added */
+OBJECT_ATTRIBUTES
+ObjectGetProperties(
+ TPM_HANDLE handle
+ )
+{
+ return HandleToObject(handle)->attributes;
+}
+#endif /* libtpms added */