Line | Count | Source |
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 | 0 | { |
73 | |
|
74 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
75 | 0 | OBJECT *parentObject; |
76 | 0 | TPM2B_DATA data; // symmetric key |
77 | 0 | TPMT_SENSITIVE sensitive; |
78 | 0 | TPM2B_NAME name; |
79 | |
|
80 | 0 | UINT16 innerKeySize = 0; // encrypt key size for inner |
81 | | // wrapper |
82 | | |
83 | | // Input Validation |
84 | | |
85 | | // FixedTPM and fixedParent must be CLEAR |
86 | 0 | if( in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET |
87 | 0 | || in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET) |
88 | 0 | return TPM_RC_ATTRIBUTES + RC_Import_objectPublic; |
89 | | |
90 | | // Get parent pointer |
91 | 0 | parentObject = ObjectGet(in->parentHandle); |
92 | |
|
93 | 0 | if(!AreAttributesForParent(parentObject)) |
94 | 0 | return TPM_RC_TYPE + RC_Import_parentHandle; |
95 | | |
96 | 0 | if(in->symmetricAlg.algorithm != TPM_ALG_NULL) |
97 | 0 | { |
98 | | // Get inner wrap key size |
99 | 0 | innerKeySize = in->symmetricAlg.keyBits.sym; |
100 | | // Input symmetric key must match the size of algorithm. |
101 | 0 | if(in->encryptionKey.t.size != (innerKeySize + 7) / 8) |
102 | 0 | return TPM_RC_SIZE + RC_Import_encryptionKey; |
103 | 0 | } |
104 | 0 | else |
105 | 0 | { |
106 | | // If input symmetric algorithm is NULL, input symmetric key size must |
107 | | // be 0 as well |
108 | 0 | if(in->encryptionKey.t.size != 0) |
109 | 0 | return TPM_RC_SIZE + RC_Import_encryptionKey; |
110 | | // If encryptedDuplication is SET, then the object must have an inner |
111 | | // wrapper |
112 | 0 | if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication) |
113 | 0 | return TPM_RC_ATTRIBUTES + RC_Import_encryptionKey; |
114 | 0 | } |
115 | | |
116 | | // See if there is an outer wrapper |
117 | 0 | if(in->inSymSeed.t.size != 0) |
118 | 0 | { |
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 | 0 | result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE", |
123 | 0 | &in->inSymSeed, &data); |
124 | 0 | pAssert(result != TPM_RC_BINDING); |
125 | | // |
126 | 0 | if(result != TPM_RC_SUCCESS) |
127 | 0 | return RcSafeAddToResult(result, RC_Import_inSymSeed); |
128 | 0 | } |
129 | 0 | else |
130 | 0 | { |
131 | | // If encrytpedDuplication is set, then the object must have an outer |
132 | | // wrapper |
133 | 0 | if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication) |
134 | 0 | return TPM_RC_ATTRIBUTES + RC_Import_inSymSeed; |
135 | 0 | data.t.size = 0; |
136 | 0 | } |
137 | | |
138 | | // Compute name of object |
139 | 0 | 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 | 0 | result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle, |
144 | 0 | in->objectPublic.t.publicArea.nameAlg, |
145 | 0 | (TPM2B_SEED *) &data, &in->symmetricAlg, |
146 | 0 | &in->encryptionKey, &sensitive); |
147 | 0 | if(result != TPM_RC_SUCCESS) |
148 | 0 | 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 | 0 | if(parentObject->publicArea.objectAttributes.fixedTPM == SET) |
153 | 0 | { |
154 | 0 | 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 | 0 | result = PublicAttributesValidation(TRUE, in->parentHandle, |
161 | 0 | &in->objectPublic.t.publicArea); |
162 | 0 | if(result != TPM_RC_SUCCESS) |
163 | 0 | 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 | 0 | result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea, |
168 | 0 | &sensitive, NULL, in->parentHandle, FALSE, |
169 | 0 | &objectHandle); |
170 | 0 | if(result != TPM_RC_SUCCESS) |
171 | 0 | return result; |
172 | | |
173 | | // Don't need the object, just needed the checks to be performed so |
174 | | // flush the object |
175 | 0 | ObjectFlush(objectHandle); |
176 | 0 | } |
177 | | |
178 | | // Command output |
179 | | |
180 | | // Prepare output private data from sensitive |
181 | 0 | SensitiveToPrivate(&sensitive, &name, in->parentHandle, |
182 | 0 | in->objectPublic.t.publicArea.nameAlg, |
183 | 0 | &out->outPrivate); |
184 | |
|
185 | 0 | return TPM_RC_SUCCESS; |
186 | 0 | } |