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

stefanberger / libtpms / 2698

pending completion
2698

Pull #353

travis-ci-com

web-flow
Merge a8cae3f5d into d08b929de
Pull Request #353: Travis: Update from bionic to focal and from xenial to bionic

33875 of 43923 relevant lines covered (77.12%)

93992.6 hits per line

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

91.07
/src/tpm2/Object.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                Manage the object store of the TPM.                                    */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*            $Id: Object.c 1658 2021-01-22 23:14:01Z 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 - 2021                                */
59
/*                                                                                */
60
/********************************************************************************/
61

62
/* 8.6 Object.c */
63
/* 8.6.1 Introduction */
64
/* This file contains the functions that manage the object store of the TPM. */
65
/* 8.6.2 Includes and Data Definitions */
66
#define OBJECT_C
67
#include "Tpm.h"
68
#include "NVMarshal.h" // libtpms added
69
#include "BackwardsCompatibilityObject.h" // libtpms added
70
/* 8.6.3 Functions */
71
/* 8.6.3.1 ObjectFlush() */
72
/* This function marks an object slot as available. Since there is no checking of the input
73
   parameters, it should be used judiciously. */
74
/* NOTE: This could be converted to a macro. */
75
void
76
ObjectFlush(
14,222✔
77
            OBJECT          *object
78
            )
79
{
80
    object->attributes.occupied = CLEAR;
14,222✔
81
}
14,222✔
82
/* 8.6.3.2 ObjectSetInUse() */
83
/* This access function sets the occupied attribute of an object slot. */
84
void
85
ObjectSetInUse(
1,768✔
86
               OBJECT          *object
87
               )
88
{
89
    object->attributes.occupied = SET;
1,768✔
90
}
1,768✔
91
/* 8.6.3.3 ObjectStartup() */
92
/* This function is called at TPM2_Startup() to initialize the object subsystem. */
93
BOOL
94
ObjectStartup(
4,108✔
95
              void
96
              )
97
{
98
    UINT32      i;
4,108✔
99
    // object slots initialization
100
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
16,432✔
101
        {
102
            //Set the slot to not occupied
103
            ObjectFlush(&s_objects[i]);
12,324✔
104
        }
105
    return TRUE;
4,108✔
106
}
107
/* 8.6.3.4 ObjectCleanupEvict() */
108
/* In this implementation, a persistent object is moved from NV into an object slot for
109
   processing. It is flushed after command execution. This function is called from
110
   ExecuteCommand(). */
111
void
112
ObjectCleanupEvict(
16,791✔
113
                   void
114
                   )
115
{
116
    UINT32      i;
16,791✔
117
    // This has to be iterated because a command may have two handles
118
    // and they may both be persistent.
119
    // This could be made to be more efficient so that a search is not needed.
120
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
67,164✔
121
        {
122
            // If an object is a temporary evict object, flush it from slot
123
            OBJECT      *object = &s_objects[i];
50,373✔
124
            if(object->attributes.evict == SET)
50,373✔
125
                ObjectFlush(object);
1,898✔
126
        }
127
    return;
16,791✔
128
}
129
/* 8.6.3.5 IsObjectPresent() */
130
/* This function checks to see if a transient handle references a loaded object.  This routine
131
   should not be called if the handle is not a transient handle. The function validates that the
132
   handle is in the implementation-dependent allowed in range for loaded transient objects. */
133
/* Return Values Meaning */
134
/* TRUE if the handle references a loaded object */
135
/* FALSE if the handle is not an object handle, or it does not reference to a loaded object */
136
BOOL
137
IsObjectPresent(
3,609✔
138
                TPMI_DH_OBJECT   handle         // IN: handle to be checked
139
                )
140
{
141
    UINT32          slotIndex = handle - TRANSIENT_FIRST;
3,609✔
142
    // Since the handle is just an index into the array that is zero based, any
143
    // handle value outsize of the range of:
144
    //    TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1)
145
    // will now be greater than or equal to MAX_LOADED_OBJECTS
146
    if(slotIndex >= MAX_LOADED_OBJECTS)
3,609✔
147
        return FALSE;
148
    // Indicate if the slot is occupied
149
    return (s_objects[slotIndex].attributes.occupied == TRUE);
3,609✔
150
}
151
/* 8.6.3.6 ObjectIsSequence() */
152
/* This function is used to check if the object is a sequence object. This function should not be
153
   called if the handle does not reference a loaded object. */
154
/* Return Values Meaning */
155
/* TRUE object is an HMAC, hash, or event sequence object */
156
/* FALSE object is not an HMAC, hash, or event sequence object */
157
BOOL
158
ObjectIsSequence(
106,759✔
159
                 OBJECT          *object         // IN: handle to be checked
160
                 )
161
{
162
    pAssert(object != NULL);
106,759✔
163
    return (object->attributes.hmacSeq == SET
106,759✔
164
            || object->attributes.hashSeq == SET
165
            || object->attributes.eventSeq == SET);
106,759✔
166
}
167
/* 8.6.3.7 HandleToObject() */
168
/* This function is used to find the object structure associated with a handle. */
169
/* This function requires that handle references a loaded object or a permanent handle. */
170
OBJECT*
171
HandleToObject(
16,410✔
172
               TPMI_DH_OBJECT   handle         // IN: handle of the object
173
               )
174
{
175
    UINT32              index;
16,410✔
176
    // Return NULL if the handle references a permanent handle because there is no
177
    // associated OBJECT.
178
    if(HandleGetType(handle) == TPM_HT_PERMANENT)
16,410✔
179
        return NULL;
180
    // In this implementation, the handle is determined by the slot occupied by the
181
    // object.
182
    index = handle - TRANSIENT_FIRST;
15,580✔
183
    pAssert(index < MAX_LOADED_OBJECTS);
15,580✔
184
    pAssert(s_objects[index].attributes.occupied);
15,580✔
185
    return &s_objects[index];
15,580✔
186
}
187
/* 8.6.3.9 GetQualifiedName() */
188
/* This function returns the Qualified Name of the object. In this implementation, the Qualified
189
   Name is computed when the object is loaded and is saved in the internal representation of the
190
   object. The alternative would be to retain the Name of the parent and compute the QN when
191
   needed. This would take the same amount of space so it is not recommended that the alternate be
192
   used. */
193
/* This function requires that handle references a loaded object. */
194
void
195
GetQualifiedName(
1,031✔
196
                 TPMI_DH_OBJECT   handle,        // IN: handle of the object
197
                 TPM2B_NAME      *qualifiedName  // OUT: qualified name of the object
198
                 )
199
{
200
    OBJECT      *object;
1,031✔
201
    switch(HandleGetType(handle))
1,031✔
202
        {
203
          case TPM_HT_PERMANENT:
628✔
204
            qualifiedName->t.size = sizeof(TPM_HANDLE);
628✔
205
            UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name);
628✔
206
            break;
628✔
207
          case TPM_HT_TRANSIENT:
403✔
208
            object = HandleToObject(handle);
403✔
209
            if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL)
403✔
210
                qualifiedName->t.size = 0;
×
211
            else
212
                // Copy the name
213
                *qualifiedName = object->qualifiedName;
403✔
214
            break;
215
          default:
×
216
            FAIL(FATAL_ERROR_INTERNAL);
×
217
        }
218
    return;
1,031✔
219
}
220
/* 8.6.3.10 ObjectGetHierarchy() */
221
/* This function returns the handle for the hierarchy of an object. */
222
TPMI_RH_HIERARCHY
223
ObjectGetHierarchy(
1,115✔
224
                   OBJECT          *object         // IN :object
225
                   )
226
{
227
    if(object->attributes.spsHierarchy)
1,115✔
228
        {
229
            return TPM_RH_OWNER;
230
        }
231
    else if(object->attributes.epsHierarchy)
327✔
232
        {
233
            return TPM_RH_ENDORSEMENT;
234
        }
235
    else if(object->attributes.ppsHierarchy)
327✔
236
        {
237
            return TPM_RH_PLATFORM;
238
        }
239
    else
240
        {
241
            return TPM_RH_NULL;
43✔
242
        }
243
}
244
/* 8.6.3.11 GetHierarchy() */
245
/* This function returns the handle of the hierarchy to which a handle belongs. This function is
246
   similar to ObjectGetHierarchy() but this routine takes a handle while ObjectGetHierarchy() takes
247
   a pointer to an object. */
248
/* This function requires that handle references a loaded object. */
249
TPMI_RH_HIERARCHY
250
GetHieriarchy(
705✔
251
             TPMI_DH_OBJECT   handle         // IN :object handle
252
             )
253
{
254
    OBJECT          *object = HandleToObject(handle);
705✔
255
    return ObjectGetHierarchy(object);
705✔
256
}
257
/* 8.6.3.12 FindEmptyObjectSlot() */
258
/* This function finds an open object slot, if any. It will clear the attributes but will not set
259
   the occupied attribute. This is so that a slot may be used and discarded if everything does not
260
   go as planned. */
261
/* Return Values Meaning */
262
/* null no open slot found */
263
/* !=null pointer to available slot */
264
OBJECT *
265
FindEmptyObjectSlot(
2,485✔
266
                    TPMI_DH_OBJECT  *handle         // OUT: (optional)
267
                    )
268
{
269
    UINT32               i;
2,485✔
270
    OBJECT              *object;
2,485✔
271
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
4,088✔
272
        {
273
            object = &s_objects[i];
4,088✔
274
            if(object->attributes.occupied == CLEAR)
4,088✔
275
                {
276
                    if(handle)
2,485✔
277
                        *handle = i + TRANSIENT_FIRST;
2,215✔
278
                    // Initialize the object attributes
279
                    // MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES));
280
                    MemorySet(object, 0, sizeof(*object)); // libtpms added: Initialize the whole object
2,485✔
281
                    return object;
2,485✔
282
                }
283
        }
284
    return NULL;
285
}
286
/* 8.6.3.13 ObjectAllocateSlot() */
287
/* This function is used to allocate a slot in internal object array. */
288
/* Return Values Meaning */
289
OBJECT *
290
ObjectAllocateSlot(
599✔
291
                   TPMI_DH_OBJECT  *handle        // OUT: handle of allocated object
292
                   )
293
{
294
    OBJECT          *object = FindEmptyObjectSlot(handle);
599✔
295
    if(object != NULL)
599✔
296
        {
297
            // if found, mark as occupied
298
            ObjectSetInUse(object);
599✔
299
        }
300
    return object;
599✔
301
}
302
/* 8.6.3.14 ObjectSetLoadedAttributes() */
303
/* This function sets the internal attributes for a loaded object. It is called to finalize the
304
   OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded object. */
305
void
306
ObjectSetLoadedAttributes(
1,169✔
307
                          OBJECT          *object,        // IN: object attributes to finalize
308
                          TPM_HANDLE       parentHandle,  // IN: the parent handle
309
                          SEED_COMPAT_LEVEL seedCompatLevel // IN: seed compat level to use for children
310
                          )
311
{
312
    OBJECT              *parent = HandleToObject(parentHandle);
1,169✔
313
    TPMA_OBJECT          objectAttributes = object->publicArea.objectAttributes;
1,169✔
314

315
    object->seedCompatLevel = seedCompatLevel; // libtpms added
1,169✔
316
    //
317
    // Copy the stClear attribute from the public area. This could be overwritten
318
    // if the parent has stClear SET
319
    object->attributes.stClear =
1,169✔
320
        IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear);
1,169✔
321
    // If parent handle is a permanent handle, it is a primary (unless it is NULL
322
    if(parent == NULL)
1,169✔
323
        {
324
            object->attributes.primary = SET;
771✔
325
            switch(parentHandle)
771✔
326
                {
327
                  case TPM_RH_ENDORSEMENT:
309✔
328
                    object->attributes.epsHierarchy = SET;
309✔
329
                    break;
309✔
330
                  case TPM_RH_OWNER:
215✔
331
                    object->attributes.spsHierarchy = SET;
215✔
332
                    break;
215✔
333
                  case TPM_RH_PLATFORM:
63✔
334
                    object->attributes.ppsHierarchy = SET;
63✔
335
                    break;
63✔
336
                  default:
184✔
337
                    // Treat the temporary attribute as a hierarchy
338
                    object->attributes.temporary = SET;
184✔
339
                    object->attributes.primary = CLEAR;
184✔
340
                    break;
184✔
341
                }
342
        }
343
    else
344
        {
345
            // is this a stClear object
346
            object->attributes.stClear =
796✔
347
                (IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear)
348
                 || (parent->attributes.stClear == SET));
398✔
349
            object->attributes.epsHierarchy = parent->attributes.epsHierarchy;
398✔
350
            object->attributes.spsHierarchy = parent->attributes.spsHierarchy;
398✔
351
            object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy;
398✔
352
            // An object is temporary if its parent is temporary or if the object
353
            // is external
354
            object->attributes.temporary = parent->attributes.temporary
796✔
355
                                           || object->attributes.external;
796✔
356
        }
357
    // If this is an external object, set the QN == name but don't SET other
358
    // key properties ('parent' or 'derived')
359
    if(object->attributes.external)
1,169✔
360
        object->qualifiedName = object->name;
143✔
361
    else
362
        {
363
            // check attributes for different types of parents
364
            if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted)
1,026✔
365
               && !object->attributes.publicOnly
446✔
366
               && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt)
446✔
367
               && object->publicArea.nameAlg != TPM_ALG_NULL)
423✔
368
                {
369
                    // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent.
370
                    // Otherwise, it is a derivation parent.
371
                    if(object->publicArea.type == TPM_ALG_KEYEDHASH)
423✔
372
                        object->attributes.derivation = SET;
3✔
373
                    else
374
                        object->attributes.isParent = SET;
420✔
375
                }
376
            ComputeQualifiedName(parentHandle, object->publicArea.nameAlg,
1,026✔
377
                                 &object->name, &object->qualifiedName);
378
        }
379
    // Set slot occupied
380
    ObjectSetInUse(object);
1,169✔
381
    return;
1,169✔
382
}
383
/* 8.6.3.15 ObjectLoad() */
384
/* Common function to load an object. A loaded object has its public area validated (unless its
385
   nameAlg is TPM_ALG_NULL). If a sensitive part is loaded, it is verified to be correct and if both
386
   public and sensitive parts are loaded, then the cryptographic binding between the objects is
387
   validated. This function does not cause the allocated slot to be marked as in use. */
388
TPM_RC
389
ObjectLoad(
1,018✔
390
           OBJECT          *object,        // IN: pointer to object slot
391
           //     object
392
           OBJECT          *parent,        // IN: (optional) the parent object
393
           TPMT_PUBLIC     *publicArea,    // IN: public area to be installed in the object
394
           TPMT_SENSITIVE  *sensitive,     // IN: (optional) sensitive area to be
395
           //      installed in the object
396
           TPM_RC           blamePublic,   // IN: parameter number to associate with the
397
           //     publicArea errors
398
           TPM_RC           blameSensitive,// IN: parameter number to associate with the
399
           //     sensitive area errors
400
           TPM2B_NAME      *name           // IN: (optional)
401
           )
402
{
403
    TPM_RC           result = TPM_RC_SUCCESS;
1,018✔
404
    BOOL             doCheck;
1,018✔
405
    //
406
    // Do validations of public area object descriptions
407
    // Is this public only or a no-name object?
408
    if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL)
1,018✔
409
        {
410
            // Need to have schemes checked so that we do the right thing with the
411
            // public key.
412
            result = SchemeChecks(NULL, publicArea);
157✔
413
        }
414
    else
415
        {
416
            // For any sensitive area, make sure that the seedSize is no larger than the
417
            // digest size of nameAlg
418
            if(sensitive->seedValue.t.size
861✔
419
               > CryptHashGetDigestSize(publicArea->nameAlg))
861✔
420
                return TPM_RCS_KEY_SIZE + blameSensitive;
8✔
421
            // Check attributes and schemes for consistency
422
            result = PublicAttributesValidation(parent, publicArea);
853✔
423
        }
424
    if(result != TPM_RC_SUCCESS)
1,010✔
425
        return RcSafeAddToResult(result, blamePublic);
44✔
426
    // If object == NULL, then this is am import. For import, load is not called
427
    // unless the parent is fixedTPM.
428
    if(object == NULL)
966✔
429
        doCheck = TRUE;// //
430
    // If the parent is not NULL, then this is an ordinary load and we only check
431
    // if the parent is not fixedTPM
432
    else if(parent != NULL)
877✔
433
        doCheck = !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
394✔
434
                                TPMA_OBJECT, fixedTPM);
435
    else
436
        // This is a loadExternal. Check everything.
437
        // Note: the check functions will filter things based on the name algorithm
438
        // and whether or not both parts are loaded.
439
        doCheck = TRUE;
440
    // Note: the parent will be NULL if this is a load external. CryptValidateKeys()
441
    // will only check the parts that need to be checked based on the settings
442
    // of publicOnly and nameAlg.
443
    // Note: For an RSA key, the keys sizes are checked but the binding is not
444
    // checked.
445
    if(doCheck)
394✔
446
        {
447
            // Do the cryptographic key validation
448
            result = CryptValidateKeys(publicArea, sensitive, blamePublic,
574✔
449
                                       blameSensitive);
450
        }
451
    // If this is an import, we are done
452
    if(object == NULL || result != TPM_RC_SUCCESS)
966✔
453
        return result;
454
    // Set the name, if one was provided
455
    if(name != NULL)
561✔
456
        object->name = *name;
561✔
457
    else
458
        object->name.t.size = 0;
×
459
    // Initialize public
460
    object->publicArea = *publicArea;
561✔
461
    // If there is a sensitive area, load it
462
    if(sensitive == NULL)
561✔
463
        object->attributes.publicOnly = SET;
85✔
464
    else
465
        {
466
            object->sensitive = *sensitive;
476✔
467
#if ALG_RSA
468
            // If this is an RSA key that is not a parent, complete the load by
469
            // computing the private exponent.
470
            if(publicArea->type == ALG_RSA_VALUE)
476✔
471
                result = CryptRsaLoadPrivateExponent(object);
290✔
472
#endif
473
        }
474
    return result;
475
}
476
/* 8.6.3.16 AllocateSequenceSlot() */
477
/* This function allocates a sequence slot and initializes the parts that are used by the normal
478
   objects so that a sequence object is not inadvertently used for an operation that is not
479
   appropriate for a sequence. */
480
static HASH_OBJECT *
481
AllocateSequenceSlot(
87✔
482
                     TPM_HANDLE      *newHandle,     // OUT: receives the allocated handle
483
                     TPM2B_AUTH      *auth           // IN: the authValue for the slot
484
                     )
485
{
486
    HASH_OBJECT      *object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle);
87✔
487
    //
488
    // Validate that the proper location of the hash state data relative to the
489
    // object state data. It would be good if this could have been done at compile
490
    // time but it can't so do it in something that can be removed after debug.
491
    cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy));
87✔
492
    if(object != NULL)
87✔
493
        {
494
            // Set the common values that a sequence object shares with an ordinary object
495
            // First, clear all attributes
496
            MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT));
87✔
497
            // The type is TPM_ALG_NULL
498
            object->type = TPM_ALG_NULL;
87✔
499
            // This has no name algorithm and the name is the Empty Buffer
500
            object->nameAlg = TPM_ALG_NULL;
87✔
501
            // A sequence object is considered to be in the NULL hierarchy so it should
502
            // be marked as temporary so that it can't be persisted
503
            object->attributes.temporary = SET;
87✔
504
            // A sequence object is DA exempt.
505
            SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA);
87✔
506
            // Copy the authorization value
507
            if(auth != NULL)
87✔
508
                object->auth = *auth;
56✔
509
            else
510
                object->auth.t.size = 0;
31✔
511
        }
512
    return object;
87✔
513
}
514
/* 8.6.3.17 ObjectCreateHMACSequence() */
515
/* This function creates an internal HMAC sequence object. */
516
/* Error Returns Meaning */
517
/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */
518
#if CC_HMAC_Start || CC_MAC_Start
519
TPM_RC
520
ObjectCreateHMACSequence(
16✔
521
                         TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
522
                         OBJECT          *keyObject,     // IN: the object containing the HMAC key
523
                         TPM2B_AUTH      *auth,          // IN: authValue
524
                         TPMI_DH_OBJECT  *newHandle      // OUT: HMAC sequence object handle
525
                         )
526
{
527
    HASH_OBJECT         *hmacObject;
16✔
528
    //
529
    // Try to allocate a slot for new object
530
    hmacObject = AllocateSequenceSlot(newHandle, auth);
16✔
531
    if(hmacObject == NULL)
16✔
532
        return TPM_RC_OBJECT_MEMORY;
533
    // Set HMAC sequence bit
534
    hmacObject->attributes.hmacSeq = SET;
16✔
535
#if !SMAC_IMPLEMENTED
536
    if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg,
537
                      keyObject->sensitive.sensitive.bits.b.size,
538
                      keyObject->sensitive.sensitive.bits.b.buffer) == 0)
539
#else
540
        if(CryptMacStart(&hmacObject->state.hmacState,
16✔
541
                         &keyObject->publicArea.parameters,
542
                         hashAlg, &keyObject->sensitive.sensitive.any.b) == 0)
543
#endif // SMAC_IMPLEMENTED
544
            return TPM_RC_FAILURE;
×
545
    return TPM_RC_SUCCESS;
546
}
547
#endif
548

549
/* 8.6.3.18 ObjectCreateHashSequence() */
550
/* This function creates a hash sequence object. */
551
/* Error Returns Meaning */
552
/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */
553
TPM_RC
554
ObjectCreateHashSequence(
21✔
555
                         TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
556
                         TPM2B_AUTH      *auth,          // IN: authValue
557
                         TPMI_DH_OBJECT  *newHandle      // OUT: sequence object handle
558
                         )
559
{
560
    HASH_OBJECT         *hashObject = AllocateSequenceSlot(newHandle, auth);
21✔
561
    // See if slot allocated
562
    if(hashObject == NULL)
21✔
563
        return TPM_RC_OBJECT_MEMORY;
564
    // Set hash sequence bit
565
    hashObject->attributes.hashSeq = SET;
21✔
566
    // Start hash for hash sequence
567
    CryptHashStart(&hashObject->state.hashState[0], hashAlg);
21✔
568
    return TPM_RC_SUCCESS;
21✔
569
}
570
/* 8.6.3.19 ObjectCreateEventSequence() */
571
/* This function creates an event sequence object. */
572
/* Error Returns Meaning */
573
/* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */
574
TPM_RC
575
ObjectCreateEventSequence(
50✔
576
                          TPM2B_AUTH      *auth,          // IN: authValue
577
                          TPMI_DH_OBJECT  *newHandle      // OUT: sequence object handle
578
                          )
579
{
580
    HASH_OBJECT         *hashObject = AllocateSequenceSlot(newHandle, auth);
50✔
581
    UINT32               count;
50✔
582
    TPM_ALG_ID           hash;
50✔
583
    // See if slot allocated
584
    if(hashObject == NULL)
50✔
585
        return TPM_RC_OBJECT_MEMORY;
586
    // Set the event sequence attribute
587
    hashObject->attributes.eventSeq = SET;
50✔
588
    // Initialize hash states for each implemented PCR algorithms
589
    for(count = 0; (hash = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++)
250✔
590
        CryptHashStart(&hashObject->state.hashState[count], hash);
200✔
591
    return TPM_RC_SUCCESS;
592
}
593
/* 8.6.3.20 ObjectTerminateEvent() */
594
/* This function is called to close out the event sequence and clean up the hash context states. */
595
void
596
ObjectTerminateEvent(
×
597
                     void
598
                     )
599
{
600
    HASH_OBJECT         *hashObject;
×
601
    int                  count;
×
602
    BYTE                 buffer[MAX_DIGEST_SIZE];
×
603
    hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
×
604
    // Don't assume that this is a proper sequence object
605
    if(hashObject->attributes.eventSeq)
×
606
        {
607
            // If it is, close any open hash contexts. This is done in case
608
            // the cryptographic implementation has some context values that need to be
609
            // cleaned up (hygiene).
610
            //
611
            for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++)
×
612
                {
613
                    CryptHashEnd(&hashObject->state.hashState[count], 0, buffer);
×
614
                }
615
            // Flush sequence object
616
            FlushObject(g_DRTMHandle);
×
617
        }
618
    g_DRTMHandle = TPM_RH_UNASSIGNED;
×
619
}
620
/* 8.6.3.21 ObjectContextLoad() */
621
/* This function loads an object from a saved object context. */
622
/* Return Values Meaning */
623
/* NULL if there is no free slot for an object */
624
/* NON_NULL points to the loaded object */
625
#if 0                        // libtpms added
626
OBJECT *
627
ObjectContextLoad(
628
                  ANY_OBJECT_BUFFER   *object,        // IN: pointer to object structure in saved
629
                  //     context
630
                  TPMI_DH_OBJECT      *handle         // OUT: object handle
631
                  )
632
{
633
    OBJECT      *newObject = ObjectAllocateSlot(handle);
634
    // Try to allocate a slot for new object
635
    if(newObject != NULL)
636
        {
637
            // Copy the first part of the object
638
            MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state));
639
            // See if this is a sequence object
640
            if(ObjectIsSequence(newObject))
641
                {
642
                    // If this is a sequence object, import the data
643
                    SequenceDataImport((HASH_OBJECT *)newObject,
644
                                       (HASH_OBJECT_BUFFER *)object);
645
                }
646
            else
647
                {
648
                    // Copy input object data to internal structure
649
                    MemoryCopy(newObject, object, sizeof(OBJECT));
650
                }
651
        }
652
    return newObject;
653
}
654
#endif                         // libtpms added begin
655

656
OBJECT *
657
ObjectContextLoadLibtpms(BYTE           *buffer,
10✔
658
                         INT32           size,
659
                         TPMI_DH_OBJECT *handle
660
                         )
661
{
662
    OBJECT      *newObject = ObjectAllocateSlot(handle);
10✔
663
    TPM_RC       rc;
10✔
664
    BYTE        *mybuf  = buffer;
10✔
665
    INT32        mysize = size;
10✔
666

667
    pAssert(handle);
10✔
668

669
    // Try to allocate a slot for new object
670
    if(newObject != NULL)
10✔
671
        {
672
            rc = ANY_OBJECT_Unmarshal(newObject, &mybuf, &mysize, false);
10✔
673
            if (rc) {
10✔
674
                 /* Attempt to load an old OBJECT that was copied out directly from
675
                  * an older version of OBJECT.
676
                  */
677
                rc = OLD_OBJECTToOBJECT(newObject, buffer, size);
×
678
                if (rc) {
×
679
                    FlushObject(*handle);
×
680
                    newObject = NULL;
×
681
                }
682
            }
683
        }
684
    return newObject;
10✔
685
}                        // libtpms added end
686

687
/* 8.6.3.22 FlushObject() */
688
/* This function frees an object slot. */
689
/* This function requires that the object is loaded. */
690
void
691
FlushObject(
675✔
692
            TPMI_DH_OBJECT   handle         // IN: handle to be freed
693
            )
694
{
695
    UINT32      index = handle - TRANSIENT_FIRST;
675✔
696
    pAssert(index < MAX_LOADED_OBJECTS);
675✔
697
    // Clear all the object attributes
698
    MemorySet((BYTE*)&(s_objects[index].attributes),
675✔
699
              0, sizeof(OBJECT_ATTRIBUTES));
700
    return;
675✔
701
}
702
/* 8.6.3.23 ObjectFlushHierarchy() */
703
/* This function is called to flush all the loaded transient objects associated with a hierarchy
704
   when the hierarchy is disabled. */
705
void
706
ObjectFlushHierarchy(
34✔
707
                     TPMI_RH_HIERARCHY    hierarchy      // IN: hierarchy to be flush
708
                     )
709
{
710
    UINT16          i;
34✔
711
    // iterate object slots
712
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
136✔
713
        {
714
            if(s_objects[i].attributes.occupied)          // If found an occupied slot
102✔
715
                {
716
                    switch(hierarchy)
11✔
717
                        {
718
                          case TPM_RH_PLATFORM:
2✔
719
                            if(s_objects[i].attributes.ppsHierarchy == SET)
2✔
720
                                s_objects[i].attributes.occupied = FALSE;
2✔
721
                            break;
722
                          case TPM_RH_OWNER:
6✔
723
                            if(s_objects[i].attributes.spsHierarchy == SET)
6✔
724
                                s_objects[i].attributes.occupied = FALSE;
4✔
725
                            break;
726
                          case TPM_RH_ENDORSEMENT:
3✔
727
                            if(s_objects[i].attributes.epsHierarchy == SET)
3✔
728
                                s_objects[i].attributes.occupied = FALSE;
2✔
729
                            break;
730
                          default:
×
731
                            FAIL(FATAL_ERROR_INTERNAL);
×
732
                            break;
102✔
733
                        }
734
                }
91✔
735
        }
736
    return;
34✔
737
}
738
/* 8.6.3.24 ObjectLoadEvict() */
739
/* This function loads a persistent object into a transient object slot. */
740
/* This function requires that handle is associated with a persistent object. */
741
/* Error Returns Meaning */
742
/* TPM_RC_HANDLE the persistent object does not exist or the associated hierarchy is disabled. */
743
/* TPM_RC_OBJECT_MEMORY no object slot */
744
TPM_RC
745
ObjectLoadEvict(
502✔
746
                TPM_HANDLE      *handle,        // IN:OUT: evict object handle.  If success, it
747
                // will be replace by the loaded object handle
748
                COMMAND_INDEX    commandIndex   // IN: the command being processed
749
                )
750
{
751
    TPM_RC          result;
502✔
752
    TPM_HANDLE      evictHandle = *handle;   // Save the evict handle
502✔
753
    OBJECT          *object;
502✔
754
    // If this is an index that references a persistent object created by
755
    // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE
756
    if(*handle >= PLATFORM_PERSISTENT)
502✔
757
        {
758
            // belongs to platform
759
            if(g_phEnable == CLEAR)
51✔
760
                return TPM_RC_HANDLE;
761
        }
762
    // belongs to owner
763
    else if(gc.shEnable == CLEAR)
451✔
764
        return TPM_RC_HANDLE;
765
    // Try to allocate a slot for an object
766
    object = ObjectAllocateSlot(handle);
502✔
767
    if(object == NULL)
502✔
768
        return TPM_RC_OBJECT_MEMORY;
769
    // Copy persistent object to transient object slot.  A TPM_RC_HANDLE
770
    // may be returned at this point. This will mark the slot as containing
771
    // a transient object so that it will be flushed at the end of the
772
    // command
773
    result = NvGetEvictObject(evictHandle, object);
502✔
774
    // Bail out if this failed
775
    if(result != TPM_RC_SUCCESS)
502✔
776
        return result;
777
    // check the object to see if it is in the endorsement hierarchy
778
    // if it is and this is not a TPM2_EvictControl() command, indicate
779
    // that the hierarchy is disabled.
780
    // If the associated hierarchy is disabled, make it look like the
781
    // handle is not defined
782
    if(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT
400✔
783
       && gc.ehEnable == CLEAR
×
784
       && GetCommandCode(commandIndex) != TPM_CC_EvictControl)
×
785
        return TPM_RC_HANDLE;
×
786
    return result;
787
}
788
/* 8.6.3.25 ObjectComputeName() */
789
/* This does the name computation from a public area (can be marshaled or not). */
790
TPM2B_NAME *
791
ObjectComputeName(
2,553✔
792
                  UINT32           size,          // IN: the size of the area to digest
793
                  BYTE            *publicArea,    // IN: the public area to digest
794
                  TPM_ALG_ID       nameAlg,       // IN: the hash algorithm to use
795
                  TPM2B_NAME      *name           // OUT: Computed name
796
                  )
797
{
798
    // Hash the publicArea into the name buffer leaving room for the nameAlg
799
    name->t.size = CryptHashBlock(nameAlg, size, publicArea,
2,553✔
800
                                  sizeof(name->t.name) - 2,
801
                                  &name->t.name[2]);
802
    // set the nameAlg
803
    UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name);
2,553✔
804
    name->t.size += 2;
2,553✔
805
    return name;
2,553✔
806
}
807
/* 8.6.3.26 PublicMarshalAndComputeName() */
808
/* This function computes the Name of an object from its public area. */
809
TPM2B_NAME *
810
PublicMarshalAndComputeName(
2,557✔
811
                            TPMT_PUBLIC     *publicArea,    // IN: public area of an object
812
                            TPM2B_NAME      *name           // OUT: name of the object
813
                            )
814
{
815
    // Will marshal a public area into a template. This is because the internal
816
    // format for a TPM2B_PUBLIC is a structure and not a simple BYTE buffer.
817
    TPM2B_TEMPLATE       marshaled;     // this is big enough to hold a
2,557✔
818
    //  marshaled TPMT_PUBLIC
819
    BYTE                *buffer = (BYTE *)&marshaled.t.buffer;
2,557✔
820
    // if the nameAlg is NULL then there is no name.
821
    if(publicArea->nameAlg == TPM_ALG_NULL)
2,557✔
822
        name->t.size = 0;
4✔
823
    else
824
        {
825
            // Marshal the public area into its canonical form
826
            marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL);
2,553✔
827
            // and compute the name
828
            ObjectComputeName(marshaled.t.size, marshaled.t.buffer,
2,553✔
829
                              publicArea->nameAlg, name);
2,553✔
830
        }
831
    return name;
2,557✔
832
}
833
/* 8.6.3.28 ComputeQualifiedName() */
834
/* This function computes the qualified name of an object. */
835
void
836
ComputeQualifiedName(
1,031✔
837
                     TPM_HANDLE       parentHandle,  // IN: parent's handle
838
                     TPM_ALG_ID       nameAlg,       // IN: name hash
839
                     TPM2B_NAME      *name,          // IN: name of the object
840
                     TPM2B_NAME      *qualifiedName  // OUT: qualified name of the object
841
                     )
842
{
843
    HASH_STATE      hashState;   // hash state
1,031✔
844
    TPM2B_NAME      parentName;
1,031✔
845
    if(parentHandle == TPM_RH_UNASSIGNED)
1,031✔
846
        {
847
            MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name));
×
848
            *qualifiedName = *name;
×
849
        }
850
    else
851
        {
852
            GetQualifiedName(parentHandle, &parentName);
1,031✔
853
            //      QN_A = hash_A (QN of parent || NAME_A)
854
            // Start hash
855
            qualifiedName->t.size = CryptHashStart(&hashState, nameAlg);
1,031✔
856
            // Add parent's qualified name
857
            CryptDigestUpdate2B(&hashState, &parentName.b);
1,031✔
858
            // Add self name
859
            CryptDigestUpdate2B(&hashState, &name->b);
1,031✔
860
            // Complete hash leaving room for the name algorithm
861
            CryptHashEnd(&hashState, qualifiedName->t.size,
1,031✔
862
                         &qualifiedName->t.name[2]);
863
            UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
1,031✔
864
            qualifiedName->t.size += 2;
1,031✔
865
        }
866
    return;
1,031✔
867
}
868
/* 8.6.3.29 ObjectIsStorage() */
869
/* This function determines if an object has the attributes associated with a parent. A parent is an
870
   asymmetric or symmetric block cipher key that has its restricted and decrypt attributes SET, and
871
   sign CLEAR. */
872
/* Return Values Meaning */
873
/* TRUE if the object is a storage key */
874
/* FALSE if the object is not a storage key */
875
BOOL
876
ObjectIsStorage(
35✔
877
                TPMI_DH_OBJECT   handle         // IN: object handle
878
                )
879
{
880
    OBJECT           *object = HandleToObject(handle);
35✔
881
    TPMT_PUBLIC      *publicArea = ((object != NULL) ? &object->publicArea : NULL);
35✔
882
    //
883
    return (publicArea != NULL
35✔
884
            && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
885
            && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
886
            && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
35✔
887
            && (object->publicArea.type == ALG_RSA_VALUE
70✔
888
                || object->publicArea.type == ALG_ECC_VALUE));
35✔
889
}
890
/* 8.6.3.30 ObjectCapGetLoaded() */
891
/* This function returns a a list of handles of loaded object, starting from handle. Handle must be
892
   in the range of valid transient object handles, but does not have to be the handle of a loaded
893
   transient object. */
894
/* Return Values Meaning */
895
/* YES if there are more handles available */
896
/* NO all the available handles has been returned */
897
TPMI_YES_NO
898
ObjectCapGetLoaded(
15✔
899
                   TPMI_DH_OBJECT   handle,        // IN: start handle
900
                   UINT32           count,         // IN: count of returned handles
901
                   TPML_HANDLE     *handleList     // OUT: list of handle
902
                   )
903
{
904
    TPMI_YES_NO          more = NO;
15✔
905
    UINT32               i;
15✔
906
    pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
15✔
907
    // Initialize output handle list
908
    handleList->count = 0;
15✔
909
    // The maximum count of handles we may return is MAX_CAP_HANDLES
910
    if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
15✔
911
    // Iterate object slots to get loaded object handles
912
    for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
44✔
913
        {
914
            if(s_objects[i].attributes.occupied == TRUE)
29✔
915
                {
916
                    // A valid transient object can not be the copy of a persistent object
917
                    pAssert(s_objects[i].attributes.evict == CLEAR);
5✔
918
                    if(handleList->count < count)
5✔
919
                        {
920
                            // If we have not filled up the return list, add this object
921
                            // handle to it
922
                            handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
5✔
923
                            handleList->count++;
5✔
924
                        }
925
                    else
926
                        {
927
                            // If the return list is full but we still have loaded object
928
                            // available, report this and stop iterating
929
                            more = YES;
930
                            break;
931
                        }
932
                }
933
        }
934
    return more;
15✔
935
}
936
/* 8.6.3.31 ObjectCapGetTransientAvail() */
937
/* This function returns an estimate of the number of additional transient objects that could be
938
   loaded into the TPM. */
939
UINT32
940
ObjectCapGetTransientAvail(
1✔
941
                           void
942
                           )
943
{
944
    UINT32      i;
1✔
945
    UINT32      num = 0;
1✔
946
    // Iterate object slot to get the number of unoccupied slots
947
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
4✔
948
        {
949
            if(s_objects[i].attributes.occupied == FALSE) num++;
3✔
950
        }
951
    return num;
1✔
952
}
953
/* 8.6.3.32 ObjectGetPublicAttributes() */
954
/* Returns the attributes associated with an object handles. */
955
TPMA_OBJECT
956
ObjectGetPublicAttributes(
1,843✔
957
                          TPM_HANDLE       handle
958
                          )
959
{
960
    return HandleToObject(handle)->publicArea.objectAttributes;
1,843✔
961
}
962
#if 0 /* libtpms added */
963
OBJECT_ATTRIBUTES
964
ObjectGetProperties(
965
                    TPM_HANDLE       handle
966
                    )
967
{
968
    return HandleToObject(handle)->attributes;
969
}
970
#endif /* libtpms added */
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