You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
9.2 KiB
186 lines
9.2 KiB
// 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 "Import_fp.h" |
|
#include "Object_spt_fp.h" |
|
// |
|
// |
|
// Error Returns Meaning |
|
// |
|
// TPM_RC_ASYMMETRIC non-duplicable storage key represented by objectPublic and its |
|
// parent referenced by parentHandle have different public parameters |
|
// TPM_RC_ATTRIBUTES attributes FixedTPM and fixedParent of objectPublic are not both |
|
// CLEAR; or inSymSeed is nonempty and parentHandle does not |
|
// reference a decryption key; or objectPublic and parentHandle have |
|
// incompatible or inconsistent attributes; or encrytpedDuplication is |
|
// SET in objectPublic but the inner or outer wrapper is missing. |
|
// |
|
// NOTE: if the TPM provides parameter values, the parameter number will indicate symmetricKey (missing |
|
// inner wrapper) or inSymSeed (missing outer wrapper). |
|
// |
|
// |
|
// TPM_RC_BINDING duplicate and objectPublic are not cryptographically |
|
// bound |
|
// |
|
// TPM_RC_ECC_POINT inSymSeed is nonempty and ECC point in inSymSeed is not on the |
|
// curve |
|
// TPM_RC_HASH non-duplicable storage key represented by objectPublic and its |
|
// parent referenced by parentHandle have different name algorithm |
|
// TPM_RC_INSUFFICIENT inSymSeed is nonempty and failed to retrieve ECC point from the |
|
// secret; or unmarshaling sensitive value from duplicate failed the |
|
// result of inSymSeed decryption |
|
// TPM_RC_INTEGRITY duplicate integrity is broken |
|
// TPM_RC_KDF objectPublic representing decrypting keyed hash object specifies |
|
// invalid KDF |
|
// TPM_RC_KEY inconsistent parameters of objectPublic; or inSymSeed is nonempty |
|
// and parentHandle does not reference a key of supported type; or |
|
// invalid key size in objectPublic representing an asymmetric key |
|
// TPM_RC_NO_RESULT inSymSeed is nonempty and multiplication resulted in ECC point at |
|
// infinity |
|
// TPM_RC_OBJECT_MEMORY no available object slot |
|
// TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID |
|
// in objectPublic; or hash algorithm is inconsistent with the scheme ID |
|
// for keyed hash object |
|
// TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in |
|
// objectPublic; or symmetricAlg and encryptionKey have different |
|
// sizes; or inSymSeed is nonempty and it size is not consistent with the |
|
// type of parentHandle; or unmarshaling sensitive value from duplicate |
|
// failed |
|
// TPM_RC_SYMMETRIC objectPublic is either a storage key with no symmetric algorithm or a |
|
// non-storage key with symmetric algorithm different from |
|
// TPM_ALG_NULL |
|
// TPM_RC_TYPE unsupported type of objectPublic; or non-duplicable storage key |
|
// represented by objectPublic and its parent referenced by |
|
// parentHandle are of different types; or parentHandle is not a storage |
|
// key; or only the public portion of parentHandle is loaded; or |
|
// objectPublic and duplicate are of different types |
|
// TPM_RC_VALUE nonempty inSymSeed and its numeric value is greater than the |
|
// modulus of the key referenced by parentHandle or inSymSeed is |
|
// larger than the size of the digest produced by the name algorithm of |
|
// the symmetric key referenced by parentHandle |
|
// |
|
TPM_RC |
|
TPM2_Import( |
|
Import_In *in, // IN: input parameter list |
|
Import_Out *out // OUT: output parameter list |
|
) |
|
{ |
|
|
|
TPM_RC result = TPM_RC_SUCCESS; |
|
OBJECT *parentObject; |
|
TPM2B_DATA data; // symmetric key |
|
TPMT_SENSITIVE sensitive; |
|
TPM2B_NAME name; |
|
|
|
UINT16 innerKeySize = 0; // encrypt key size for inner |
|
// wrapper |
|
|
|
// Input Validation |
|
|
|
// FixedTPM and fixedParent must be CLEAR |
|
if( in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET |
|
|| in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET) |
|
return TPM_RC_ATTRIBUTES + RC_Import_objectPublic; |
|
|
|
// Get parent pointer |
|
parentObject = ObjectGet(in->parentHandle); |
|
|
|
if(!AreAttributesForParent(parentObject)) |
|
return TPM_RC_TYPE + RC_Import_parentHandle; |
|
|
|
if(in->symmetricAlg.algorithm != TPM_ALG_NULL) |
|
{ |
|
// Get inner wrap key size |
|
innerKeySize = in->symmetricAlg.keyBits.sym; |
|
// Input symmetric key must match the size of algorithm. |
|
if(in->encryptionKey.t.size != (innerKeySize + 7) / 8) |
|
return TPM_RC_SIZE + RC_Import_encryptionKey; |
|
} |
|
else |
|
{ |
|
// If input symmetric algorithm is NULL, input symmetric key size must |
|
// be 0 as well |
|
if(in->encryptionKey.t.size != 0) |
|
return TPM_RC_SIZE + RC_Import_encryptionKey; |
|
// If encryptedDuplication is SET, then the object must have an inner |
|
// wrapper |
|
if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication) |
|
return TPM_RC_ATTRIBUTES + RC_Import_encryptionKey; |
|
} |
|
|
|
// See if there is an outer wrapper |
|
if(in->inSymSeed.t.size != 0) |
|
{ |
|
// Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES, |
|
// TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT, |
|
// TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point |
|
result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE", |
|
&in->inSymSeed, &data); |
|
pAssert(result != TPM_RC_BINDING); |
|
// |
|
if(result != TPM_RC_SUCCESS) |
|
return RcSafeAddToResult(result, RC_Import_inSymSeed); |
|
} |
|
else |
|
{ |
|
// If encrytpedDuplication is set, then the object must have an outer |
|
// wrapper |
|
if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication) |
|
return TPM_RC_ATTRIBUTES + RC_Import_inSymSeed; |
|
data.t.size = 0; |
|
} |
|
|
|
// Compute name of object |
|
ObjectComputeName(&(in->objectPublic.t.publicArea), &name); |
|
|
|
// Retrieve sensitive from private. |
|
// TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here. |
|
result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle, |
|
in->objectPublic.t.publicArea.nameAlg, |
|
(TPM2B_SEED *) &data, &in->symmetricAlg, |
|
&in->encryptionKey, &sensitive); |
|
if(result != TPM_RC_SUCCESS) |
|
return RcSafeAddToResult(result, RC_Import_duplicate); |
|
|
|
// If the parent of this object has fixedTPM SET, then fully validate this |
|
// object so that validation can be skipped when it is loaded |
|
if(parentObject->publicArea.objectAttributes.fixedTPM == SET) |
|
{ |
|
TPM_HANDLE objectHandle; |
|
|
|
// Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME, |
|
// TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH, |
|
// TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned |
|
// at this point |
|
result = PublicAttributesValidation(TRUE, in->parentHandle, |
|
&in->objectPublic.t.publicArea); |
|
if(result != TPM_RC_SUCCESS) |
|
return RcSafeAddToResult(result, RC_Import_objectPublic); |
|
|
|
// Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or |
|
// TPM_RC_OBJECT_MEMORY error may be returned at this point |
|
result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea, |
|
&sensitive, NULL, in->parentHandle, FALSE, |
|
&objectHandle); |
|
if(result != TPM_RC_SUCCESS) |
|
return result; |
|
|
|
// Don't need the object, just needed the checks to be performed so |
|
// flush the object |
|
ObjectFlush(objectHandle); |
|
} |
|
|
|
// Command output |
|
|
|
// Prepare output private data from sensitive |
|
SensitiveToPrivate(&sensitive, &name, in->parentHandle, |
|
in->objectPublic.t.publicArea.nameAlg, |
|
&out->outPrivate); |
|
|
|
return TPM_RC_SUCCESS; |
|
}
|
|
|