libtpms/src/tpm2/ObjectCommands.c
Stefan Berger b3a00577e8 rev180: Add HierarchyNormalizeHandle and use it
Add a simplified version of HierarchyNormalizeHandle that simply returns
the passed handle and sync the callers with upstream.
HierarchyNormalizeHandle will be extended at some later point.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2024-01-03 20:23:19 -05:00

684 lines
29 KiB
C

/********************************************************************************/
/* */
/* Object Commands */
/* Written by Ken Goldman */
/* IBM Thomas J. Watson Research Center */
/* */
/* 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 - 2023 */
/* */
/********************************************************************************/
#include "Tpm.h"
#include "Object_spt_fp.h"
#include "Create_fp.h"
#if CC_Create // Conditional expansion of this file
/*(See part 3 specification)
// Create a regular object
*/
// Return Type: TPM_RC
// TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data'
// is an Empty Buffer, or is SET when 'sensitive.data' is
// not empty;
// 'fixedTPM', 'fixedParent', or 'encryptedDuplication'
// attributes are inconsistent between themselves or with
// those of the parent object;
// inconsistent 'restricted', 'decrypt' and 'sign'
// attributes;
// attempt to inject sensitive data for an asymmetric
// key;
// TPM_RC_HASH non-duplicable storage key and its parent have
// different name algorithm
// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash
// object
// TPM_RC_KEY invalid key size values in an asymmetric key public
// area or a provided symmetric key has a value that is
// not allowed
// TPM_RC_KEY_SIZE key size in public area for symmetric key differs from
// the size in the sensitive creation area; may also be
// returned if the TPM does not allow the key size to be
// used for a Storage Key
// TPM_RC_OBJECT_MEMORY a free slot is not available as scratch memory for
// object creation
// TPM_RC_RANGE the exponent value of an RSA key is not supported.
// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign', or
// 'restricted' and key's scheme ID; or hash algorithm is
// inconsistent with the scheme ID for keyed hash object
// TPM_RC_SIZE size of public authPolicy or sensitive authValue does
// not match digest size of the name algorithm
// sensitive data size for the keyed hash object is
// larger than is allowed for the scheme
// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified;
// or non-storage key with symmetric algorithm different
// from TPM_ALG_NULL
// TPM_RC_TYPE unknown object type;
// 'parentHandle' does not reference a restricted
// decryption key in the storage hierarchy with both
// public and sensitive portion loaded
// TPM_RC_VALUE exponent is not prime or could not find a prime using
// the provided parameters for an RSA key;
// unsupported name algorithm for an ECC key
// TPM_RC_OBJECT_MEMORY there is no free slot for the object
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
result = TicketComputeCreation(EntityGetHierarchy(in->parentHandle),
&newObject->name,
&out->creationHash,
&out->creationTicket);
if(result != TPM_RC_SUCCESS)
return result;
// 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
/*(See part 3 of specification)
* Create and load any type of key, including a temporary key.
* The input template is a marshaled public area rather than an unmarshaled one as
* used in Create and CreatePrimary. This is so that the label and context that
* could be in the template can be processed without changing the formats for the
* calls to Create and CreatePrimary.
*/
// Return Type: TPM_RC
// TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data'
// is an Empty Buffer;
// 'fixedTPM', 'fixedParent', or 'encryptedDuplication'
// attributes are inconsistent between themselves or with
// those of the parent object;
// inconsistent 'restricted', 'decrypt' and 'sign'
// attributes;
// attempt to inject sensitive data for an asymmetric
// key;
// attempt to create a symmetric cipher key that is not
// a decryption key
// TPM_RC_FW_LIMITED The requested hierarchy is FW-limited, but the TPM
// does not support FW-limited objects or the TPM failed
// to derive the Firmware Secret.
// TPM_RC_SVN_LIMITED The requested hierarchy is SVN-limited, but the TPM
// does not support SVN-limited objects or the TPM failed
// to derive the Firmware SVN Secret for the requested
// SVN.
// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash
// object
// TPM_RC_KEY the value of a provided symmetric key is not allowed
// TPM_RC_OBJECT_MEMORY there is no free slot for the object
// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign',
// 'restricted' and key's scheme ID; or hash algorithm is
// inconsistent with the scheme ID for keyed hash object
// TPM_RC_SIZE size of public authorization policy or sensitive
// authorization value does not match digest size of the
// name algorithm sensitive data size for the keyed hash
// object is larger than is allowed for the scheme
// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified;
// or non-storage key with symmetric algorithm different
// from TPM_ALG_NULL
// TPM_RC_TYPE cannot create the object of the indicated type
// (usually only occurs if trying to derive an RSA key).
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 rest 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;
TPM2B_SEED primary_seed;
newObject->attributes.primary = SET;
if(HierarchyNormalizeHandle(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 = HierarchyGetPrimarySeed(in->parentHandle, &primary_seed);
if(result != TPM_RC_SUCCESS)
return result;
// If so, use the primary seed and the digest of the template
// to seed the DRBG
result = DRBG_InstantiateSeeded(
(DRBG_STATE*)rand,
&primary_seed.b,
PRIMARY_OBJECT_CREATION,
(TPM2B*)PublicMarshalAndComputeName(publicArea, &name),
&in->inSensitive.sensitive.data.b,
seedCompatLevel); // libtpms added
MemorySet(primary_seed.b.buffer, 0, primary_seed.b.size);
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