1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 3: Commands 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #include "InternalRoutines.h" 9 #include "Import_fp.h" 10 #include "Object_spt_fp.h" 11 // 12 // 13 // Error Returns Meaning 14 // 15 // TPM_RC_ASYMMETRIC non-duplicable storage key represented by objectPublic and its 16 // parent referenced by parentHandle have different public parameters 17 // TPM_RC_ATTRIBUTES attributes FixedTPM and fixedParent of objectPublic are not both 18 // CLEAR; or inSymSeed is nonempty and parentHandle does not 19 // reference a decryption key; or objectPublic and parentHandle have 20 // incompatible or inconsistent attributes; or encrytpedDuplication is 21 // SET in objectPublic but the inner or outer wrapper is missing. 22 // 23 // NOTE: if the TPM provides parameter values, the parameter number will indicate symmetricKey (missing 24 // inner wrapper) or inSymSeed (missing outer wrapper). 25 // 26 // 27 // TPM_RC_BINDING duplicate and objectPublic are not cryptographically 28 // bound 29 // 30 // TPM_RC_ECC_POINT inSymSeed is nonempty and ECC point in inSymSeed is not on the 31 // curve 32 // TPM_RC_HASH non-duplicable storage key represented by objectPublic and its 33 // parent referenced by parentHandle have different name algorithm 34 // TPM_RC_INSUFFICIENT inSymSeed is nonempty and failed to retrieve ECC point from the 35 // secret; or unmarshaling sensitive value from duplicate failed the 36 // result of inSymSeed decryption 37 // TPM_RC_INTEGRITY duplicate integrity is broken 38 // TPM_RC_KDF objectPublic representing decrypting keyed hash object specifies 39 // invalid KDF 40 // TPM_RC_KEY inconsistent parameters of objectPublic; or inSymSeed is nonempty 41 // and parentHandle does not reference a key of supported type; or 42 // invalid key size in objectPublic representing an asymmetric key 43 // TPM_RC_NO_RESULT inSymSeed is nonempty and multiplication resulted in ECC point at 44 // infinity 45 // TPM_RC_OBJECT_MEMORY no available object slot 46 // TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID 47 // in objectPublic; or hash algorithm is inconsistent with the scheme ID 48 // for keyed hash object 49 // TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in 50 // objectPublic; or symmetricAlg and encryptionKey have different 51 // sizes; or inSymSeed is nonempty and it size is not consistent with the 52 // type of parentHandle; or unmarshaling sensitive value from duplicate 53 // failed 54 // TPM_RC_SYMMETRIC objectPublic is either a storage key with no symmetric algorithm or a 55 // non-storage key with symmetric algorithm different from 56 // TPM_ALG_NULL 57 // TPM_RC_TYPE unsupported type of objectPublic; or non-duplicable storage key 58 // represented by objectPublic and its parent referenced by 59 // parentHandle are of different types; or parentHandle is not a storage 60 // key; or only the public portion of parentHandle is loaded; or 61 // objectPublic and duplicate are of different types 62 // TPM_RC_VALUE nonempty inSymSeed and its numeric value is greater than the 63 // modulus of the key referenced by parentHandle or inSymSeed is 64 // larger than the size of the digest produced by the name algorithm of 65 // the symmetric key referenced by parentHandle 66 // 67 TPM_RC 68 TPM2_Import( 69 Import_In *in, // IN: input parameter list 70 Import_Out *out // OUT: output parameter list 71 ) 72 { 73 74 TPM_RC result = TPM_RC_SUCCESS; 75 OBJECT *parentObject; 76 TPM2B_DATA data; // symmetric key 77 TPMT_SENSITIVE sensitive; 78 TPM2B_NAME name; 79 80 UINT16 innerKeySize = 0; // encrypt key size for inner 81 // wrapper 82 83 // Input Validation 84 85 // FixedTPM and fixedParent must be CLEAR 86 if( in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET 87 || in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET) 88 return TPM_RC_ATTRIBUTES + RC_Import_objectPublic; 89 90 // Get parent pointer 91 parentObject = ObjectGet(in->parentHandle); 92 93 if(!AreAttributesForParent(parentObject)) 94 return TPM_RC_TYPE + RC_Import_parentHandle; 95 96 if(in->symmetricAlg.algorithm != TPM_ALG_NULL) 97 { 98 // Get inner wrap key size 99 innerKeySize = in->symmetricAlg.keyBits.sym; 100 // Input symmetric key must match the size of algorithm. 101 if(in->encryptionKey.t.size != (innerKeySize + 7) / 8) 102 return TPM_RC_SIZE + RC_Import_encryptionKey; 103 } 104 else 105 { 106 // If input symmetric algorithm is NULL, input symmetric key size must 107 // be 0 as well 108 if(in->encryptionKey.t.size != 0) 109 return TPM_RC_SIZE + RC_Import_encryptionKey; 110 // If encryptedDuplication is SET, then the object must have an inner 111 // wrapper 112 if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication) 113 return TPM_RC_ATTRIBUTES + RC_Import_encryptionKey; 114 } 115 116 // See if there is an outer wrapper 117 if(in->inSymSeed.t.size != 0) 118 { 119 // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES, 120 // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT, 121 // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point 122 result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE", 123 &in->inSymSeed, &data); 124 pAssert(result != TPM_RC_BINDING); 125 // 126 if(result != TPM_RC_SUCCESS) 127 return RcSafeAddToResult(result, RC_Import_inSymSeed); 128 } 129 else 130 { 131 // If encrytpedDuplication is set, then the object must have an outer 132 // wrapper 133 if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication) 134 return TPM_RC_ATTRIBUTES + RC_Import_inSymSeed; 135 data.t.size = 0; 136 } 137 138 // Compute name of object 139 ObjectComputeName(&(in->objectPublic.t.publicArea), &name); 140 141 // Retrieve sensitive from private. 142 // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here. 143 result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle, 144 in->objectPublic.t.publicArea.nameAlg, 145 (TPM2B_SEED *) &data, &in->symmetricAlg, 146 &in->encryptionKey, &sensitive); 147 if(result != TPM_RC_SUCCESS) 148 return RcSafeAddToResult(result, RC_Import_duplicate); 149 150 // If the parent of this object has fixedTPM SET, then fully validate this 151 // object so that validation can be skipped when it is loaded 152 if(parentObject->publicArea.objectAttributes.fixedTPM == SET) 153 { 154 TPM_HANDLE objectHandle; 155 156 // Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME, 157 // TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH, 158 // TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned 159 // at this point 160 result = PublicAttributesValidation(TRUE, in->parentHandle, 161 &in->objectPublic.t.publicArea); 162 if(result != TPM_RC_SUCCESS) 163 return RcSafeAddToResult(result, RC_Import_objectPublic); 164 165 // Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or 166 // TPM_RC_OBJECT_MEMORY error may be returned at this point 167 result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea, 168 &sensitive, NULL, in->parentHandle, FALSE, 169 &objectHandle); 170 if(result != TPM_RC_SUCCESS) 171 return result; 172 173 // Don't need the object, just needed the checks to be performed so 174 // flush the object 175 ObjectFlush(objectHandle); 176 } 177 178 // Command output 179 180 // Prepare output private data from sensitive 181 SensitiveToPrivate(&sensitive, &name, in->parentHandle, 182 in->objectPublic.t.publicArea.nameAlg, 183 &out->outPrivate); 184 185 return TPM_RC_SUCCESS; 186 } 187