blob: ced7e4dd488e34e888775cf6cb7f63cd21171f4b [file] [log] [blame]
/* Microsoft Reference Implementation for TPM 2.0
*
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and
* contributor rights, including patent rights, and no such rights are granted
* under this license.
*
* Copyright (c) Microsoft Corporation
*
* All rights reserved.
*
* BSD License
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#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_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;
// 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.xor.hashAlg != TPM_ALG_NULL
&& scheme->details.xor.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.xor.hashAlg,
scheme->details.xor.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;
}
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;
// 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);
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);
return result;
}
#endif // CC_CreateLoaded