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

stefanberger / libtpms / #2042

29 Dec 2025 05:13PM UTC coverage: 77.227% (+0.05%) from 77.174%
#2042

push

travis-ci

web-flow
Merge 5908364a4 into 4f71e9b45

36113 of 46762 relevant lines covered (77.23%)

125434.03 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

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

505
#include "Tpm.h"
506
#include "CreateLoaded_fp.h"
507

508
#if CC_CreateLoaded  // Conditional expansion of this file
509

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

567
    // Input Validation
568

569
    // How the public area is unmarshaled is determined by the parent, so
570
    // see if parent is a derivation parent
571
    derivation = (parent != NULL && parent->attributes.derivation);
58✔
572

573
    // If the parent is an object, then make sure that it is either a parent or
574
    // derivation parent
575
    if(parent != NULL && !parent->attributes.isParent && !derivation)
58✔
576
        return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle;
577

578
    // Get a spot in which to create the newObject
579
    newObject = FindEmptyObjectSlot(&out->objectHandle);
58✔
580
    if(newObject == NULL)
58✔
581
        return TPM_RC_OBJECT_MEMORY;
582

583
    // Do this to save typing
584
    publicArea = &newObject->publicArea;
58✔
585

586
    // Unmarshal the template into the object space. TPM2_Create() and
587
    // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher.
588
    // This command is different because of an unfortunate property of the
589
    // unique field of an ECC key. It is a structure rather than a single TPM2B. If
590
    // if had been a TPM2B, then the label and context could be within a TPM2B and
591
    // unmarshaled like other public areas. Since it is not, this command needs its
592
    // on template that is a TPM2B that is unmarshaled as a BYTE array with a
593
    // its own unmarshal function.
594
    result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, &labelContext);
58✔
595
    if(result != TPM_RC_SUCCESS)
58✔
596
        return result + RC_CreateLoaded_inPublic;
×
597

598
    // Validate that the authorization size is appropriate
599
    if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
58✔
600
        return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive;
601

602
    // Command output
603
    if(derivation)
58✔
604
        {
605
            TPMT_KEYEDHASH_SCHEME* scheme;
13✔
606
            scheme = &parent->publicArea.parameters.keyedHashDetail.scheme;
13✔
607

608
            // SP800-108 is the only KDF supported by this implementation and there is
609
            // no default hash algorithm.
610
            pAssert(scheme->details.xor.hashAlg != TPM_ALG_NULL
13✔
611
                    && scheme->details.xor.kdf == TPM_ALG_KDF1_SP800_108);
612
            // Don't derive RSA keys
613
            if(publicArea->type == TPM_ALG_RSA)
13✔
614
                return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
615
            if(publicArea->type == TPM_ALG_ECC &&                        // libtpms added begin
26✔
616
                RuntimeProfileRequiresAttributeFlags(&g_RuntimeProfile,
13✔
617
                                                     RUNTIME_ATTRIBUTE_NO_ECC_KEY_DERIVATION))
618
                return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;                // libtpms added end
619
            // sensitiveDataOrigin has to be CLEAR in a derived object. Since this
620
            // is specific to a derived object, it is checked here.
621
            if(IS_ATTRIBUTE(
13✔
622
                            publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin))
623
                return TPM_RCS_ATTRIBUTES;
624
            // Check the rest of the attributes
625
            result = PublicAttributesValidation(parent, 0, publicArea);
13✔
626
            if(result != TPM_RC_SUCCESS)
13✔
627
                return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
×
628
            // Process the template and sensitive areas to get the actual 'label' and
629
            // 'context' values to be used for this derivation.
630
            result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
13✔
631
            if(result != TPM_RC_SUCCESS)
13✔
632
                return result;
633
            // Set up the KDF for object generation
634
            DRBG_InstantiateSeededKdf((KDF_STATE*)rand,
13✔
635
                                      scheme->details.xor.hashAlg,
13✔
636
                                      scheme->details.xor.kdf,
13✔
637
                                      &parent->sensitive.sensitive.bits.b,
638
                                      &labelContext.label.b,
639
                                      &labelContext.context.b,
640
                                      TPM_MAX_DERIVATION_BITS);
641
            // Clear the sensitive size so that the creation functions will not try
642
            // to use this value.
643
            in->inSensitive.sensitive.data.t.size = 0;
13✔
644
            seedCompatLevel = parent->seedCompatLevel;               // libtpms added
13✔
645
        }
646
    else
647
        {
648
            // Check attributes in input public area. CreateChecks() checks the things
649
            // that are unique to creation and then validates the attributes and values
650
            // that are common to create and load.
651
            result = CreateChecks(parent,
45✔
652
                                  (parent == NULL) ? in->parentHandle : 0,
653
                                  publicArea,
654
                                  in->inSensitive.sensitive.data.t.size);
45✔
655

656
            if(result != TPM_RC_SUCCESS)
45✔
657
                return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
×
658
            // Creating a primary object
659
            if(parent == NULL)
45✔
660
                {
661
                    TPM2B_NAME name;
43✔
662
                    TPM2B_SEED primary_seed;
43✔
663

664
                    newObject->attributes.primary = SET;
43✔
665
                    if(HierarchyNormalizeHandle(in->parentHandle) == TPM_RH_ENDORSEMENT)
43✔
666
                        newObject->attributes.epsHierarchy = SET;
12✔
667
                    seedCompatLevel = HierarchyGetPrimarySeedCompatLevel(in->parentHandle); // libtpms added
43✔
668
                    // If so, use the primary seed and the digest of the template
669
                    // to seed the DRBG
670

671
                    result = HierarchyGetPrimarySeed(in->parentHandle, &primary_seed);
43✔
672
                    if(result != TPM_RC_SUCCESS)
43✔
673
                        return result;
×
674

675
                    // If so, use the primary seed and the digest of the template
676
                    // to seed the DRBG
677
                    result = DRBG_InstantiateSeeded(
43✔
678
                                                    (DRBG_STATE*)rand,
679
                                                    &primary_seed.b,
680
                                                    PRIMARY_OBJECT_CREATION,
681
                                                    (TPM2B*)PublicMarshalAndComputeName(publicArea, &name),
43✔
682
                                                    &in->inSensitive.sensitive.data.b,
43✔
683
                                                    seedCompatLevel);        // libtpms added
684
                    MemorySet(primary_seed.b.buffer, 0, primary_seed.b.size);
43✔
685

686
                    if(result != TPM_RC_SUCCESS)
43✔
687
                        return result;
688
                }
689
            else
690
                {
691
                    // This is an ordinary object so use the normal random number generator
692
                    rand = NULL;
693
                }
694
        }
695
    // Internal data update
696
    // Create the object
697
    result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand);
58✔
698
    DRBG_Uninstantiate((DRBG_STATE*)rand);
58✔
699
    if(result != TPM_RC_SUCCESS)
58✔
700
        return result;
701
    // if this is not a Primary key and not a derived key, then return the sensitive
702
    // area
703
    if(parent != NULL && !derivation)
58✔
704
        // Prepare output private data from sensitive
705
        SensitiveToPrivate(&newObject->sensitive,
2✔
706
                           &newObject->name,
707
                           parent,
708
                           newObject->publicArea.nameAlg,
2✔
709
                           &out->outPrivate);
710
    else
711
        out->outPrivate.t.size = 0;
56✔
712
    // Set the remaining return values
713
    out->outPublic.publicArea = newObject->publicArea;
58✔
714
    out->name                 = newObject->name;
58✔
715
    // Set the remaining attributes for a loaded object
716
    ObjectSetLoadedAttributes(newObject, in->parentHandle,
58✔
717
                              seedCompatLevel); // libtpms added
718
   return result;
58✔
719
}
720

721
#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