summaryrefslogtreecommitdiffstats
path: root/src/tpm2/ObjectCommands.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tpm2/ObjectCommands.c549
1 files changed, 549 insertions, 0 deletions
diff --git a/src/tpm2/ObjectCommands.c b/src/tpm2/ObjectCommands.c
new file mode 100644
index 0000000..27f6637
--- /dev/null
+++ b/src/tpm2/ObjectCommands.c
@@ -0,0 +1,549 @@
+/********************************************************************************/
+/* */
+/* Object Commands */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: ObjectCommands.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 */
+/* */
+/********************************************************************************/
+
+#include "Tpm.h"
+#include "Object_spt_fp.h"
+#include "Create_fp.h"
+#if CC_Create // Conditional expansion of this file
+TPM_RC
+TPM2_Create(
+ Create_In *in, // IN: input parameter list
+ Create_Out *out // OUT: output parameter list
+ )
+{
+ TPM_RC result = TPM_RC_SUCCESS;
+ OBJECT *parentObject;
+ OBJECT *newObject;
+ TPMT_PUBLIC *publicArea;
+ // Input Validation
+ parentObject = HandleToObject(in->parentHandle);
+ pAssert(parentObject != NULL);
+ // Does parent have the proper attributes?
+ if(!ObjectIsParent(parentObject))
+ return TPM_RCS_TYPE + RC_Create_parentHandle;
+ // Get a slot for the creation
+ newObject = FindEmptyObjectSlot(NULL);
+ if(newObject == NULL)
+ return TPM_RC_OBJECT_MEMORY;
+ // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical
+ // form for processing
+ // to save typing.
+ publicArea = &newObject->publicArea;
+ // Copy the input structure to the allocated structure
+ *publicArea = in->inPublic.publicArea;
+ // Check attributes in input public area. CreateChecks() checks the things that
+ // are unique to creation and then validates the attributes and values that are
+ // common to create and load.
+ result = CreateChecks(parentObject, publicArea,
+ in->inSensitive.sensitive.data.t.size);
+ if(result != TPM_RC_SUCCESS)
+ return RcSafeAddToResult(result, RC_Create_inPublic);
+ // Clean up the authValue if necessary
+ if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
+ return TPM_RCS_SIZE + RC_Create_inSensitive;
+ // Command Output
+ // Create the object using the default TPM random-number generator
+ result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL);
+ if(result != TPM_RC_SUCCESS)
+ return result;
+ // Fill in creation data
+ FillInCreationData(in->parentHandle, publicArea->nameAlg,
+ &in->creationPCR, &in->outsideInfo,
+ &out->creationData, &out->creationHash);
+ // Compute creation ticket
+ TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &newObject->name,
+ &out->creationHash, &out->creationTicket);
+ // Prepare output private data from sensitive
+ SensitiveToPrivate(&newObject->sensitive, &newObject->name, parentObject,
+ publicArea->nameAlg,
+ &out->outPrivate);
+ // Finish by copying the remaining return values
+ out->outPublic.publicArea = newObject->publicArea;
+ return TPM_RC_SUCCESS;
+}
+#endif // CC_Create
+#include "Tpm.h"
+#include "Load_fp.h"
+#if CC_Load // Conditional expansion of this file
+#include "Object_spt_fp.h"
+TPM_RC
+TPM2_Load(
+ Load_In *in, // IN: input parameter list
+ Load_Out *out // OUT: output parameter list
+ )
+{
+ TPM_RC result = TPM_RC_SUCCESS;
+ TPMT_SENSITIVE sensitive = {0}; // libtpms changed (valgrind)
+ OBJECT *parentObject;
+ OBJECT *newObject;
+ // Input Validation
+ // Don't get invested in loading if there is no place to put it.
+ newObject = FindEmptyObjectSlot(&out->objectHandle);
+ if(newObject == NULL)
+ return TPM_RC_OBJECT_MEMORY;
+ if(in->inPrivate.t.size == 0)
+ return TPM_RCS_SIZE + RC_Load_inPrivate;
+ parentObject = HandleToObject(in->parentHandle);
+ pAssert(parentObject != NULL);
+ // Is the object that is being used as the parent actually a parent.
+ if(!ObjectIsParent(parentObject))
+ return TPM_RCS_TYPE + RC_Load_parentHandle;
+ // Compute the name of object. If there isn't one, it is because the nameAlg is
+ // not valid.
+ PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name);
+ if(out->name.t.size == 0)
+ return TPM_RCS_HASH + RC_Load_inPublic;
+ // Retrieve sensitive data.
+ result = PrivateToSensitive(&in->inPrivate.b, &out->name.b, parentObject,
+ in->inPublic.publicArea.nameAlg,
+ &sensitive);
+ if(result != TPM_RC_SUCCESS)
+ return RcSafeAddToResult(result, RC_Load_inPrivate);
+ // Internal Data Update
+ // Load and validate object
+ result = ObjectLoad(newObject, parentObject,
+ &in->inPublic.publicArea, &sensitive,
+ RC_Load_inPublic, RC_Load_inPrivate,
+ &out->name);
+ if(result == TPM_RC_SUCCESS)
+ {
+ // Set the common OBJECT attributes for a loaded object.
+ ObjectSetLoadedAttributes(newObject, in->parentHandle,
+ parentObject->seedCompatLevel); // libtpms added
+ }
+ return result;
+}
+#endif // CC_Load
+#include "Tpm.h"
+#include "LoadExternal_fp.h"
+#if CC_LoadExternal // Conditional expansion of this file
+#include "Object_spt_fp.h"
+TPM_RC
+TPM2_LoadExternal(
+ LoadExternal_In *in, // IN: input parameter list
+ LoadExternal_Out *out // OUT: output parameter list
+ )
+{
+ TPM_RC result;
+ OBJECT *object;
+ TPMT_SENSITIVE *sensitive = NULL;
+ // Input Validation
+ // Don't get invested in loading if there is no place to put it.
+ object = FindEmptyObjectSlot(&out->objectHandle);
+ if(object == NULL)
+ return TPM_RC_OBJECT_MEMORY;
+ // If the hierarchy to be associated with this object is turned off, the object
+ // cannot be loaded.
+ if(!HierarchyIsEnabled(in->hierarchy))
+ return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy;
+ // For loading an object with both public and sensitive
+ if(in->inPrivate.size != 0)
+ {
+ // An external object with a sensitive area can only be loaded in the
+ // NULL hierarchy
+ if(in->hierarchy != TPM_RH_NULL)
+ return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy;
+ // An external object with a sensitive area must have fixedTPM == CLEAR
+ // fixedParent == CLEAR so that it does not appear to be a key created by
+ // this TPM.
+ if(IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)
+ || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT,
+ fixedParent)
+ || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT,
+ restricted))
+ return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic;
+ // Have sensitive point to something other than NULL so that object
+ // initialization will load the sensitive part too
+ sensitive = &in->inPrivate.sensitiveArea;
+ }
+ // Need the name to initialize the object structure
+ PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name);
+ // Load and validate key
+ result = ObjectLoad(object, NULL,
+ &in->inPublic.publicArea, sensitive,
+ RC_LoadExternal_inPublic, RC_LoadExternal_inPrivate,
+ &out->name);
+ if(result == TPM_RC_SUCCESS)
+ {
+ object->attributes.external = SET;
+ // Set the common OBJECT attributes for a loaded object.
+ ObjectSetLoadedAttributes(object, in->hierarchy,
+ // if anything can be derived from an external object,
+ // we make sure it always uses the old algorithm
+ SEED_COMPAT_LEVEL_ORIGINAL); // libtpms added
+ }
+ return result;
+}
+#endif // CC_LoadExternal
+#include "Tpm.h"
+#include "ReadPublic_fp.h"
+#if CC_ReadPublic // Conditional expansion of this file
+TPM_RC
+TPM2_ReadPublic(
+ ReadPublic_In *in, // IN: input parameter list
+ ReadPublic_Out *out // OUT: output parameter list
+ )
+{
+ OBJECT *object = HandleToObject(in->objectHandle);
+ // Input Validation
+ // Can not read public area of a sequence object
+ if(ObjectIsSequence(object))
+ return TPM_RC_SEQUENCE;
+ // Command Output
+ out->outPublic.publicArea = object->publicArea;
+ out->name = object->name;
+ out->qualifiedName = object->qualifiedName;
+ return TPM_RC_SUCCESS;
+}
+#endif // CC_ReadPublic
+#include "Tpm.h"
+#include "ActivateCredential_fp.h"
+#if CC_ActivateCredential // Conditional expansion of this file
+#include "Object_spt_fp.h"
+TPM_RC
+TPM2_ActivateCredential(
+ ActivateCredential_In *in, // IN: input parameter list
+ ActivateCredential_Out *out // OUT: output parameter list
+ )
+{
+ TPM_RC result = TPM_RC_SUCCESS;
+ OBJECT *object; // decrypt key
+ OBJECT *activateObject; // key associated with credential
+ TPM2B_DATA data; // credential data
+ // Input Validation
+ // Get decrypt key pointer
+ object = HandleToObject(in->keyHandle);
+ // Get certificated object pointer
+ activateObject = HandleToObject(in->activateHandle);
+ // input decrypt key must be an asymmetric, restricted decryption key
+ if(!CryptIsAsymAlgorithm(object->publicArea.type)
+ || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
+ || !IS_ATTRIBUTE(object->publicArea.objectAttributes,
+ TPMA_OBJECT, restricted))
+ return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle;
+ // Command output
+ // Decrypt input credential data via asymmetric decryption. A
+ // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
+ // point
+ result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data);
+ if(result != TPM_RC_SUCCESS)
+ {
+ if(result == TPM_RC_KEY)
+ return TPM_RC_FAILURE;
+ return RcSafeAddToResult(result, RC_ActivateCredential_secret);
+ }
+ // Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal
+ // errors may be returned at this point
+ result = CredentialToSecret(&in->credentialBlob.b,
+ &activateObject->name.b,
+ &data.b,
+ object,
+ &out->certInfo);
+ if(result != TPM_RC_SUCCESS)
+ return RcSafeAddToResult(result, RC_ActivateCredential_credentialBlob);
+ return TPM_RC_SUCCESS;
+}
+#endif // CC_ActivateCredential
+#include "Tpm.h"
+#include "MakeCredential_fp.h"
+#if CC_MakeCredential // Conditional expansion of this file
+#include "Object_spt_fp.h"
+TPM_RC
+TPM2_MakeCredential(
+ MakeCredential_In *in, // IN: input parameter list
+ MakeCredential_Out *out // OUT: output parameter list
+ )
+{
+ TPM_RC result = TPM_RC_SUCCESS;
+ OBJECT *object;
+ TPM2B_DATA data;
+ // Input Validation
+ // Get object pointer
+ object = HandleToObject(in->handle);
+ // input key must be an asymmetric, restricted decryption key
+ // NOTE: Needs to be restricted to have a symmetric value.
+ if(!CryptIsAsymAlgorithm(object->publicArea.type)
+ || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
+ || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
+ return TPM_RCS_TYPE + RC_MakeCredential_handle;
+ // The credential information may not be larger than the digest size used for
+ // the Name of the key associated with handle.
+ if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg))
+ return TPM_RCS_SIZE + RC_MakeCredential_credential;
+ // Command Output
+ // Make encrypt key and its associated secret structure.
+ out->secret.t.size = sizeof(out->secret.t.secret);
+ result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret);
+ if(result != TPM_RC_SUCCESS)
+ return result;
+ // Prepare output credential data from secret
+ SecretToCredential(&in->credential, &in->objectName.b, &data.b,
+ object, &out->credentialBlob);
+ return TPM_RC_SUCCESS;
+}
+#endif // CC_MakeCredential
+#include "Tpm.h"
+#include "Unseal_fp.h"
+#if CC_Unseal // Conditional expansion of this file
+TPM_RC
+TPM2_Unseal(
+ Unseal_In *in,
+ Unseal_Out *out
+ )
+{
+ OBJECT *object;
+ // Input Validation
+ // Get pointer to loaded object
+ object = HandleToObject(in->itemHandle);
+ // Input handle must be a data object
+ if(object->publicArea.type != TPM_ALG_KEYEDHASH)
+ return TPM_RCS_TYPE + RC_Unseal_itemHandle;
+ if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
+ || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
+ || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
+ return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle;
+ // Command Output
+ // Copy data
+ out->outData = object->sensitive.sensitive.bits;
+ return TPM_RC_SUCCESS;
+}
+#endif // CC_Unseal
+#include "Tpm.h"
+#include "ObjectChangeAuth_fp.h"
+#if CC_ObjectChangeAuth // Conditional expansion of this file
+#include "Object_spt_fp.h"
+TPM_RC
+TPM2_ObjectChangeAuth(
+ ObjectChangeAuth_In *in, // IN: input parameter list
+ ObjectChangeAuth_Out *out // OUT: output parameter list
+ )
+{
+ TPMT_SENSITIVE sensitive;
+ OBJECT *object = HandleToObject(in->objectHandle);
+ TPM2B_NAME QNCompare;
+ // Input Validation
+ // Can not change authorization on sequence object
+ if(ObjectIsSequence(object))
+ return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle;
+ // Make sure that the authorization value is consistent with the nameAlg
+ if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg))
+ return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth;
+ // Parent handle should be the parent of object handle. In this
+ // implementation we verify this by checking the QN of object. Other
+ // implementation may choose different method to verify this attribute.
+ ComputeQualifiedName(in->parentHandle,
+ object->publicArea.nameAlg,
+ &object->name, &QNCompare);
+ if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b))
+ return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle;
+ // Command Output
+ // Prepare the sensitive area with the new authorization value
+ sensitive = object->sensitive;
+ sensitive.authValue = in->newAuth;
+ // Protect the sensitive area
+ SensitiveToPrivate(&sensitive, &object->name, HandleToObject(in->parentHandle),
+ object->publicArea.nameAlg,
+ &out->outPrivate);
+ return TPM_RC_SUCCESS;
+}
+#endif // CC_ObjectChangeAuth
+#include "Tpm.h"
+#include "CreateLoaded_fp.h"
+#if CC_CreateLoaded // Conditional expansion of this file
+TPM_RC
+TPM2_CreateLoaded(
+ CreateLoaded_In *in, // IN: input parameter list
+ CreateLoaded_Out *out // OUT: output parameter list
+ )
+{
+ TPM_RC result = TPM_RC_SUCCESS;
+ OBJECT *parent = HandleToObject(in->parentHandle);
+ OBJECT *newObject;
+ BOOL derivation;
+ TPMT_PUBLIC *publicArea;
+ RAND_STATE randState;
+ RAND_STATE *rand = &randState;
+ TPMS_DERIVE labelContext;
+ SEED_COMPAT_LEVEL seedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added
+ // Input Validation
+ // How the public area is unmarshaled is determined by the parent, so
+ // see if parent is a derivation parent
+ derivation = (parent != NULL && parent->attributes.derivation);
+ // If the parent is an object, then make sure that it is either a parent or
+ // derivation parent
+ if(parent != NULL && !parent->attributes.isParent && !derivation)
+ return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle;
+ // Get a spot in which to create the newObject
+ newObject = FindEmptyObjectSlot(&out->objectHandle);
+ if(newObject == NULL)
+ return TPM_RC_OBJECT_MEMORY;
+ // Do this to save typing
+ publicArea = &newObject->publicArea;
+ // Unmarshal the template into the object space. TPM2_Create() and
+ // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher.
+ // This command is different because of an unfortunate property of the
+ // unique field of an ECC key. It is a structure rather than a single TPM2B. If
+ // if had been a TPM2B, then the label and context could be within a TPM2B and
+ // unmarshaled like other public areas. Since it is not, this command needs its
+ // on template that is a TPM2B that is unmarshaled as a BYTE array with a
+ // its own unmarshal function.
+ result = UnmarshalToPublic(publicArea, &in->inPublic, derivation,
+ &labelContext);
+ if(result != TPM_RC_SUCCESS)
+ return result + RC_CreateLoaded_inPublic;
+ // Validate that the authorization size is appropriate
+ if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
+ return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive;
+ // Command output
+ if(derivation)
+ {
+ TPMT_KEYEDHASH_SCHEME *scheme;
+ scheme = &parent->publicArea.parameters.keyedHashDetail.scheme;
+ // SP800-108 is the only KDF supported by this implementation and there is
+ // no default hash algorithm.
+ pAssert(scheme->details.xorr.hashAlg != TPM_ALG_NULL
+ && scheme->details.xorr.kdf == TPM_ALG_KDF1_SP800_108);
+ // Don't derive RSA keys
+ if(publicArea->type == TPM_ALG_RSA)
+ return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
+ // sensitiveDataOrigin has to be CLEAR in a derived object. Since this
+ // is specific to a derived object, it is checked here.
+ if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT,
+ sensitiveDataOrigin))
+ return TPM_RCS_ATTRIBUTES;
+ // Check the reset of the attributes
+ result = PublicAttributesValidation(parent, publicArea);
+ if(result != TPM_RC_SUCCESS)
+ return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
+ // Process the template and sensitive areas to get the actual 'label' and
+ // 'context' values to be used for this derivation.
+ result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
+ if(result != TPM_RC_SUCCESS)
+ return result;
+ // Set up the KDF for object generation
+ DRBG_InstantiateSeededKdf((KDF_STATE *)rand,
+ scheme->details.xorr.hashAlg,
+ scheme->details.xorr.kdf,
+ &parent->sensitive.sensitive.bits.b,
+ &labelContext.label.b,
+ &labelContext.context.b,
+ TPM_MAX_DERIVATION_BITS);
+ // Clear the sensitive size so that the creation functions will not try
+ // to use this value.
+ in->inSensitive.sensitive.data.t.size = 0;
+ seedCompatLevel = parent->seedCompatLevel; // libtpms added
+ }
+ else
+ {
+ // Check attributes in input public area. CreateChecks() checks the things
+ // that are unique to creation and then validates the attributes and values
+ // that are common to create and load.
+ result = CreateChecks(parent, publicArea,
+ in->inSensitive.sensitive.data.t.size);
+ if(result != TPM_RC_SUCCESS)
+ return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
+ // Creating a primary object
+ if(parent == NULL)
+ {
+ TPM2B_NAME name;
+ newObject->attributes.primary = SET;
+ if(in->parentHandle == TPM_RH_ENDORSEMENT)
+ newObject->attributes.epsHierarchy = SET;
+ seedCompatLevel =
+ HierarchyGetPrimarySeedCompatLevel(in->parentHandle); // libtpms added
+ // If so, use the primary seed and the digest of the template
+ // to seed the DRBG
+ result = DRBG_InstantiateSeeded((DRBG_STATE *)rand,
+ &HierarchyGetPrimarySeed(in->parentHandle)->b,
+ PRIMARY_OBJECT_CREATION,
+ (TPM2B *)PublicMarshalAndComputeName(publicArea,&name),
+ &in->inSensitive.sensitive.data.b,
+ seedCompatLevel); // libtpms added
+ if (result != TPM_RC_SUCCESS)
+ return result;
+ }
+ else
+ // This is an ordinary object so use the normal random number generator
+ rand = NULL;
+ }
+ // Internal data update
+ // Create the object
+ result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand);
+ if(result != TPM_RC_SUCCESS)
+ return result;
+ // if this is not a Primary key and not a derived key, then return the sensitive
+ // area
+ if(parent != NULL && !derivation)
+ // Prepare output private data from sensitive
+ SensitiveToPrivate(&newObject->sensitive, &newObject->name,
+ parent, newObject->publicArea.nameAlg,
+ &out->outPrivate);
+ else
+ out->outPrivate.t.size = 0;
+ // Set the remaining return values
+ out->outPublic.publicArea = newObject->publicArea;
+ out->name = newObject->name;
+ // Set the remaining attributes for a loaded object
+ ObjectSetLoadedAttributes(newObject, in->parentHandle,
+ seedCompatLevel); // libtpms added
+ return result;
+}
+#endif // CC_CreateLoaded