// 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; }