Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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_RCS_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_RCS_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_RCS_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 | } |