Coverage Report

Created: 2025-09-05 06:38

/src/tpm2/Object.c
Line
Count
Source (jump to first uncovered line)
1
// This file was extracted from the TCG Published
2
// Trusted Platform Module Library
3
// Part 4: Supporting Routines
4
// Family "2.0"
5
// Level 00 Revision 01.16
6
// October 30, 2014
7
8
#define OBJECT_C
9
#include "InternalRoutines.h"
10
#include "Platform.h"
11
//
12
//
13
//            Functions
14
//
15
//             ObjectStartup()
16
//
17
//       This function is called at TPM2_Startup() to initialize the object subsystem.
18
//
19
void
20
ObjectStartup(
21
     void
22
     )
23
253
{
24
253
     UINT32        i;
25
     // object slots initialization
26
1.01k
     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
27
759
     {
28
         //Set the slot to not occupied
29
759
         s_objects[i].occupied = FALSE;
30
759
     }
31
253
     return;
32
253
}
33
//
34
//
35
//             ObjectCleanupEvict()
36
//
37
//       In this implementation, a persistent object is moved from NV into an object slot for processing. It is
38
//       flushed after command execution. This function is called from ExecuteCommand().
39
//
40
void
41
ObjectCleanupEvict(
42
     void
43
     )
44
506
{
45
506
     UINT32        i;
46
     // This has to be iterated because a command may have two handles
47
     // and they may both be persistent.
48
     // This could be made to be more efficient so that a search is not needed.
49
2.02k
     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
50
1.51k
     {
51
         // If an object is a temporary evict object, flush it from slot
52
1.51k
         if(s_objects[i].object.entity.attributes.evict == SET)
53
0
             s_objects[i].occupied = FALSE;
54
1.51k
     }
55
506
   return;
56
506
}
57
//
58
//
59
//          ObjectIsPresent()
60
//
61
//     This function checks to see if a transient handle references a loaded object. This routine should not be
62
//     called if the handle is not a transient handle. The function validates that the handle is in the
63
//     implementation-dependent allowed in range for loaded transient objects.
64
//
65
//     Return Value                      Meaning
66
//
67
//     TRUE                              if the handle references a loaded object
68
//     FALSE                             if the handle is not an object handle, or it does not reference to a
69
//                                       loaded object
70
//
71
BOOL
72
ObjectIsPresent(
73
   TPMI_DH_OBJECT        handle              // IN: handle to be checked
74
   )
75
48
{
76
48
   UINT32              slotIndex;                  // index of object slot
77
48
   pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
78
   // The index in the loaded object array is found by subtracting the first
79
   // object handle number from the input handle number. If the indicated
80
   // slot is occupied, then indicate that there is already is a loaded
81
   // object associated with the handle.
82
48
   slotIndex = handle - TRANSIENT_FIRST;
83
48
   if(slotIndex >= MAX_LOADED_OBJECTS)
84
0
       return FALSE;
85
48
   return s_objects[slotIndex].occupied;
86
48
}
87
//
88
//
89
//          ObjectIsSequence()
90
//
91
//     This function is used to check if the object is a sequence object. This function should not be called if the
92
//     handle does not reference a loaded object.
93
//
94
//     Return Value                      Meaning
95
//
96
//     TRUE                              object is an HMAC, hash, or event sequence object
97
//     FALSE                             object is not an HMAC, hash, or event sequence object
98
//
99
BOOL
100
ObjectIsSequence(
101
   OBJECT              *object               // IN: handle to be checked
102
   )
103
0
{
104
0
   pAssert (object != NULL);
105
0
   if(   object->attributes.hmacSeq == SET
106
0
      || object->attributes.hashSeq == SET
107
0
      || object->attributes.eventSeq == SET)
108
0
       return TRUE;
109
0
   else
110
0
       return FALSE;
111
0
}
112
//
113
//
114
//           ObjectGet()
115
//
116
//      This function is used to find the object structure associated with a handle.
117
//      This function requires that handle references a loaded object.
118
//
119
OBJECT*
120
ObjectGet(
121
    TPMI_DH_OBJECT       handle             // IN: handle of the object
122
    )
123
0
{
124
0
    pAssert(   handle >= TRANSIENT_FIRST
125
0
            && handle - TRANSIENT_FIRST < MAX_LOADED_OBJECTS);
126
0
    pAssert(s_objects[handle - TRANSIENT_FIRST].occupied == TRUE);
127
    // In this implementation, the handle is determined by the slot occupied by the
128
    // object.
129
0
    return &s_objects[handle - TRANSIENT_FIRST].object.entity;
130
0
}
131
//
132
//
133
//           ObjectGetName()
134
//
135
//      This function is used to access the Name of the object. In this implementation, the Name is computed
136
//      when the object is loaded and is saved in the internal representation of the object. This function copies
137
//      the Name data from the object into the buffer at name and returns the number of octets copied.
138
//      This function requires that handle references a loaded object.
139
//
140
UINT16
141
ObjectGetName(
142
    TPMI_DH_OBJECT       handle,            // IN: handle of the object
143
    NAME                *name               // OUT: name of the object
144
    )
145
0
{
146
0
    OBJECT      *object = ObjectGet(handle);
147
0
    if(object->publicArea.nameAlg == TPM_ALG_NULL)
148
0
        return 0;
149
    // Copy the Name data to the output
150
0
    MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME));
151
0
    return object->name.t.size;
152
0
}
153
//
154
//
155
//           ObjectGetNameAlg()
156
//
157
//      This function is used to get the Name algorithm of a object.
158
//      This function requires that handle references a loaded object.
159
//
160
TPMI_ALG_HASH
161
ObjectGetNameAlg(
162
    TPMI_DH_OBJECT       handle             // IN: handle of the object
163
    )
164
0
{
165
0
    OBJECT                   *object = ObjectGet(handle);
166
0
    return object->publicArea.nameAlg;
167
0
}
168
//
169
//
170
//
171
//           ObjectGetQualifiedName()
172
//
173
//      This function returns the Qualified Name of the object. In this implementation, the Qualified Name is
174
//      computed when the object is loaded and is saved in the internal representation of the object. The
175
//      alternative would be to retain the Name of the parent and compute the QN when needed. This would take
176
//      the same amount of space so it is not recommended that the alternate be used.
177
//      This function requires that handle references a loaded object.
178
//
179
void
180
ObjectGetQualifiedName(
181
    TPMI_DH_OBJECT       handle,            // IN: handle of the object
182
    TPM2B_NAME          *qualifiedName      // OUT: qualified name of the object
183
    )
184
0
{
185
0
    OBJECT      *object = ObjectGet(handle);
186
0
    if(object->publicArea.nameAlg == TPM_ALG_NULL)
187
0
        qualifiedName->t.size = 0;
188
0
    else
189
        // Copy the name
190
0
        *qualifiedName = object->qualifiedName;
191
0
    return;
192
0
}
193
//
194
//
195
//           ObjectDataGetHierarchy()
196
//
197
//      This function returns the handle for the hierarchy of an object.
198
//
199
TPMI_RH_HIERARCHY
200
ObjectDataGetHierarchy(
201
    OBJECT              *object             // IN :object
202
    )
203
0
{
204
0
    if(object->attributes.spsHierarchy)
205
0
    {
206
0
        return TPM_RH_OWNER;
207
0
    }
208
0
    else if(object->attributes.epsHierarchy)
209
0
    {
210
0
        return TPM_RH_ENDORSEMENT;
211
0
    }
212
0
    else if(object->attributes.ppsHierarchy)
213
0
    {
214
0
        return TPM_RH_PLATFORM;
215
0
    }
216
0
    else
217
0
    {
218
0
        return TPM_RH_NULL;
219
0
    }
220
0
}
221
//
222
//
223
//          ObjectGetHierarchy()
224
//
225
//      This function returns the handle of the hierarchy to which a handle belongs. This function is similar to
226
//      ObjectDataGetHierarchy() but this routine takes a handle but ObjectDataGetHierarchy() takes an pointer
227
//      to an object.
228
//      This function requires that handle references a loaded object.
229
//
230
TPMI_RH_HIERARCHY
231
ObjectGetHierarchy(
232
    TPMI_DH_OBJECT        handle              // IN :object handle
233
    )
234
0
{
235
0
    OBJECT               *object = ObjectGet(handle);
236
0
    return ObjectDataGetHierarchy(object);
237
0
}
238
//
239
//
240
//           ObjectAllocateSlot()
241
//
242
//      This function is used to allocate a slot in internal object array.
243
//
244
//      Return Value                       Meaning
245
//
246
//      TRUE                               allocate success
247
//      FALSE                              do not have free slot
248
//
249
static BOOL
250
ObjectAllocateSlot(
251
    TPMI_DH_OBJECT       *handle,             // OUT: handle of allocated object
252
    OBJECT               **object             // OUT: points to the allocated object
253
    )
254
53
{
255
53
    UINT32          i;
256
    // find an unoccupied handle slot
257
53
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
258
53
    {
259
53
        if(!s_objects[i].occupied)          // If found a free slot
260
53
        {
261
            // Mark the slot as occupied
262
53
            s_objects[i].occupied = TRUE;
263
53
            break;
264
53
        }
265
53
    }
266
    // If we reach the end of object slot without finding a free one, return
267
    // error.
268
53
    if(i == MAX_LOADED_OBJECTS) return FALSE;
269
53
    *handle = i + TRANSIENT_FIRST;
270
53
    *object = &s_objects[i].object.entity;
271
    // Initialize the container.
272
53
    MemorySet(*object, 0, sizeof(**object));
273
53
    return TRUE;
274
53
}
275
//
276
//
277
//           ObjectLoad()
278
//
279
//      This function loads an object into an internal object structure. If an error is returned, the internal state is
280
//      unchanged.
281
//
282
//
283
//
284
//
285
//      Error Returns                     Meaning
286
//
287
//      TPM_RC_BINDING                    if the public and sensitive parts of the object are not matched
288
//      TPM_RC_KEY                        if the parameters in the public area of the object are not consistent
289
//      TPM_RC_OBJECT_MEMORY              if there is no free slot for an object
290
//      TPM_RC_TYPE                       the public and private parts are not the same type
291
//
292
TPM_RC
293
ObjectLoad(
294
   TPMI_RH_HIERARCHY        hierarchy,               //   IN: hierarchy to which the object belongs
295
   TPMT_PUBLIC             *publicArea,              //   IN: public area
296
   TPMT_SENSITIVE          *sensitive,               //   IN: sensitive area (may be null)
297
   TPM2B_NAME              *name,                    //   IN: object's name (may be null)
298
   TPM_HANDLE               parentHandle,            //   IN: handle of parent
299
   BOOL                     skipChecks,              //   IN: flag to indicate if it is OK to skip
300
                                                     //       consistency checks.
301
   TPMI_DH_OBJECT          *handle                   //   OUT: object handle
302
   )
303
53
{
304
53
   OBJECT                   *object = NULL;
305
53
   OBJECT                   *parent = NULL;
306
53
   TPM_RC                    result = TPM_RC_SUCCESS;
307
53
   TPM2B_NAME                parentQN;         // Parent qualified name
308
   // Try to allocate a slot for new object
309
53
   if(!ObjectAllocateSlot(handle, &object))
310
0
       return TPM_RC_OBJECT_MEMORY;
311
   // Initialize public
312
53
   object->publicArea = *publicArea;
313
53
   if(sensitive != NULL)
314
53
       object->sensitive = *sensitive;
315
   // Are the consistency checks needed
316
53
   if(!skipChecks)
317
49
   {
318
       // Check if key size matches
319
49
       if(!CryptObjectIsPublicConsistent(&object->publicArea))
320
0
       {
321
0
           result = TPM_RC_KEY;
322
0
           goto ErrorExit;
323
0
       }
324
49
       if(sensitive != NULL)
325
49
       {
326
           // Check if public type matches sensitive type
327
49
           result = CryptObjectPublicPrivateMatch(object);
328
49
           if(result != TPM_RC_SUCCESS)
329
48
               goto ErrorExit;
330
49
       }
331
49
   }
332
5
   object->attributes.publicOnly = (sensitive == NULL);
333
   // If 'name' is NULL, then there is nothing left to do for this
334
   // object as it has no qualified name and it is not a member of any
335
   // hierarchy and it is temporary
336
5
   if(name == NULL || name->t.size == 0)
337
0
   {
338
0
       object->qualifiedName.t.size = 0;
339
0
       object->name.t.size = 0;
340
0
       object->attributes.temporary = SET;
341
0
       return TPM_RC_SUCCESS;
342
0
   }
343
   // If parent handle is a permanent handle, it is a primary or temporary
344
   // object
345
5
   if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
346
5
   {
347
       // initialize QN
348
5
       parentQN.t.size = 4;
349
        // for a primary key, parent qualified name is the handle of hierarchy
350
5
        UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name);
351
5
   }
352
0
   else
353
0
   {
354
       // Get hierarchy and qualified name of parent
355
0
       ObjectGetQualifiedName(parentHandle, &parentQN);
356
        // Check for stClear object
357
0
        parent = ObjectGet(parentHandle);
358
0
        if(    publicArea->objectAttributes.stClear == SET
359
0
            || parent->attributes.stClear == SET)
360
0
             object->attributes.stClear = SET;
361
0
   }
362
5
   object->name = *name;
363
   // Compute object qualified name
364
5
   ObjectComputeQualifiedName(&parentQN, publicArea->nameAlg,
365
5
                              name, &object->qualifiedName);
366
   // Any object in TPM_RH_NULL hierarchy is temporary
367
5
   if(hierarchy == TPM_RH_NULL)
368
3
   {
369
3
       object->attributes.temporary = SET;
370
3
   }
371
2
   else if(parentQN.t.size == sizeof(TPM_HANDLE))
372
2
   {
373
       // Otherwise, if the size of parent's qualified name is the size of a
374
       // handle, this object is a primary object
375
2
       object->attributes.primary = SET;
376
2
   }
377
5
   switch(hierarchy)
378
5
   {
379
0
       case TPM_RH_PLATFORM:
380
0
           object->attributes.ppsHierarchy = SET;
381
0
           break;
382
0
       case TPM_RH_OWNER:
383
0
           object->attributes.spsHierarchy = SET;
384
0
           break;
385
2
       case TPM_RH_ENDORSEMENT:
386
2
           object->attributes.epsHierarchy = SET;
387
2
           break;
388
3
       case TPM_RH_NULL:
389
3
           break;
390
0
       default:
391
0
           pAssert(FALSE);
392
0
           break;
393
5
   }
394
5
   return TPM_RC_SUCCESS;
395
48
ErrorExit:
396
48
   ObjectFlush(*handle);
397
48
   return result;
398
5
}
399
//
400
//
401
//
402
//          AllocateSequenceSlot()
403
//
404
//      This function allocates a sequence slot and initializes the parts that are used by the normal objects so
405
//      that a sequence object is not inadvertently used for an operation that is not appropriate for a sequence.
406
//
407
static BOOL
408
AllocateSequenceSlot(
409
   TPM_HANDLE          *newHandle,             // OUT: receives the allocated handle
410
   HASH_OBJECT         **object,               // OUT: receives pointer to allocated object
411
   TPM2B_AUTH          *auth                   // IN: the authValue for the slot
412
   )
413
0
{
414
0
   OBJECT                   *objectHash;                   // the hash as an object
415
0
   if(!ObjectAllocateSlot(newHandle, &objectHash))
416
0
       return FALSE;
417
0
   *object = (HASH_OBJECT *)objectHash;
418
   // Validate that the proper location of the hash state data relative to the
419
   // object state data.
420
0
   pAssert(&((*object)->auth) == &objectHash->publicArea.authPolicy);
421
   // Set the common values that a sequence object shares with an ordinary object
422
   // The type is TPM_ALG_NULL
423
0
   (*object)->type = TPM_ALG_NULL;
424
   // This has no name algorithm and the name is the Empty Buffer
425
0
   (*object)->nameAlg = TPM_ALG_NULL;
426
   // Clear the attributes
427
0
   MemorySet(&((*object)->objectAttributes), 0, sizeof(TPMA_OBJECT));
428
   // A sequence object is considered to be in the NULL hierarchy so it should
429
   // be marked as temporary so that it can't be persisted
430
0
   (*object)->attributes.temporary = SET;
431
   // A sequence object is DA exempt.
432
0
   (*object)->objectAttributes.noDA = SET;
433
0
   if(auth != NULL)
434
0
   {
435
0
       MemoryRemoveTrailingZeros(auth);
436
0
       (*object)->auth = *auth;
437
0
   }
438
0
   else
439
0
       (*object)->auth.t.size = 0;
440
0
   return TRUE;
441
0
}
442
//
443
//
444
//          ObjectCreateHMACSequence()
445
//
446
//      This function creates an internal HMAC sequence object.
447
//
448
//      Error Returns                     Meaning
449
//
450
//      TPM_RC_OBJECT_MEMORY              if there is no free slot for an object
451
//
452
TPM_RC
453
ObjectCreateHMACSequence(
454
   TPMI_ALG_HASH        hashAlg,               // IN: hash algorithm
455
   TPM_HANDLE           handle,                // IN: the handle associated with sequence
456
                                               //     object
457
   TPM2B_AUTH         *auth,                 // IN: authValue
458
   TPMI_DH_OBJECT     *newHandle             // OUT: HMAC sequence object handle
459
   )
460
0
{
461
0
   HASH_OBJECT               *hmacObject;
462
0
   OBJECT                    *keyObject;
463
   // Try to allocate a slot for new object
464
0
   if(!AllocateSequenceSlot(newHandle, &hmacObject, auth))
465
0
       return TPM_RC_OBJECT_MEMORY;
466
   // Set HMAC sequence bit
467
0
   hmacObject->attributes.hmacSeq = SET;
468
   // Get pointer to the HMAC key object
469
0
   keyObject = ObjectGet(handle);
470
0
   CryptStartHMACSequence2B(hashAlg, &keyObject->sensitive.sensitive.bits.b,
471
0
                            &hmacObject->state.hmacState);
472
0
   return TPM_RC_SUCCESS;
473
0
}
474
//
475
//
476
//         ObjectCreateHashSequence()
477
//
478
//      This function creates a hash sequence object.
479
//
480
//      Error Returns                   Meaning
481
//
482
//      TPM_RC_OBJECT_MEMORY            if there is no free slot for an object
483
//
484
TPM_RC
485
ObjectCreateHashSequence(
486
   TPMI_ALG_HASH       hashAlg,              // IN: hash algorithm
487
   TPM2B_AUTH         *auth,                 // IN: authValue
488
   TPMI_DH_OBJECT     *newHandle             // OUT: sequence object handle
489
   )
490
0
{
491
0
   HASH_OBJECT               *hashObject;
492
   // Try to allocate a slot for new object
493
0
   if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
494
0
       return TPM_RC_OBJECT_MEMORY;
495
   // Set hash sequence bit
496
0
   hashObject->attributes.hashSeq = SET;
497
   // Start hash for hash sequence
498
0
   CryptStartHashSequence(hashAlg, &hashObject->state.hashState[0]);
499
0
   return TPM_RC_SUCCESS;
500
0
}
501
//
502
//
503
//         ObjectCreateEventSequence()
504
//
505
//      This function creates an event sequence object.
506
//
507
//      Error Returns                   Meaning
508
//
509
//      TPM_RC_OBJECT_MEMORY            if there is no free slot for an object
510
//
511
TPM_RC
512
ObjectCreateEventSequence(
513
   TPM2B_AUTH          *auth,              // IN: authValue
514
   TPMI_DH_OBJECT      *newHandle          // OUT: sequence object handle
515
   )
516
0
{
517
0
   HASH_OBJECT              *hashObject;
518
0
   UINT32                    count;
519
0
   TPM_ALG_ID                hash;
520
   // Try to allocate a slot for new object
521
0
   if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
522
0
       return TPM_RC_OBJECT_MEMORY;
523
   // Set the event sequence attribute
524
0
   hashObject->attributes.eventSeq = SET;
525
   // Initialize hash states for each implemented PCR algorithms
526
0
   for(count = 0; (hash = CryptGetHashAlgByIndex(count)) != TPM_ALG_NULL; count++)
527
0
   {
528
       // If this is a _TPM_Init or _TPM_HashStart, the sequence object will
529
       // not leave the TPM so it doesn't need the sequence handling
530
0
       if(auth == NULL)
531
0
            CryptStartHash(hash, &hashObject->state.hashState[count]);
532
0
       else
533
0
            CryptStartHashSequence(hash, &hashObject->state.hashState[count]);
534
0
   }
535
0
   return TPM_RC_SUCCESS;
536
0
}
537
//
538
//
539
//          ObjectTerminateEvent()
540
//
541
//      This function is called to close out the event sequence and clean up the hash context states.
542
//
543
void
544
ObjectTerminateEvent(
545
   void
546
   )
547
0
{
548
0
   HASH_OBJECT         *hashObject;
549
0
   int                  count;
550
0
   BYTE                 buffer[MAX_DIGEST_SIZE];
551
0
   hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
552
   // Don't assume that this is a proper sequence object
553
0
   if(hashObject->attributes.eventSeq)
554
0
   {
555
       // If it is, close any open hash contexts. This is done in case
556
       // the crypto implementation has some context values that need to be
557
       // cleaned up (hygiene).
558
       //
559
0
       for(count = 0; CryptGetHashAlgByIndex(count) != TPM_ALG_NULL; count++)
560
0
       {
561
0
           CryptCompleteHash(&hashObject->state.hashState[count], 0, buffer);
562
0
       }
563
       // Flush sequence object
564
0
       ObjectFlush(g_DRTMHandle);
565
0
   }
566
0
   g_DRTMHandle = TPM_RH_UNASSIGNED;
567
0
}
568
//
569
//
570
//
571
//          ObjectContextLoad()
572
//
573
//      This function loads an object from a saved object context.
574
//
575
//      Error Returns                     Meaning
576
//
577
//      TPM_RC_OBJECT_MEMORY              if there is no free slot for an object
578
//
579
TPM_RC
580
ObjectContextLoad(
581
    OBJECT              *object,               // IN: object structure from saved context
582
    TPMI_DH_OBJECT      *handle                // OUT: object handle
583
    )
584
0
{
585
0
    OBJECT         *newObject;
586
    // Try to allocate a slot for new object
587
0
    if(!ObjectAllocateSlot(handle, &newObject))
588
0
        return TPM_RC_OBJECT_MEMORY;
589
    // Copy input object data to internal structure
590
0
    *newObject = *object;
591
0
    return TPM_RC_SUCCESS;
592
0
}
593
//
594
//
595
//          ObjectFlush()
596
//
597
//      This function frees an object slot.
598
//      This function requires that the object is loaded.
599
//
600
void
601
ObjectFlush(
602
    TPMI_DH_OBJECT        handle               // IN: handle to be freed
603
    )
604
48
{
605
48
    UINT32      index = handle - TRANSIENT_FIRST;
606
48
    pAssert(ObjectIsPresent(handle));
607
    // Mark the handle slot as unoccupied
608
48
    s_objects[index].occupied = FALSE;
609
    // With no attributes
610
48
    MemorySet((BYTE*)&(s_objects[index].object.entity.attributes),
611
48
               0, sizeof(OBJECT_ATTRIBUTES));
612
48
    return;
613
48
}
614
//
615
//
616
//          ObjectFlushHierarchy()
617
//
618
//      This function is called to flush all the loaded transient objects associated with a hierarchy when the
619
//      hierarchy is disabled.
620
//
621
void
622
ObjectFlushHierarchy(
623
    TPMI_RH_HIERARCHY          hierarchy             // IN: hierarchy to be flush
624
    )
625
0
{
626
0
    UINT16              i;
627
    // iterate object slots
628
0
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
629
0
    {
630
0
        if(s_objects[i].occupied)           // If found an occupied slot
631
0
        {
632
0
            switch(hierarchy)
633
0
            {
634
0
                case TPM_RH_PLATFORM:
635
0
                    if(s_objects[i].object.entity.attributes.ppsHierarchy == SET)
636
0
                         s_objects[i].occupied = FALSE;
637
0
                    break;
638
0
                case TPM_RH_OWNER:
639
0
                    if(s_objects[i].object.entity.attributes.spsHierarchy == SET)
640
0
                         s_objects[i].occupied = FALSE;
641
0
                    break;
642
0
                case TPM_RH_ENDORSEMENT:
643
0
                    if(s_objects[i].object.entity.attributes.epsHierarchy == SET)
644
0
                         s_objects[i].occupied = FALSE;
645
0
                    break;
646
0
                default:
647
0
                    pAssert(FALSE);
648
0
                    break;
649
0
            }
650
0
        }
651
0
    }
652
0
    return;
653
0
}
654
//
655
//
656
//           ObjectLoadEvict()
657
//
658
//      This function loads a persistent object into a transient object slot.
659
//      This function requires that handle is associated with a persistent object.
660
//
661
//      Error Returns                     Meaning
662
//
663
//      TPM_RC_HANDLE                     the persistent object does not exist or the associated hierarchy is
664
//                                        disabled.
665
//      TPM_RC_OBJECT_MEMORY              no object slot
666
//
667
TPM_RC
668
ObjectLoadEvict(
669
    TPM_HANDLE           *handle,             // IN:OUT: evict object handle. If success, it
670
                                              // will be replace by the loaded object handle
671
    TPM_CC                commandCode         // IN: the command being processed
672
    )
673
0
{
674
0
    TPM_RC               result;
675
0
    TPM_HANDLE           evictHandle = *handle;           // Save the evict handle
676
0
    OBJECT               *object;
677
    // If this is an index that references a persistent object created by
678
    // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE
679
0
    if(*handle >= PLATFORM_PERSISTENT)
680
0
    {
681
        // belongs to platform
682
0
        if(g_phEnable == CLEAR)
683
0
            return TPM_RC_HANDLE;
684
0
    }
685
    // belongs to owner
686
0
    else if(gc.shEnable == CLEAR)
687
0
        return TPM_RC_HANDLE;
688
   // Try to allocate a slot for an object
689
0
   if(!ObjectAllocateSlot(handle, &object))
690
0
       return TPM_RC_OBJECT_MEMORY;
691
   // Copy persistent object to transient object slot. A TPM_RC_HANDLE
692
   // may be returned at this point. This will mark the slot as containing
693
   // a transient object so that it will be flushed at the end of the
694
   // command
695
0
   result = NvGetEvictObject(evictHandle, object);
696
   // Bail out if this failed
697
0
   if(result != TPM_RC_SUCCESS)
698
0
       return result;
699
   // check the object to see if it is in the endorsement hierarchy
700
   // if it is and this is not a TPM2_EvictControl() command, indicate
701
   // that the hierarchy is disabled.
702
   // If the associated hierarchy is disabled, make it look like the
703
   // handle is not defined
704
0
   if(     ObjectDataGetHierarchy(object) == TPM_RH_ENDORSEMENT
705
0
        && gc.ehEnable == CLEAR
706
0
        && commandCode != TPM_CC_EvictControl
707
0
      )
708
0
        return TPM_RC_HANDLE;
709
0
   return result;
710
0
}
711
//
712
//
713
//          ObjectComputeName()
714
//
715
//      This function computes the Name of an object from its public area.
716
//
717
void
718
ObjectComputeName(
719
   TPMT_PUBLIC         *publicArea,       // IN: public area of an object
720
   TPM2B_NAME          *name              // OUT: name of the object
721
   )
722
57
{
723
57
   TPM2B_PUBLIC               marshalBuffer;
724
57
   BYTE                      *buffer;               // auxiliary marshal buffer pointer
725
57
   INT32                      bufferSize;
726
57
   HASH_STATE                 hashState;            // hash state
727
   // if the nameAlg is NULL then there is no name.
728
57
   if(publicArea->nameAlg == TPM_ALG_NULL)
729
0
   {
730
0
       name->t.size = 0;
731
0
       return;
732
0
   }
733
   // Start hash stack
734
57
   name->t.size = CryptStartHash(publicArea->nameAlg, &hashState);
735
   // Marshal the public area into its canonical form
736
57
   buffer = marshalBuffer.b.buffer;
737
57
   bufferSize = sizeof(TPMT_PUBLIC);
738
57
   marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, &bufferSize);
739
   // Adding public area
740
57
   CryptUpdateDigest2B(&hashState, &marshalBuffer.b);
741
   // Complete hash leaving room for the name algorithm
742
57
   CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]);
743
   // set the nameAlg
744
57
   UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name);
745
//
746
57
   name->t.size += 2;
747
57
   return;
748
57
}
749
//
750
//
751
//          ObjectComputeQualifiedName()
752
//
753
//      This function computes the qualified name of an object.
754
//
755
void
756
ObjectComputeQualifiedName(
757
   TPM2B_NAME          *parentQN,             //   IN: parent's qualified name
758
   TPM_ALG_ID           nameAlg,              //   IN: name hash
759
   TPM2B_NAME          *name,                 //   IN: name of the object
760
   TPM2B_NAME          *qualifiedName         //   OUT: qualified name of the object
761
   )
762
5
{
763
5
   HASH_STATE          hashState;         // hash state
764
   //         QN_A = hash_A (QN of parent || NAME_A)
765
   // Start hash
766
5
   qualifiedName->t.size = CryptStartHash(nameAlg, &hashState);
767
   // Add parent's qualified name
768
5
   CryptUpdateDigest2B(&hashState, &parentQN->b);
769
   // Add self name
770
5
   CryptUpdateDigest2B(&hashState, &name->b);
771
   // Complete hash leaving room for the name algorithm
772
5
   CryptCompleteHash(&hashState, qualifiedName->t.size,
773
5
                     &qualifiedName->t.name[2]);
774
5
   UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
775
5
   qualifiedName->t.size += 2;
776
5
   return;
777
5
}
778
//
779
//
780
//          ObjectDataIsStorage()
781
//
782
//      This function determines if a public area has the attributes associated with a storage key. A storage key is
783
//      an asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR.
784
//
785
//      Return Value                      Meaning
786
//
787
//      TRUE                              if the object is a storage key
788
//      FALSE                             if the object is not a storage key
789
//
790
BOOL
791
ObjectDataIsStorage(
792
   TPMT_PUBLIC         *publicArea            // IN: public area of the object
793
   )
794
0
{
795
0
   if(   CryptIsAsymAlgorithm(publicArea->type)                          //   must be asymmetric,
796
0
      && publicArea->objectAttributes.restricted == SET                  //   restricted,
797
0
      && publicArea->objectAttributes.decrypt == SET                     //   decryption key
798
0
      && publicArea->objectAttributes.sign == CLEAR                      //   can not be sign key
799
0
     )
800
0
       return TRUE;
801
0
   else
802
0
       return FALSE;
803
0
}
804
//
805
//          ObjectIsStorage()
806
//
807
//      This function determines if an object has the attributes associated with a storage key. A storage key is an
808
//      asymmetric object that has its restricted and decrypt attributes SET, and sign CLEAR.
809
//
810
//      Return Value                    Meaning
811
//
812
//      TRUE                            if the object is a storage key
813
//      FALSE                           if the object is not a storage key
814
//
815
BOOL
816
ObjectIsStorage(
817
     TPMI_DH_OBJECT     handle              // IN: object handle
818
     )
819
0
{
820
0
     OBJECT           *object = ObjectGet(handle);
821
0
     return ObjectDataIsStorage(&object->publicArea);
822
0
}
823
//
824
//
825
//          ObjectCapGetLoaded()
826
//
827
//      This function returns a a list of handles of loaded object, starting from handle. Handle must be in the
828
//      range of valid transient object handles, but does not have to be the handle of a loaded transient object.
829
//
830
//      Return Value                    Meaning
831
//
832
//      YES                             if there are more handles available
833
//      NO                              all the available handles has been returned
834
//
835
TPMI_YES_NO
836
ObjectCapGetLoaded(
837
     TPMI_DH_OBJECT     handle,             // IN: start handle
838
     UINT32             count,              // IN: count of returned handles
839
     TPML_HANDLE       *handleList          // OUT: list of handle
840
     )
841
0
{
842
0
     TPMI_YES_NO             more = NO;
843
0
     UINT32                  i;
844
0
     pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
845
     // Initialize output handle list
846
0
     handleList->count = 0;
847
     // The maximum count of handles we may return is MAX_CAP_HANDLES
848
0
     if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
849
     // Iterate object slots to get loaded object handles
850
0
     for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
851
0
     {
852
0
         if(s_objects[i].occupied == TRUE)
853
0
         {
854
             // A valid transient object can not be the copy of a persistent object
855
0
             pAssert(s_objects[i].object.entity.attributes.evict == CLEAR);
856
0
              if(handleList->count < count)
857
0
              {
858
                  // If we have not filled up the return list, add this object
859
                  // handle to it
860
0
                  handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
861
0
                  handleList->count++;
862
//
863
0
                 }
864
0
                 else
865
0
                 {
866
                     // If the return list is full but we still have loaded object
867
                     // available, report this and stop iterating
868
0
                     more = YES;
869
0
                     break;
870
0
                 }
871
0
          }
872
0
     }
873
0
     return more;
874
0
}
875
//
876
//
877
//             ObjectCapGetTransientAvail()
878
//
879
//      This function returns an estimate of the number of additional transient objects that could be loaded into
880
//      the TPM.
881
//
882
UINT32
883
ObjectCapGetTransientAvail(
884
     void
885
     )
886
0
{
887
0
     UINT32          i;
888
0
     UINT32          num = 0;
889
     // Iterate object slot to get the number of unoccupied slots
890
0
     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
891
0
     {
892
0
         if(s_objects[i].occupied == FALSE) num++;
893
0
     }
894
0
     return num;
895
0
}