118 lines
4.1 KiB
C
118 lines
4.1 KiB
C
// This file was extracted from the TCG Published
|
|
// Trusted Platform Module Library
|
|
// Part 3: Commands
|
|
// Family "2.0"
|
|
// Level 00 Revision 01.16
|
|
// October 30, 2014
|
|
|
|
#include "InternalRoutines.h"
|
|
#include "Duplicate_fp.h"
|
|
#include "Object_spt_fp.h"
|
|
//
|
|
//
|
|
// Error Returns Meaning
|
|
//
|
|
// TPM_RC_ATTRIBUTES key to duplicate has fixedParent SET
|
|
// TPM_RC_HIERARCHY encryptedDuplication is SET and newParentHandle specifies Null
|
|
// Hierarchy
|
|
// TPM_RC_KEY newParentHandle references invalid ECC key (public point not on the
|
|
// curve)
|
|
// TPM_RC_SIZE input encryption key size does not match the size specified in
|
|
// symmetric algorithm
|
|
// TPM_RC_SYMMETRIC encryptedDuplication is SET but no symmetric algorithm is provided
|
|
// TPM_RC_TYPE newParentHandle is neither a storage key nor TPM_RH_NULL; or
|
|
// the object has a NULL nameAlg
|
|
//
|
|
TPM_RC
|
|
TPM2_Duplicate(
|
|
Duplicate_In *in, // IN: input parameter list
|
|
Duplicate_Out *out // OUT: output parameter list
|
|
)
|
|
{
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
TPMT_SENSITIVE sensitive;
|
|
|
|
UINT16 innerKeySize = 0; // encrypt key size for inner wrap
|
|
|
|
OBJECT *object;
|
|
TPM2B_DATA data;
|
|
|
|
// Input Validation
|
|
|
|
// Get duplicate object pointer
|
|
object = ObjectGet(in->objectHandle);
|
|
|
|
// duplicate key must have fixParent bit CLEAR.
|
|
if(object->publicArea.objectAttributes.fixedParent == SET)
|
|
return TPM_RC_ATTRIBUTES + RC_Duplicate_objectHandle;
|
|
|
|
// Do not duplicate object with NULL nameAlg
|
|
if(object->publicArea.nameAlg == TPM_ALG_NULL)
|
|
return TPM_RC_TYPE + RC_Duplicate_objectHandle;
|
|
|
|
// new parent key must be a storage object or TPM_RH_NULL
|
|
if(in->newParentHandle != TPM_RH_NULL
|
|
&& !ObjectIsStorage(in->newParentHandle))
|
|
return TPM_RC_TYPE + RC_Duplicate_newParentHandle;
|
|
|
|
// If the duplicates object has encryptedDuplication SET, then there must be
|
|
// an inner wrapper and the new parent may not be TPM_RH_NULL
|
|
if(object->publicArea.objectAttributes.encryptedDuplication == SET)
|
|
{
|
|
if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
|
|
return TPM_RC_SYMMETRIC + RC_Duplicate_symmetricAlg;
|
|
if(in->newParentHandle == TPM_RH_NULL)
|
|
return TPM_RC_HIERARCHY + RC_Duplicate_newParentHandle;
|
|
}
|
|
|
|
if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
|
|
{
|
|
// if algorithm is TPM_ALG_NULL, input key size must be 0
|
|
if(in->encryptionKeyIn.t.size != 0)
|
|
return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
|
|
}
|
|
else
|
|
{
|
|
// Get inner wrap key size
|
|
innerKeySize = in->symmetricAlg.keyBits.sym;
|
|
|
|
// If provided the input symmetric key must match the size of the algorithm
|
|
if(in->encryptionKeyIn.t.size != 0
|
|
&& in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
|
|
return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
|
|
}
|
|
|
|
// Command Output
|
|
|
|
if(in->newParentHandle != TPM_RH_NULL)
|
|
{
|
|
|
|
// Make encrypt key and its associated secret structure. A TPM_RC_KEY
|
|
// error may be returned at this point
|
|
out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
|
|
result = CryptSecretEncrypt(in->newParentHandle,
|
|
"DUPLICATE", &data, &out->outSymSeed);
|
|
pAssert(result != TPM_RC_VALUE);
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
// Do not apply outer wrapper
|
|
data.t.size = 0;
|
|
out->outSymSeed.t.size = 0;
|
|
}
|
|
|
|
// Copy sensitive area
|
|
sensitive = object->sensitive;
|
|
|
|
// Prepare output private data from sensitive
|
|
SensitiveToDuplicate(&sensitive, &object->name, in->newParentHandle,
|
|
object->publicArea.nameAlg, (TPM2B_SEED *) &data,
|
|
&in->symmetricAlg, &in->encryptionKeyIn,
|
|
&out->duplicate);
|
|
|
|
out->encryptionKeyOut = in->encryptionKeyIn;
|
|
|
|
return TPM_RC_SUCCESS;
|
|
}
|