/src/ibmswtpm2/src/ObjectCommands.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Object Commands */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: ObjectCommands.c 1259 2018-07-10 19:11:09Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | #include "Tpm.h" |
63 | | #include "Object_spt_fp.h" |
64 | | #include "Create_fp.h" |
65 | | #if CC_Create // Conditional expansion of this file |
66 | | TPM_RC |
67 | | TPM2_Create( |
68 | | Create_In *in, // IN: input parameter list |
69 | | Create_Out *out // OUT: output parameter list |
70 | | ) |
71 | 0 | { |
72 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
73 | 0 | OBJECT *parentObject; |
74 | 0 | OBJECT *newObject; |
75 | 0 | TPMT_PUBLIC *publicArea; |
76 | | // Input Validation |
77 | 0 | parentObject = HandleToObject(in->parentHandle); |
78 | 0 | pAssert(parentObject != NULL); |
79 | | // Does parent have the proper attributes? |
80 | 0 | if(!ObjectIsParent(parentObject)) |
81 | 0 | return TPM_RCS_TYPE + RC_Create_parentHandle; |
82 | | // Get a slot for the creation |
83 | 0 | newObject = FindEmptyObjectSlot(NULL); |
84 | 0 | if(newObject == NULL) |
85 | 0 | return TPM_RC_OBJECT_MEMORY; |
86 | | // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical |
87 | | // form for processing |
88 | | // to save typing. |
89 | 0 | publicArea = &newObject->publicArea; |
90 | | // Copy the input structure to the allocated structure |
91 | 0 | *publicArea = in->inPublic.publicArea; |
92 | | // Check attributes in input public area. CreateChecks() checks the things that |
93 | | // are unique to creation and then validates the attributes and values that are |
94 | | // common to create and load. |
95 | 0 | result = CreateChecks(parentObject, publicArea, |
96 | 0 | in->inSensitive.sensitive.data.t.size); |
97 | 0 | if(result != TPM_RC_SUCCESS) |
98 | 0 | return RcSafeAddToResult(result, RC_Create_inPublic); |
99 | | // Clean up the authValue if necessary |
100 | 0 | if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) |
101 | 0 | return TPM_RCS_SIZE + RC_Create_inSensitive; |
102 | | // Command Output |
103 | | // Create the object using the default TPM random-number generator |
104 | 0 | result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL); |
105 | 0 | if(result != TPM_RC_SUCCESS) |
106 | 0 | return result; |
107 | | // Fill in creation data |
108 | 0 | FillInCreationData(in->parentHandle, publicArea->nameAlg, |
109 | 0 | &in->creationPCR, &in->outsideInfo, |
110 | 0 | &out->creationData, &out->creationHash); |
111 | | // Compute creation ticket |
112 | 0 | TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &newObject->name, |
113 | 0 | &out->creationHash, &out->creationTicket); |
114 | | // Prepare output private data from sensitive |
115 | 0 | SensitiveToPrivate(&newObject->sensitive, &newObject->name.b, parentObject, |
116 | 0 | publicArea->nameAlg, |
117 | 0 | &out->outPrivate); |
118 | | // Finish by copying the remaining return values |
119 | 0 | out->outPublic.publicArea = newObject->publicArea; |
120 | 0 | return TPM_RC_SUCCESS; |
121 | 0 | } |
122 | | #endif // CC_Create |
123 | | #include "Tpm.h" |
124 | | #include "Load_fp.h" |
125 | | #if CC_Load // Conditional expansion of this file |
126 | | #include "Object_spt_fp.h" |
127 | | TPM_RC |
128 | | TPM2_Load( |
129 | | Load_In *in, // IN: input parameter list |
130 | | Load_Out *out // OUT: output parameter list |
131 | | ) |
132 | 0 | { |
133 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
134 | 0 | TPMT_SENSITIVE sensitive; |
135 | 0 | OBJECT *parentObject; |
136 | 0 | OBJECT *newObject; |
137 | | // Input Validation |
138 | | // Don't get invested in loading if there is no place to put it. |
139 | 0 | newObject = FindEmptyObjectSlot(&out->objectHandle); |
140 | 0 | if(newObject == NULL) |
141 | 0 | return TPM_RC_OBJECT_MEMORY; |
142 | 0 | if(in->inPrivate.t.size == 0) |
143 | 0 | return TPM_RCS_SIZE + RC_Load_inPrivate; |
144 | 0 | parentObject = HandleToObject(in->parentHandle); |
145 | 0 | pAssert(parentObject != NULL); |
146 | | // Is the object that is being used as the parent actually a parent. |
147 | 0 | if(!ObjectIsParent(parentObject)) |
148 | 0 | return TPM_RCS_TYPE + RC_Load_parentHandle; |
149 | | // Compute the name of object. If there isn't one, it is because the nameAlg is |
150 | | // not valid. |
151 | 0 | PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); |
152 | 0 | if(out->name.t.size == 0) |
153 | 0 | return TPM_RCS_HASH + RC_Load_inPublic; |
154 | | // Retrieve sensitive data. |
155 | 0 | result = PrivateToSensitive(&in->inPrivate.b, &out->name.b, parentObject, |
156 | 0 | in->inPublic.publicArea.nameAlg, |
157 | 0 | &sensitive); |
158 | 0 | if(result != TPM_RC_SUCCESS) |
159 | 0 | return RcSafeAddToResult(result, RC_Load_inPrivate); |
160 | | // Internal Data Update |
161 | | // Load and validate object |
162 | 0 | result = ObjectLoad(newObject, parentObject, |
163 | 0 | &in->inPublic.publicArea, &sensitive, |
164 | 0 | RC_Load_inPublic, RC_Load_inPrivate, |
165 | 0 | &out->name); |
166 | 0 | if(result == TPM_RC_SUCCESS) |
167 | 0 | { |
168 | | // Set the common OBJECT attributes for a loaded object. |
169 | 0 | ObjectSetLoadedAttributes(newObject, in->parentHandle); |
170 | 0 | } |
171 | 0 | return result; |
172 | 0 | } |
173 | | #endif // CC_Load |
174 | | #include "Tpm.h" |
175 | | #include "LoadExternal_fp.h" |
176 | | #if CC_LoadExternal // Conditional expansion of this file |
177 | | #include "Object_spt_fp.h" |
178 | | TPM_RC |
179 | | TPM2_LoadExternal( |
180 | | LoadExternal_In *in, // IN: input parameter list |
181 | | LoadExternal_Out *out // OUT: output parameter list |
182 | | ) |
183 | 0 | { |
184 | 0 | TPM_RC result; |
185 | 0 | OBJECT *object; |
186 | 0 | TPMT_SENSITIVE *sensitive = NULL; |
187 | | // Input Validation |
188 | | // Don't get invested in loading if there is no place to put it. |
189 | 0 | object = FindEmptyObjectSlot(&out->objectHandle); |
190 | 0 | if(object == NULL) |
191 | 0 | return TPM_RC_OBJECT_MEMORY; |
192 | | // If the hierarchy to be associated with this object is turned off, the object |
193 | | // cannot be loaded. |
194 | 0 | if(!HierarchyIsEnabled(in->hierarchy)) |
195 | 0 | return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; |
196 | | // For loading an object with both public and sensitive |
197 | 0 | if(in->inPrivate.size != 0) |
198 | 0 | { |
199 | | // An external object with a sensitive area can only be loaded in the |
200 | | // NULL hierarchy |
201 | 0 | if(in->hierarchy != TPM_RH_NULL) |
202 | 0 | return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; |
203 | | // An external object with a sensitive area must have fixedTPM == CLEAR |
204 | | // fixedParent == CLEAR so that it does not appear to be a key created by |
205 | | // this TPM. |
206 | 0 | if(IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM) |
207 | 0 | || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, |
208 | 0 | fixedParent) |
209 | 0 | || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, |
210 | 0 | restricted)) |
211 | 0 | return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic; |
212 | | // Have sensitive point to something other than NULL so that object |
213 | | // initialization will load the sensitive part too |
214 | 0 | sensitive = &in->inPrivate.sensitiveArea; |
215 | 0 | } |
216 | | // Need the name to initialize the object structure |
217 | 0 | PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); |
218 | | // Load and validate key |
219 | 0 | result = ObjectLoad(object, NULL, |
220 | 0 | &in->inPublic.publicArea, sensitive, |
221 | 0 | RC_LoadExternal_inPublic, RC_LoadExternal_inPrivate, |
222 | 0 | &out->name); |
223 | 0 | if(result == TPM_RC_SUCCESS) |
224 | 0 | { |
225 | 0 | object->attributes.external = SET; |
226 | | // Set the common OBJECT attributes for a loaded object. |
227 | 0 | ObjectSetLoadedAttributes(object, in->hierarchy); |
228 | 0 | } |
229 | 0 | return result; |
230 | 0 | } |
231 | | #endif // CC_LoadExternal |
232 | | #include "Tpm.h" |
233 | | #include "ReadPublic_fp.h" |
234 | | #if CC_ReadPublic // Conditional expansion of this file |
235 | | TPM_RC |
236 | | TPM2_ReadPublic( |
237 | | ReadPublic_In *in, // IN: input parameter list |
238 | | ReadPublic_Out *out // OUT: output parameter list |
239 | | ) |
240 | 0 | { |
241 | 0 | OBJECT *object = HandleToObject(in->objectHandle); |
242 | | // Input Validation |
243 | | // Can not read public area of a sequence object |
244 | 0 | if(ObjectIsSequence(object)) |
245 | 0 | return TPM_RC_SEQUENCE; |
246 | | // Command Output |
247 | 0 | out->outPublic.publicArea = object->publicArea; |
248 | 0 | out->name = object->name; |
249 | 0 | out->qualifiedName = object->qualifiedName; |
250 | 0 | return TPM_RC_SUCCESS; |
251 | 0 | } |
252 | | #endif // CC_ReadPublic |
253 | | #include "Tpm.h" |
254 | | #include "ActivateCredential_fp.h" |
255 | | #if CC_ActivateCredential // Conditional expansion of this file |
256 | | #include "Object_spt_fp.h" |
257 | | TPM_RC |
258 | | TPM2_ActivateCredential( |
259 | | ActivateCredential_In *in, // IN: input parameter list |
260 | | ActivateCredential_Out *out // OUT: output parameter list |
261 | | ) |
262 | 0 | { |
263 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
264 | 0 | OBJECT *object; // decrypt key |
265 | 0 | OBJECT *activateObject; // key associated with credential |
266 | 0 | TPM2B_DATA data; // credential data |
267 | | // Input Validation |
268 | | // Get decrypt key pointer |
269 | 0 | object = HandleToObject(in->keyHandle); |
270 | | // Get certificated object pointer |
271 | 0 | activateObject = HandleToObject(in->activateHandle); |
272 | | // input decrypt key must be an asymmetric, restricted decryption key |
273 | 0 | if(!CryptIsAsymAlgorithm(object->publicArea.type) |
274 | 0 | || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) |
275 | 0 | || !IS_ATTRIBUTE(object->publicArea.objectAttributes, |
276 | 0 | TPMA_OBJECT, restricted)) |
277 | 0 | return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle; |
278 | | // Command output |
279 | | // Decrypt input credential data via asymmetric decryption. A |
280 | | // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this |
281 | | // point |
282 | 0 | result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data); |
283 | 0 | if(result != TPM_RC_SUCCESS) |
284 | 0 | { |
285 | 0 | if(result == TPM_RC_KEY) |
286 | 0 | return TPM_RC_FAILURE; |
287 | 0 | return RcSafeAddToResult(result, RC_ActivateCredential_secret); |
288 | 0 | } |
289 | | // Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal |
290 | | // errors may be returned at this point |
291 | 0 | result = CredentialToSecret(&in->credentialBlob.b, |
292 | 0 | &activateObject->name.b, |
293 | 0 | &data.b, |
294 | 0 | object, |
295 | 0 | &out->certInfo); |
296 | 0 | if(result != TPM_RC_SUCCESS) |
297 | 0 | return RcSafeAddToResult(result, RC_ActivateCredential_credentialBlob); |
298 | 0 | return TPM_RC_SUCCESS; |
299 | 0 | } |
300 | | #endif // CC_ActivateCredential |
301 | | #include "Tpm.h" |
302 | | #include "MakeCredential_fp.h" |
303 | | #if CC_MakeCredential // Conditional expansion of this file |
304 | | #include "Object_spt_fp.h" |
305 | | TPM_RC |
306 | | TPM2_MakeCredential( |
307 | | MakeCredential_In *in, // IN: input parameter list |
308 | | MakeCredential_Out *out // OUT: output parameter list |
309 | | ) |
310 | 0 | { |
311 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
312 | 0 | OBJECT *object; |
313 | 0 | TPM2B_DATA data; |
314 | | // Input Validation |
315 | | // Get object pointer |
316 | 0 | object = HandleToObject(in->handle); |
317 | | // input key must be an asymmetric, restricted decryption key |
318 | | // NOTE: Needs to be restricted to have a symmetric value. |
319 | 0 | if(!CryptIsAsymAlgorithm(object->publicArea.type) |
320 | 0 | || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) |
321 | 0 | || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) |
322 | 0 | return TPM_RCS_TYPE + RC_MakeCredential_handle; |
323 | | // The credential information may not be larger than the digest size used for |
324 | | // the Name of the key associated with handle. |
325 | 0 | if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg)) |
326 | 0 | return TPM_RCS_SIZE + RC_MakeCredential_credential; |
327 | | // Command Output |
328 | | // Make encrypt key and its associated secret structure. |
329 | 0 | out->secret.t.size = sizeof(out->secret.t.secret); |
330 | 0 | result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret); |
331 | 0 | if(result != TPM_RC_SUCCESS) |
332 | 0 | return result; |
333 | | // Prepare output credential data from secret |
334 | 0 | SecretToCredential(&in->credential, &in->objectName.b, &data.b, |
335 | 0 | object, &out->credentialBlob); |
336 | 0 | return TPM_RC_SUCCESS; |
337 | 0 | } |
338 | | #endif // CC_MakeCredential |
339 | | #include "Tpm.h" |
340 | | #include "Unseal_fp.h" |
341 | | #if CC_Unseal // Conditional expansion of this file |
342 | | TPM_RC |
343 | | TPM2_Unseal( |
344 | | Unseal_In *in, |
345 | | Unseal_Out *out |
346 | | ) |
347 | 0 | { |
348 | 0 | OBJECT *object; |
349 | | // Input Validation |
350 | | // Get pointer to loaded object |
351 | 0 | object = HandleToObject(in->itemHandle); |
352 | | // Input handle must be a data object |
353 | 0 | if(object->publicArea.type != TPM_ALG_KEYEDHASH) |
354 | 0 | return TPM_RCS_TYPE + RC_Unseal_itemHandle; |
355 | 0 | if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) |
356 | 0 | || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) |
357 | 0 | || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) |
358 | 0 | return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle; |
359 | | // Command Output |
360 | | // Copy data |
361 | 0 | out->outData = object->sensitive.sensitive.bits; |
362 | 0 | return TPM_RC_SUCCESS; |
363 | 0 | } |
364 | | #endif // CC_Unseal |
365 | | #include "Tpm.h" |
366 | | #include "ObjectChangeAuth_fp.h" |
367 | | #if CC_ObjectChangeAuth // Conditional expansion of this file |
368 | | #include "Object_spt_fp.h" |
369 | | TPM_RC |
370 | | TPM2_ObjectChangeAuth( |
371 | | ObjectChangeAuth_In *in, // IN: input parameter list |
372 | | ObjectChangeAuth_Out *out // OUT: output parameter list |
373 | | ) |
374 | 0 | { |
375 | 0 | TPMT_SENSITIVE sensitive; |
376 | 0 | OBJECT *object = HandleToObject(in->objectHandle); |
377 | 0 | TPM2B_NAME QNCompare; |
378 | | // Input Validation |
379 | | // Can not change authorization on sequence object |
380 | 0 | if(ObjectIsSequence(object)) |
381 | 0 | return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle; |
382 | | // Make sure that the authorization value is consistent with the nameAlg |
383 | 0 | if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg)) |
384 | 0 | return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth; |
385 | | // Parent handle should be the parent of object handle. In this |
386 | | // implementation we verify this by checking the QN of object. Other |
387 | | // implementation may choose different method to verify this attribute. |
388 | 0 | ComputeQualifiedName(in->parentHandle, |
389 | 0 | object->publicArea.nameAlg, |
390 | 0 | &object->name, &QNCompare); |
391 | 0 | if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b)) |
392 | 0 | return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle; |
393 | | // Command Output |
394 | | // Prepare the sensitive area with the new authorization value |
395 | 0 | sensitive = object->sensitive; |
396 | 0 | sensitive.authValue = in->newAuth; |
397 | | // Protect the sensitive area |
398 | 0 | SensitiveToPrivate(&sensitive, &object->name.b, HandleToObject(in->parentHandle), |
399 | 0 | object->publicArea.nameAlg, |
400 | 0 | &out->outPrivate); |
401 | 0 | return TPM_RC_SUCCESS; |
402 | 0 | } |
403 | | #endif // CC_ObjectChangeAuth |
404 | | #include "Tpm.h" |
405 | | #include "CreateLoaded_fp.h" |
406 | | #if CC_CreateLoaded // Conditional expansion of this file |
407 | | TPM_RC |
408 | | TPM2_CreateLoaded( |
409 | | CreateLoaded_In *in, // IN: input parameter list |
410 | | CreateLoaded_Out *out // OUT: output parameter list |
411 | | ) |
412 | 0 | { |
413 | 0 | TPM_RC result = TPM_RC_SUCCESS; |
414 | 0 | OBJECT *parent = HandleToObject(in->parentHandle); |
415 | 0 | OBJECT *newObject; |
416 | 0 | BOOL derivation; |
417 | 0 | TPMT_PUBLIC *publicArea; |
418 | 0 | RAND_STATE randState; |
419 | 0 | RAND_STATE *rand = &randState; |
420 | 0 | TPMS_DERIVE labelContext; |
421 | | // Input Validation |
422 | | // How the public area is unmarshaled is determined by the parent, so |
423 | | // see if parent is a derivation parent |
424 | 0 | derivation = (parent != NULL && parent->attributes.derivation); |
425 | | // If the parent is an object, then make sure that it is either a parent or |
426 | | // derivation parent |
427 | 0 | if(parent != NULL && !parent->attributes.isParent && !derivation) |
428 | 0 | return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle; |
429 | | // Get a spot in which to create the newObject |
430 | 0 | newObject = FindEmptyObjectSlot(&out->objectHandle); |
431 | 0 | if(newObject == NULL) |
432 | 0 | return TPM_RC_OBJECT_MEMORY; |
433 | | // Do this to save typing |
434 | 0 | publicArea = &newObject->publicArea; |
435 | | // Unmarshal the template into the object space. TPM2_Create() and |
436 | | // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher. |
437 | | // This command is different because of an unfortunate property of the |
438 | | // unique field of an ECC key. It is a structure rather than a single TPM2B. If |
439 | | // if had been a TPM2B, then the label and context could be within a TPM2B and |
440 | | // unmarshaled like other public areas. Since it is not, this command needs its |
441 | | // on template that is a TPM2B that is unmarshaled as a BYTE array with a |
442 | | // its own unmarshal function. |
443 | 0 | result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, |
444 | 0 | &labelContext); |
445 | 0 | if(result != TPM_RC_SUCCESS) |
446 | 0 | return result + RC_CreateLoaded_inPublic; |
447 | | // Validate that the authorization size is appropriate |
448 | 0 | if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) |
449 | 0 | return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive; |
450 | | // Command output |
451 | 0 | if(derivation) |
452 | 0 | { |
453 | 0 | TPMT_KEYEDHASH_SCHEME *scheme; |
454 | 0 | scheme = &parent->publicArea.parameters.keyedHashDetail.scheme; |
455 | | // SP800-108 is the only KDF supported by this implementation and there is |
456 | | // no default hash algorithm. |
457 | 0 | pAssert(scheme->details.xorr.hashAlg != TPM_ALG_NULL |
458 | 0 | && scheme->details.xorr.kdf == TPM_ALG_KDF1_SP800_108); |
459 | | // Don't derive RSA keys |
460 | 0 | if(publicArea->type == ALG_RSA_VALUE) |
461 | 0 | return TPM_RCS_TYPE + RC_CreateLoaded_inPublic; |
462 | | // sensitiveDataOrigin has to be CLEAR in a derived object. Since this |
463 | | // is specific to a derived object, it is checked here. |
464 | 0 | if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, |
465 | 0 | sensitiveDataOrigin)) |
466 | 0 | return TPM_RCS_ATTRIBUTES; |
467 | | // Check the reset of the attributes |
468 | 0 | result = PublicAttributesValidation(parent, publicArea); |
469 | 0 | if(result != TPM_RC_SUCCESS) |
470 | 0 | return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); |
471 | | // Process the template and sensitive areas to get the actual 'label' and |
472 | | // 'context' values to be used for this derivation. |
473 | 0 | result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data); |
474 | 0 | if(result != TPM_RC_SUCCESS) |
475 | 0 | return result; |
476 | | // Set up the KDF for object generation |
477 | 0 | DRBG_InstantiateSeededKdf((KDF_STATE *)rand, |
478 | 0 | scheme->details.xorr.hashAlg, |
479 | 0 | scheme->details.xorr.kdf, |
480 | 0 | &parent->sensitive.sensitive.bits.b, |
481 | 0 | &labelContext.label.b, |
482 | 0 | &labelContext.context.b, |
483 | 0 | TPM_MAX_DERIVATION_BITS); |
484 | | // Clear the sensitive size so that the creation functions will not try |
485 | | // to use this value. |
486 | 0 | in->inSensitive.sensitive.data.t.size = 0; |
487 | 0 | } |
488 | 0 | else |
489 | 0 | { |
490 | | // Check attributes in input public area. CreateChecks() checks the things |
491 | | // that are unique to creation and then validates the attributes and values |
492 | | // that are common to create and load. |
493 | 0 | result = CreateChecks(parent, publicArea, |
494 | 0 | in->inSensitive.sensitive.data.t.size); |
495 | 0 | if(result != TPM_RC_SUCCESS) |
496 | 0 | return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); |
497 | | // Creating a primary object |
498 | 0 | if(parent == NULL) |
499 | 0 | { |
500 | 0 | TPM2B_NAME name; |
501 | 0 | newObject->attributes.primary = SET; |
502 | 0 | if(in->parentHandle == TPM_RH_ENDORSEMENT) |
503 | 0 | newObject->attributes.epsHierarchy = SET; |
504 | | // If so, use the primary seed and the digest of the template |
505 | | // to seed the DRBG |
506 | 0 | DRBG_InstantiateSeeded((DRBG_STATE *)rand, |
507 | 0 | &HierarchyGetPrimarySeed(in->parentHandle)->b, |
508 | 0 | PRIMARY_OBJECT_CREATION, |
509 | 0 | (TPM2B *)PublicMarshalAndComputeName(publicArea, |
510 | 0 | &name), |
511 | 0 | &in->inSensitive.sensitive.data.b); |
512 | 0 | } |
513 | 0 | else |
514 | | // This is an ordinary object so use the normal random number generator |
515 | 0 | rand = NULL; |
516 | 0 | } |
517 | | // Internal data update |
518 | | // Create the object |
519 | 0 | result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand); |
520 | 0 | if(result != TPM_RC_SUCCESS) |
521 | 0 | return result; |
522 | | // if this is not a Primary key and not a derived key, then return the sensitive |
523 | | // area |
524 | 0 | if(parent != NULL && !derivation) |
525 | | // Prepare output private data from sensitive |
526 | 0 | SensitiveToPrivate(&newObject->sensitive, &newObject->name.b, |
527 | 0 | parent, newObject->publicArea.nameAlg, |
528 | 0 | &out->outPrivate); |
529 | 0 | else |
530 | 0 | out->outPrivate.t.size = 0; |
531 | | // Set the remaining return values |
532 | 0 | out->outPublic.publicArea = newObject->publicArea; |
533 | 0 | out->name = newObject->name; |
534 | | // Set the remaining attributes for a loaded object |
535 | 0 | ObjectSetLoadedAttributes(newObject, in->parentHandle); |
536 | 0 | return result; |
537 | 0 | } |
538 | | #endif // CC_CreateLoaded |