• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2043

29 Dec 2025 06:12PM UTC coverage: 77.222% (-0.005%) from 77.227%
#2043

push

travis-ci

web-flow
Merge dad4446a5 into a3917cb92

36065 of 46703 relevant lines covered (77.22%)

101207.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.81
/src/tpm2/ObjectCommands.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                             Object Commands                                        */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*                                                                                */
7
/*  Licenses and Notices                                                        */
8
/*                                                                                */
9
/*  1. Copyright Licenses:                                                        */
10
/*                                                                                */
11
/*  - Trusted Computing Group (TCG) grants to the user of the source code in        */
12
/*    this specification (the "Source Code") a worldwide, irrevocable,                 */
13
/*    nonexclusive, royalty free, copyright license to reproduce, create         */
14
/*    derivative works, distribute, display and perform the Source Code and        */
15
/*    derivative works thereof, and to grant others the rights granted herein.        */
16
/*                                                                                */
17
/*  - The TCG grants to the user of the other parts of the specification         */
18
/*    (other than the Source Code) the rights to reproduce, distribute,         */
19
/*    display, and perform the specification solely for the purpose of                 */
20
/*    developing products based on such documents.                                */
21
/*                                                                                */
22
/*  2. Source Code Distribution Conditions:                                        */
23
/*                                                                                */
24
/*  - Redistributions of Source Code must retain the above copyright licenses,         */
25
/*    this list of conditions and the following disclaimers.                        */
26
/*                                                                                */
27
/*  - Redistributions in binary form must reproduce the above copyright         */
28
/*    licenses, this list of conditions        and the following disclaimers in the         */
29
/*    documentation and/or other materials provided with the distribution.        */
30
/*                                                                                */
31
/*  3. Disclaimers:                                                                */
32
/*                                                                                */
33
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF        */
34
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH        */
35
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)        */
36
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.                */
37
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for                 */
38
/*  information on specification licensing rights available through TCG         */
39
/*  membership agreements.                                                        */
40
/*                                                                                */
41
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED         */
42
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR         */
43
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR                 */
44
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY                 */
45
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.                */
46
/*                                                                                */
47
/*  - Without limitation, TCG and its members and licensors disclaim all         */
48
/*    liability, including liability for infringement of any proprietary         */
49
/*    rights, relating to use of information in this specification and to the        */
50
/*    implementation of this specification, and TCG disclaims all liability for        */
51
/*    cost of procurement of substitute goods or services, lost profits, loss         */
52
/*    of use, loss of data or any incidental, consequential, direct, indirect,         */
53
/*    or special damages, whether under contract, tort, warranty or otherwise,         */
54
/*    arising in any way out of use or reliance upon this specification or any         */
55
/*    information herein.                                                        */
56
/*                                                                                */
57
/*  (c) Copyright IBM Corp. and others, 2016 - 2024                                */
58
/*                                                                                */
59
/********************************************************************************/
60

61
#include "Tpm.h"
62
#include "Object_spt_fp.h"
63
#include "Create_fp.h"
64

65
#if CC_Create  // Conditional expansion of this file
66

67
/*(See part 3 specification)
68
// Create a regular object
69
*/
70
//  Return Type: TPM_RC
71
//      TPM_RC_ATTRIBUTES       'sensitiveDataOrigin' is CLEAR when 'sensitive.data'
72
//                              is an Empty Buffer, or is SET when 'sensitive.data' is
73
//                              not empty;
74
//                              'fixedTPM', 'fixedParent', or 'encryptedDuplication'
75
//                              attributes are inconsistent between themselves or with
76
//                              those of the parent object;
77
//                              inconsistent 'restricted', 'decrypt' and 'sign'
78
//                              attributes;
79
//                              attempt to inject sensitive data for an asymmetric
80
//                              key;
81
//      TPM_RC_HASH             non-duplicable storage key and its parent have
82
//                              different name algorithm
83
//      TPM_RC_KDF              incorrect KDF specified for decrypting keyed hash
84
//                              object
85
//      TPM_RC_KEY              invalid key size values in an asymmetric key public
86
//                              area or a provided symmetric key has a value that is
87
//                              not allowed
88
//      TPM_RC_KEY_SIZE         key size in public area for symmetric key differs from
89
//                              the size in the sensitive creation area; may also be
90
//                              returned if the TPM does not allow the key size to be
91
//                              used for a Storage Key
92
//      TPM_RC_OBJECT_MEMORY    a free slot is not available as scratch memory for
93
//                              object creation
94
//      TPM_RC_RANGE            the exponent value of an RSA key is not supported.
95
//      TPM_RC_SCHEME           inconsistent attributes 'decrypt', 'sign', or
96
//                              'restricted' and key's scheme ID; or hash algorithm is
97
//                              inconsistent with the scheme ID for keyed hash object
98
//      TPM_RC_SIZE             size of public authPolicy or sensitive authValue does
99
//                              not match digest size of the name algorithm
100
//                              sensitive data size for the keyed hash object is
101
//                              larger than is allowed for the scheme
102
//      TPM_RC_SYMMETRIC        a storage key with no symmetric algorithm specified;
103
//                              or non-storage key with symmetric algorithm different
104
//                              from TPM_ALG_NULL
105
//      TPM_RC_TYPE             unknown object type;
106
//                              'parentHandle' does not reference a restricted
107
//                              decryption key in the storage hierarchy with both
108
//                              public and sensitive portion loaded
109
//      TPM_RC_VALUE            exponent is not prime or could not find a prime using
110
//                              the provided parameters for an RSA key;
111
//                              unsupported name algorithm for an ECC key
112
//      TPM_RC_OBJECT_MEMORY    there is no free slot for the object
113
TPM_RC
114
TPM2_Create(Create_In*  in,  // IN: input parameter list
278✔
115
            Create_Out* out  // OUT: output parameter list
116
            )
117
{
118
    TPM_RC       result = TPM_RC_SUCCESS;
278✔
119
    OBJECT*      parentObject;
278✔
120
    OBJECT*      newObject;
278✔
121
    TPMT_PUBLIC* publicArea;
278✔
122
    // Input Validation
123
    parentObject = HandleToObject(in->parentHandle);
278✔
124
    pAssert(parentObject != NULL);
278✔
125

126
    // Does parent have the proper attributes?
127
    if(!ObjectIsParent(parentObject))
278✔
128
        return TPM_RCS_TYPE + RC_Create_parentHandle;
129

130
    // Get a slot for the creation
131
    newObject = FindEmptyObjectSlot(NULL);
278✔
132
    if(newObject == NULL)
278✔
133
        return TPM_RC_OBJECT_MEMORY;
134
    // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical
135
    // form for processing
136

137
    // to save typing.
138
    publicArea = &newObject->publicArea;
278✔
139

140
    // Copy the input structure to the allocated structure
141
    *publicArea = in->inPublic.publicArea;
278✔
142

143
    // Check attributes in input public area. CreateChecks() checks the things that
144
    // are unique to creation and then validates the attributes and values that are
145
    // common to create and load.
146
    result = CreateChecks(parentObject,
556✔
147
                          /* primaryHierarchy = */ 0,
148
                          publicArea,
149
                          in->inSensitive.sensitive.data.t.size);
278✔
150
    if(result != TPM_RC_SUCCESS)
278✔
151
        return RcSafeAddToResult(result, RC_Create_inPublic);
×
152
    // Clean up the authValue if necessary
153
    if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
278✔
154
        return TPM_RCS_SIZE + RC_Create_inSensitive;
155

156
    // Command Output
157
    // Create the object using the default TPM random-number generator
158
    result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL);
278✔
159
    if(result != TPM_RC_SUCCESS)
278✔
160
        return result;
161
    // Fill in creation data
162
    FillInCreationData(in->parentHandle,
278✔
163
                       publicArea->nameAlg,
278✔
164
                       &in->creationPCR,
165
                       &in->outsideInfo,
166
                       &out->creationData,
167
                       &out->creationHash);
168

169
    // Compute creation ticket
170
    result = TicketComputeCreation(EntityGetHierarchy(in->parentHandle),
278✔
171
                                   &newObject->name,
172
                                   &out->creationHash,
173
                                   &out->creationTicket);
174
    if(result != TPM_RC_SUCCESS)
278✔
175
        return result;
176

177
    // Prepare output private data from sensitive
178
    SensitiveToPrivate(&newObject->sensitive,
278✔
179
                       &newObject->name,
180
                       parentObject,
181
                       publicArea->nameAlg,
278✔
182
                       &out->outPrivate);
183

184
    newObject->hierarchy = parentObject->hierarchy;
278✔
185

186
    // Finish by copying the remaining return values
187
    out->outPublic.publicArea = newObject->publicArea;
278✔
188
    return TPM_RC_SUCCESS;
278✔
189
}
190

191
#endif  // CC_Create
192

193
#include "Tpm.h"
194
#include "Load_fp.h"
195
#if CC_Load  // Conditional expansion of this file
196
#include "Object_spt_fp.h"
197
TPM_RC
198
TPM2_Load(
407✔
199
          Load_In         *in,            // IN: input parameter list
200
          Load_Out        *out            // OUT: output parameter list
201
          )
202
{
203
    TPM_RC                   result = TPM_RC_SUCCESS;
407✔
204
    TPMT_SENSITIVE           sensitive = {0}; // libtpms changed (valgrind)
407✔
205
    OBJECT                  *parentObject;
407✔
206
    OBJECT                  *newObject;
407✔
207
    // Input Validation
208
    // Don't get invested in loading if there is no place to put it.
209
    newObject = FindEmptyObjectSlot(&out->objectHandle);
407✔
210
    if(newObject == NULL)
407✔
211
        return TPM_RC_OBJECT_MEMORY;
212
    if(in->inPrivate.t.size == 0)
407✔
213
        return TPM_RCS_SIZE + RC_Load_inPrivate;
214
    parentObject = HandleToObject(in->parentHandle);
407✔
215
    pAssert(parentObject != NULL);
407✔
216
    // Is the object that is being used as the parent actually a parent.
217
    if(!ObjectIsParent(parentObject))
407✔
218
        return TPM_RCS_TYPE + RC_Load_parentHandle;
219
    // Compute the name of object. If there isn't one, it is because the nameAlg is
220
    // not valid.
221
    PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name);
407✔
222
    if(out->name.t.size == 0)
407✔
223
        return TPM_RCS_HASH + RC_Load_inPublic;
224
    // Retrieve sensitive data.
225
    result = PrivateToSensitive(&in->inPrivate.b, &out->name.b, parentObject,
814✔
226
                                in->inPublic.publicArea.nameAlg,
407✔
227
                                &sensitive);
228
    if(result != TPM_RC_SUCCESS)
407✔
229
        return RcSafeAddToResult(result, RC_Load_inPrivate);
3✔
230
    // Internal Data Update
231
    // Load and validate object
232
    result = ObjectLoad(newObject, parentObject,
404✔
233
                        &in->inPublic.publicArea, &sensitive,
234
                        RC_Load_inPublic, RC_Load_inPrivate,
235
                        &out->name);
236
    if(result == TPM_RC_SUCCESS)
404✔
237
        {
238
            // Set the common OBJECT attributes for a loaded object.
239
            ObjectSetLoadedAttributes(newObject, in->parentHandle,
404✔
240
                                      parentObject->seedCompatLevel); // libtpms added
404✔
241
        }
242
    return result;
243
}
244
#endif // CC_Load
245
#include "Tpm.h"
246
#include "LoadExternal_fp.h"
247
#if CC_LoadExternal  // Conditional expansion of this file
248
#include "Object_spt_fp.h"
249
TPM_RC
250
TPM2_LoadExternal(
550✔
251
                  LoadExternal_In     *in,            // IN: input parameter list
252
                  LoadExternal_Out    *out            // OUT: output parameter list
253
                  )
254
{
255
    TPM_RC               result;
550✔
256
    OBJECT              *object;
550✔
257
    TPMT_SENSITIVE      *sensitive = NULL;
550✔
258
    // Input Validation
259
    // Don't get invested in loading if there is no place to put it.
260
    object = FindEmptyObjectSlot(&out->objectHandle);
550✔
261
    if(object == NULL)
550✔
262
        return TPM_RC_OBJECT_MEMORY;
263
    // If the hierarchy to be associated with this object is turned off, the object
264
    // cannot be loaded.
265
    if(!HierarchyIsEnabled(in->hierarchy))
550✔
266
        return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy;
267
    // For loading an object with both public and sensitive
268
    if(in->inPrivate.size != 0)
550✔
269
        {
270
            // An external object with a sensitive area can only be loaded in the
271
            // NULL hierarchy
272
            if(in->hierarchy != TPM_RH_NULL)
394✔
273
                return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy;
274
            // An external object with a sensitive area must have fixedTPM == CLEAR
275
            // fixedParent == CLEAR so that it does not appear to be a key created by
276
            // this TPM.
277
            if(IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)
390✔
278
               || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT,
279
                               fixedParent)
280
               || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT,
390✔
281
                               restricted))
282
                return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic;
283
            // Have sensitive point to something other than NULL so that object
284
            // initialization will load the sensitive part too
285
            sensitive = &in->inPrivate.sensitiveArea;
386✔
286
        }
287
    // Need the name to initialize the object structure
288
    PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name);
542✔
289
    // Load and validate key
290
    result = ObjectLoad(object, NULL,
542✔
291
                        &in->inPublic.publicArea, sensitive,
292
                        RC_LoadExternal_inPublic, RC_LoadExternal_inPrivate,
293
                        &out->name);
294
    if(result == TPM_RC_SUCCESS)
542✔
295
        {
296
            object->attributes.external = SET;
150✔
297
            // Set the common OBJECT attributes for a loaded object.
298
            ObjectSetLoadedAttributes(object, in->hierarchy,
150✔
299
                                      // if anything can be derived from an external object,
300
                                      // we make sure it always uses the old algorithm
301
                                      SEED_COMPAT_LEVEL_ORIGINAL); // libtpms added
302
        }
303
    return result;
304
}
305
#endif // CC_LoadExternal
306
#include "Tpm.h"
307
#include "ReadPublic_fp.h"
308
#if CC_ReadPublic  // Conditional expansion of this file
309
TPM_RC
310
TPM2_ReadPublic(
131✔
311
                ReadPublic_In   *in,            // IN: input parameter list
312
                ReadPublic_Out  *out            // OUT: output parameter list
313
                )
314
{
315
    OBJECT                  *object = HandleToObject(in->objectHandle);
131✔
316
    // Input Validation
317
    // Can not read public area of a sequence object
318
    if(ObjectIsSequence(object))
131✔
319
        return TPM_RC_SEQUENCE;
320
    // Command Output
321
    out->outPublic.publicArea = object->publicArea;
131✔
322
    out->name = object->name;
131✔
323
    out->qualifiedName = object->qualifiedName;
131✔
324
    return TPM_RC_SUCCESS;
131✔
325
}
326
#endif // CC_ReadPublic
327
#include "Tpm.h"
328
#include "ActivateCredential_fp.h"
329
#if CC_ActivateCredential  // Conditional expansion of this file
330
#include "Object_spt_fp.h"
331
TPM_RC
332
TPM2_ActivateCredential(
1✔
333
                        ActivateCredential_In   *in,            // IN: input parameter list
334
                        ActivateCredential_Out  *out            // OUT: output parameter list
335
                        )
336
{
337
    TPM_RC                   result = TPM_RC_SUCCESS;
1✔
338
    OBJECT                  *object;            // decrypt key
1✔
339
    OBJECT                  *activateObject;    // key associated with credential
1✔
340
    TPM2B_DATA               data;          // credential data
1✔
341
    // Input Validation
342
    // Get decrypt key pointer
343
    object = HandleToObject(in->keyHandle);
1✔
344
    // Get certificated object pointer
345
    activateObject = HandleToObject(in->activateHandle);
1✔
346
    // input decrypt key must be an asymmetric, restricted decryption key
347
    if(!CryptIsAsymAlgorithm(object->publicArea.type)
1✔
348
       || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
349
       || !IS_ATTRIBUTE(object->publicArea.objectAttributes,
1✔
350
                        TPMA_OBJECT, restricted))
351
        return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle;
352
    // Command output
353
    // Decrypt input credential data via asymmetric decryption.  A
354
    // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
355
    // point
356
    result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data);
1✔
357
    if(result != TPM_RC_SUCCESS)
1✔
358
        {
359
            if(result == TPM_RC_KEY)
×
360
                return TPM_RC_FAILURE;
361
            return RcSafeAddToResult(result, RC_ActivateCredential_secret);
×
362
        }
363
    // Retrieve secret data.  A TPM_RC_INTEGRITY error or unmarshal
364
    // errors may be returned at this point
365
    result = CredentialToSecret(&in->credentialBlob.b,
1✔
366
                                &activateObject->name.b,
367
                                &data.b,
368
                                object,
369
                                &out->certInfo);
370
    if(result != TPM_RC_SUCCESS)
1✔
371
        return RcSafeAddToResult(result, RC_ActivateCredential_credentialBlob);
×
372
    return TPM_RC_SUCCESS;
373
}
374
#endif // CC_ActivateCredential
375
#include "Tpm.h"
376
#include "MakeCredential_fp.h"
377
#if CC_MakeCredential  // Conditional expansion of this file
378
#include "Object_spt_fp.h"
379
TPM_RC
380
TPM2_MakeCredential(
1✔
381
                    MakeCredential_In   *in,            // IN: input parameter list
382
                    MakeCredential_Out  *out            // OUT: output parameter list
383
                    )
384
{
385
    TPM_RC               result = TPM_RC_SUCCESS;
1✔
386
    OBJECT              *object;
1✔
387
    TPM2B_DATA           data;
1✔
388
   // Input Validation
389
    // Get object pointer
390
    object = HandleToObject(in->handle);
1✔
391
    // input key must be an asymmetric, restricted decryption key
392
    // NOTE: Needs to be restricted to have a symmetric value.
393
    if(!CryptIsAsymAlgorithm(object->publicArea.type)
1✔
394
       || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
395
       || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
1✔
396
        return TPM_RCS_TYPE + RC_MakeCredential_handle;
397
    // The credential information may not be larger than the digest size used for
398
    // the Name of the key associated with handle.
399
    if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg))
1✔
400
        return TPM_RCS_SIZE + RC_MakeCredential_credential;
401
    // Command Output
402
    // Make encrypt key and its associated secret structure.
403
    out->secret.t.size = sizeof(out->secret.t.secret);
1✔
404
    result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret);
1✔
405
    if(result != TPM_RC_SUCCESS)
1✔
406
        return result;
407
    // Prepare output credential data from secret
408
    SecretToCredential(&in->credential, &in->objectName.b, &data.b,
1✔
409
                       object, &out->credentialBlob);
410
    return TPM_RC_SUCCESS;
1✔
411
}
412
#endif // CC_MakeCredential
413
#include "Tpm.h"
414
#include "Unseal_fp.h"
415
#if CC_Unseal  // Conditional expansion of this file
416
TPM_RC
417
TPM2_Unseal(
23✔
418
            Unseal_In           *in,
419
            Unseal_Out          *out
420
            )
421
{
422
    OBJECT                  *object;
23✔
423
    // Input Validation
424
    // Get pointer to loaded object
425
    object = HandleToObject(in->itemHandle);
23✔
426
    // Input handle must be a data object
427
    if(object->publicArea.type != TPM_ALG_KEYEDHASH)
23✔
428
        return TPM_RCS_TYPE + RC_Unseal_itemHandle;
429
    if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
23✔
430
       || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
431
       || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
23✔
432
        return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle;
433
    // Command Output
434
    // Copy data
435
    out->outData = object->sensitive.sensitive.bits;
23✔
436
    return TPM_RC_SUCCESS;
23✔
437
}
438
#endif // CC_Unseal
439
#include "Tpm.h"
440
#include "ObjectChangeAuth_fp.h"
441
#if CC_ObjectChangeAuth  // Conditional expansion of this file
442
#include "Object_spt_fp.h"
443
TPM_RC
444
TPM2_ObjectChangeAuth(
5✔
445
                      ObjectChangeAuth_In     *in,            // IN: input parameter list
446
                      ObjectChangeAuth_Out    *out            // OUT: output parameter list
447
                      )
448
{
449
    TPMT_SENSITIVE           sensitive;
5✔
450
    OBJECT                  *object = HandleToObject(in->objectHandle);
5✔
451
    TPM2B_NAME               QNCompare;
5✔
452
    // Input Validation
453
    // Can not change authorization on sequence object
454
    if(ObjectIsSequence(object))
5✔
455
        return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle;
456
    // Make sure that the authorization value is consistent with the nameAlg
457
    if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg))
5✔
458
        return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth;
459
    // Parent handle should be the parent of object handle.  In this
460
    // implementation we verify this by checking the QN of object.  Other
461
    // implementation may choose different method to verify this attribute.
462
    ComputeQualifiedName(in->parentHandle,
5✔
463
                         object->publicArea.nameAlg,
5✔
464
                         &object->name, &QNCompare);
465
    if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b))
5✔
466
        return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle;
467
    // Command Output
468
    // Prepare the sensitive area with the new authorization value
469
    sensitive = object->sensitive;
5✔
470
    sensitive.authValue = in->newAuth;
5✔
471
    // Protect the sensitive area
472
    SensitiveToPrivate(&sensitive, &object->name, HandleToObject(in->parentHandle),
10✔
473
                       object->publicArea.nameAlg,
5✔
474
                       &out->outPrivate);
475
    return TPM_RC_SUCCESS;
5✔
476
}
477
#endif // CC_ObjectChangeAuth
478

479
#include "Tpm.h"
480
#include "CreateLoaded_fp.h"
481

482
#if CC_CreateLoaded  // Conditional expansion of this file
483

484
/*(See part 3 of specification)
485
 * Create and load any type of key, including a temporary key.
486
 * The input template is a marshaled public area rather than an unmarshaled one as
487
 * used in Create and CreatePrimary. This is so that the label and context that
488
 * could be in the template can be processed without changing the formats for the
489
 * calls to Create and CreatePrimary.
490
 */
491
//  Return Type: TPM_RC
492
//      TPM_RC_ATTRIBUTES       'sensitiveDataOrigin' is CLEAR when 'sensitive.data'
493
//                              is an Empty Buffer;
494
//                              'fixedTPM', 'fixedParent', or 'encryptedDuplication'
495
//                              attributes are inconsistent between themselves or with
496
//                              those of the parent object;
497
//                              inconsistent 'restricted', 'decrypt' and 'sign'
498
//                              attributes;
499
//                              attempt to inject sensitive data for an asymmetric
500
//                              key;
501
//                              attempt to create a symmetric cipher key that is not
502
//                              a decryption key
503
//      TPM_RC_FW_LIMITED       The requested hierarchy is FW-limited, but the TPM
504
//                              does not support FW-limited objects or the TPM failed
505
//                              to derive the Firmware Secret.
506
//      TPM_RC_SVN_LIMITED      The requested hierarchy is SVN-limited, but the TPM
507
//                              does not support SVN-limited objects or the TPM failed
508
//                              to derive the Firmware SVN Secret for the requested
509
//                              SVN.
510
//      TPM_RC_KDF              incorrect KDF specified for decrypting keyed hash
511
//                              object
512
//      TPM_RC_KEY              the value of a provided symmetric key is not allowed
513
//      TPM_RC_OBJECT_MEMORY    there is no free slot for the object
514
//      TPM_RC_SCHEME           inconsistent attributes 'decrypt', 'sign',
515
//                              'restricted' and key's scheme ID; or hash algorithm is
516
//                              inconsistent with the scheme ID for keyed hash object
517
//      TPM_RC_SIZE             size of public authorization policy or sensitive
518
//                              authorization value does not match digest size of the
519
//                              name algorithm sensitive data size for the keyed hash
520
//                              object is larger than is allowed for the scheme
521
//      TPM_RC_SYMMETRIC        a storage key with no symmetric algorithm specified;
522
//                              or non-storage key with symmetric algorithm different
523
//                              from TPM_ALG_NULL
524
//      TPM_RC_TYPE             cannot create the object of the indicated type
525
//                              (usually only occurs if trying to derive an RSA key).
526
TPM_RC
527
TPM2_CreateLoaded(CreateLoaded_In*  in,  // IN: input parameter list
58✔
528
                  CreateLoaded_Out* out  // OUT: output parameter list
529
                  )
530
{
531
    TPM_RC       result = TPM_RC_SUCCESS;
58✔
532
    OBJECT*      parent = HandleToObject(in->parentHandle);
58✔
533
    OBJECT*      newObject;
58✔
534
    BOOL         derivation;
58✔
535
    TPMT_PUBLIC* publicArea;
58✔
536
    RAND_STATE   randState;
58✔
537
    RAND_STATE*  rand = &randState;
58✔
538
    TPMS_DERIVE  labelContext;
58✔
539
    SEED_COMPAT_LEVEL seedCompatLevel = RuntimeProfileGetSeedCompatLevel(); // libtpms added
58✔
540

541
    // Input Validation
542

543
    // How the public area is unmarshaled is determined by the parent, so
544
    // see if parent is a derivation parent
545
    derivation = (parent != NULL && parent->attributes.derivation);
58✔
546

547
    // If the parent is an object, then make sure that it is either a parent or
548
    // derivation parent
549
    if(parent != NULL && !parent->attributes.isParent && !derivation)
58✔
550
        return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle;
551

552
    // Get a spot in which to create the newObject
553
    newObject = FindEmptyObjectSlot(&out->objectHandle);
58✔
554
    if(newObject == NULL)
58✔
555
        return TPM_RC_OBJECT_MEMORY;
556

557
    // Do this to save typing
558
    publicArea = &newObject->publicArea;
58✔
559

560
    // Unmarshal the template into the object space. TPM2_Create() and
561
    // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher.
562
    // This command is different because of an unfortunate property of the
563
    // unique field of an ECC key. It is a structure rather than a single TPM2B. If
564
    // if had been a TPM2B, then the label and context could be within a TPM2B and
565
    // unmarshaled like other public areas. Since it is not, this command needs its
566
    // on template that is a TPM2B that is unmarshaled as a BYTE array with a
567
    // its own unmarshal function.
568
    result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, &labelContext);
58✔
569
    if(result != TPM_RC_SUCCESS)
58✔
570
        return result + RC_CreateLoaded_inPublic;
×
571

572
    // Validate that the authorization size is appropriate
573
    if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
58✔
574
        return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive;
575

576
    // Command output
577
    if(derivation)
58✔
578
        {
579
            TPMT_KEYEDHASH_SCHEME* scheme;
13✔
580
            scheme = &parent->publicArea.parameters.keyedHashDetail.scheme;
13✔
581

582
            // SP800-108 is the only KDF supported by this implementation and there is
583
            // no default hash algorithm.
584
            pAssert(scheme->details.xorr.hashAlg != TPM_ALG_NULL
13✔
585
                    && scheme->details.xorr.kdf == TPM_ALG_KDF1_SP800_108);
586
            // Don't derive RSA keys
587
            if(publicArea->type == TPM_ALG_RSA)
13✔
588
                return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
589
            if(publicArea->type == TPM_ALG_ECC &&                        // libtpms added begin
26✔
590
                RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,
13✔
591
                                                     RUNTIME_ATTRIBUTE_NO_ECC_KEY_DERIVATION))
592
                return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;                // libtpms added end
593
            // sensitiveDataOrigin has to be CLEAR in a derived object. Since this
594
            // is specific to a derived object, it is checked here.
595
            if(IS_ATTRIBUTE(
13✔
596
                            publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin))
597
                return TPM_RCS_ATTRIBUTES;
598
            // Check the rest of the attributes
599
            result = PublicAttributesValidation(parent, 0, publicArea);
13✔
600
            if(result != TPM_RC_SUCCESS)
13✔
601
                return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
×
602
            // Process the template and sensitive areas to get the actual 'label' and
603
            // 'context' values to be used for this derivation.
604
            result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
13✔
605
            if(result != TPM_RC_SUCCESS)
13✔
606
                return result;
607
            // Set up the KDF for object generation
608
            DRBG_InstantiateSeededKdf((KDF_STATE*)rand,
13✔
609
                                      scheme->details.xorr.hashAlg,
13✔
610
                                      scheme->details.xorr.kdf,
13✔
611
                                      &parent->sensitive.sensitive.bits.b,
612
                                      &labelContext.label.b,
613
                                      &labelContext.context.b,
614
                                      TPM_MAX_DERIVATION_BITS);
615
            // Clear the sensitive size so that the creation functions will not try
616
            // to use this value.
617
            in->inSensitive.sensitive.data.t.size = 0;
13✔
618
            seedCompatLevel = parent->seedCompatLevel;               // libtpms added
13✔
619
        }
620
    else
621
        {
622
            // Check attributes in input public area. CreateChecks() checks the things
623
            // that are unique to creation and then validates the attributes and values
624
            // that are common to create and load.
625
            result = CreateChecks(parent,
45✔
626
                                  (parent == NULL) ? in->parentHandle : 0,
627
                                  publicArea,
628
                                  in->inSensitive.sensitive.data.t.size);
45✔
629

630
            if(result != TPM_RC_SUCCESS)
45✔
631
                return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
×
632
            // Creating a primary object
633
            if(parent == NULL)
45✔
634
                {
635
                    TPM2B_NAME name;
43✔
636
                    TPM2B_SEED primary_seed;
43✔
637

638
                    newObject->attributes.primary = SET;
43✔
639
                    if(HierarchyNormalizeHandle(in->parentHandle) == TPM_RH_ENDORSEMENT)
43✔
640
                        newObject->attributes.epsHierarchy = SET;
12✔
641
                    seedCompatLevel = HierarchyGetPrimarySeedCompatLevel(in->parentHandle); // libtpms added
43✔
642
                    // If so, use the primary seed and the digest of the template
643
                    // to seed the DRBG
644

645
                    result = HierarchyGetPrimarySeed(in->parentHandle, &primary_seed);
43✔
646
                    if(result != TPM_RC_SUCCESS)
43✔
647
                        return result;
×
648

649
                    // If so, use the primary seed and the digest of the template
650
                    // to seed the DRBG
651
                    result = DRBG_InstantiateSeeded(
43✔
652
                                                    (DRBG_STATE*)rand,
653
                                                    &primary_seed.b,
654
                                                    PRIMARY_OBJECT_CREATION,
655
                                                    (TPM2B*)PublicMarshalAndComputeName(publicArea, &name),
43✔
656
                                                    &in->inSensitive.sensitive.data.b,
43✔
657
                                                    seedCompatLevel);        // libtpms added
658
                    MemorySet(primary_seed.b.buffer, 0, primary_seed.b.size);
43✔
659

660
                    if(result != TPM_RC_SUCCESS)
43✔
661
                        return result;
662
                }
663
            else
664
                {
665
                    // This is an ordinary object so use the normal random number generator
666
                    rand = NULL;
667
                }
668
        }
669
    // Internal data update
670
    // Create the object
671
    result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand);
58✔
672
    DRBG_Uninstantiate((DRBG_STATE*)rand);
58✔
673
    if(result != TPM_RC_SUCCESS)
58✔
674
        return result;
675
    // if this is not a Primary key and not a derived key, then return the sensitive
676
    // area
677
    if(parent != NULL && !derivation)
58✔
678
        // Prepare output private data from sensitive
679
        SensitiveToPrivate(&newObject->sensitive,
2✔
680
                           &newObject->name,
681
                           parent,
682
                           newObject->publicArea.nameAlg,
2✔
683
                           &out->outPrivate);
684
    else
685
        out->outPrivate.t.size = 0;
56✔
686
    // Set the remaining return values
687
    out->outPublic.publicArea = newObject->publicArea;
58✔
688
    out->name                 = newObject->name;
58✔
689
    // Set the remaining attributes for a loaded object
690
    ObjectSetLoadedAttributes(newObject, in->parentHandle,
58✔
691
                              seedCompatLevel); // libtpms added
692
   return result;
58✔
693
}
694

695
#endif  // CC_CreateLoaded
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc