Coverage Report

Created: 2023-09-25 06:15

/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