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
ObjectStartup(void)20 ObjectStartup(
21      void
22      )
23 {
24      UINT32        i;
25      // object slots initialization
26      for(i = 0; i < MAX_LOADED_OBJECTS; i++)
27      {
28          //Set the slot to not occupied
29          s_objects[i].occupied = FALSE;
30      }
31      return;
32 }
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
ObjectCleanupEvict(void)41 ObjectCleanupEvict(
42      void
43      )
44 {
45      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      for(i = 0; i < MAX_LOADED_OBJECTS; i++)
50      {
51          // If an object is a temporary evict object, flush it from slot
52          if(s_objects[i].object.entity.attributes.evict == SET)
53              s_objects[i].occupied = FALSE;
54      }
55    return;
56 }
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
ObjectIsPresent(TPMI_DH_OBJECT handle)72 ObjectIsPresent(
73    TPMI_DH_OBJECT        handle              // IN: handle to be checked
74    )
75 {
76    UINT32              slotIndex;                  // index of object slot
77    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    slotIndex = handle - TRANSIENT_FIRST;
83    if(slotIndex >= MAX_LOADED_OBJECTS)
84        return FALSE;
85    return s_objects[slotIndex].occupied;
86 }
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
ObjectIsSequence(OBJECT * object)100 ObjectIsSequence(
101    OBJECT              *object               // IN: handle to be checked
102    )
103 {
104    pAssert (object != NULL);
105    if(   object->attributes.hmacSeq == SET
106       || object->attributes.hashSeq == SET
107       || object->attributes.eventSeq == SET)
108        return TRUE;
109    else
110        return FALSE;
111 }
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*
ObjectGet(TPMI_DH_OBJECT handle)120 ObjectGet(
121     TPMI_DH_OBJECT       handle             // IN: handle of the object
122     )
123 {
124     pAssert(   handle >= TRANSIENT_FIRST
125             && handle - TRANSIENT_FIRST < MAX_LOADED_OBJECTS);
126     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     return &s_objects[handle - TRANSIENT_FIRST].object.entity;
130 }
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
ObjectGetName(TPMI_DH_OBJECT handle,NAME * name)141 ObjectGetName(
142     TPMI_DH_OBJECT       handle,            // IN: handle of the object
143     NAME                *name               // OUT: name of the object
144     )
145 {
146     OBJECT      *object = ObjectGet(handle);
147     if(object->publicArea.nameAlg == TPM_ALG_NULL)
148         return 0;
149     // Copy the Name data to the output
150     MemoryCopy(name, object->name.t.name, object->name.t.size, sizeof(NAME));
151     return object->name.t.size;
152 }
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
ObjectGetNameAlg(TPMI_DH_OBJECT handle)161 ObjectGetNameAlg(
162     TPMI_DH_OBJECT       handle             // IN: handle of the object
163     )
164 {
165     OBJECT                   *object = ObjectGet(handle);
166     return object->publicArea.nameAlg;
167 }
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
ObjectGetQualifiedName(TPMI_DH_OBJECT handle,TPM2B_NAME * qualifiedName)180 ObjectGetQualifiedName(
181     TPMI_DH_OBJECT       handle,            // IN: handle of the object
182     TPM2B_NAME          *qualifiedName      // OUT: qualified name of the object
183     )
184 {
185     OBJECT      *object = ObjectGet(handle);
186     if(object->publicArea.nameAlg == TPM_ALG_NULL)
187         qualifiedName->t.size = 0;
188     else
189         // Copy the name
190         *qualifiedName = object->qualifiedName;
191     return;
192 }
193 //
194 //
195 //           ObjectDataGetHierarchy()
196 //
197 //      This function returns the handle for the hierarchy of an object.
198 //
199 TPMI_RH_HIERARCHY
ObjectDataGetHierarchy(OBJECT * object)200 ObjectDataGetHierarchy(
201     OBJECT              *object             // IN :object
202     )
203 {
204     if(object->attributes.spsHierarchy)
205     {
206         return TPM_RH_OWNER;
207     }
208     else if(object->attributes.epsHierarchy)
209     {
210         return TPM_RH_ENDORSEMENT;
211     }
212     else if(object->attributes.ppsHierarchy)
213     {
214         return TPM_RH_PLATFORM;
215     }
216     else
217     {
218         return TPM_RH_NULL;
219     }
220 }
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
ObjectGetHierarchy(TPMI_DH_OBJECT handle)231 ObjectGetHierarchy(
232     TPMI_DH_OBJECT        handle              // IN :object handle
233     )
234 {
235     OBJECT               *object = ObjectGet(handle);
236     return ObjectDataGetHierarchy(object);
237 }
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
ObjectAllocateSlot(TPMI_DH_OBJECT * handle,OBJECT ** object)250 ObjectAllocateSlot(
251     TPMI_DH_OBJECT       *handle,             // OUT: handle of allocated object
252     OBJECT               **object             // OUT: points to the allocated object
253     )
254 {
255     UINT32          i;
256     // find an unoccupied handle slot
257     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
258     {
259         if(!s_objects[i].occupied)          // If found a free slot
260         {
261             // Mark the slot as occupied
262             s_objects[i].occupied = TRUE;
263             break;
264         }
265     }
266     // If we reach the end of object slot without finding a free one, return
267     // error.
268     if(i == MAX_LOADED_OBJECTS) return FALSE;
269     *handle = i + TRANSIENT_FIRST;
270     *object = &s_objects[i].object.entity;
271     // Initialize the object attributes
272     MemorySet(&((*object)->attributes), 0, sizeof(OBJECT_ATTRIBUTES));
273     return TRUE;
274 }
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
ObjectLoad(TPMI_RH_HIERARCHY hierarchy,TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM2B_NAME * name,TPM_HANDLE parentHandle,BOOL skipChecks,TPMI_DH_OBJECT * handle)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 {
304    OBJECT                   *object = NULL;
305    OBJECT                   *parent = NULL;
306    TPM_RC                    result = TPM_RC_SUCCESS;
307    TPM2B_NAME                parentQN;         // Parent qualified name
308    // Try to allocate a slot for new object
309    if(!ObjectAllocateSlot(handle, &object))
310        return TPM_RC_OBJECT_MEMORY;
311    // Initialize public
312    object->publicArea = *publicArea;
313    if(sensitive != NULL)
314        object->sensitive = *sensitive;
315    // Are the consistency checks needed
316    if(!skipChecks)
317    {
318        // Check if key size matches
319        if(!CryptObjectIsPublicConsistent(&object->publicArea))
320        {
321            result = TPM_RC_KEY;
322            goto ErrorExit;
323        }
324        if(sensitive != NULL)
325        {
326            // Check if public type matches sensitive type
327            result = CryptObjectPublicPrivateMatch(object);
328            if(result != TPM_RC_SUCCESS)
329                goto ErrorExit;
330        }
331    }
332    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    if(name == NULL || name->t.size == 0)
337    {
338        object->qualifiedName.t.size = 0;
339        object->name.t.size = 0;
340        object->attributes.temporary = SET;
341        return TPM_RC_SUCCESS;
342    }
343    // If parent handle is a permanent handle, it is a primary or temporary
344    // object
345    if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
346    {
347        // initialize QN
348        parentQN.t.size = 4;
349         // for a primary key, parent qualified name is the handle of hierarchy
350         UINT32_TO_BYTE_ARRAY(parentHandle, parentQN.t.name);
351    }
352    else
353    {
354        // Get hierarchy and qualified name of parent
355        ObjectGetQualifiedName(parentHandle, &parentQN);
356         // Check for stClear object
357         parent = ObjectGet(parentHandle);
358         if(    publicArea->objectAttributes.stClear == SET
359             || parent->attributes.stClear == SET)
360              object->attributes.stClear = SET;
361    }
362    object->name = *name;
363    // Compute object qualified name
364    ObjectComputeQualifiedName(&parentQN, publicArea->nameAlg,
365                               name, &object->qualifiedName);
366    // Any object in TPM_RH_NULL hierarchy is temporary
367    if(hierarchy == TPM_RH_NULL)
368    {
369        object->attributes.temporary = SET;
370    }
371    else if(parentQN.t.size == sizeof(TPM_HANDLE))
372    {
373        // Otherwise, if the size of parent's qualified name is the size of a
374        // handle, this object is a primary object
375        object->attributes.primary = SET;
376    }
377    switch(hierarchy)
378    {
379        case TPM_RH_PLATFORM:
380            object->attributes.ppsHierarchy = SET;
381            break;
382        case TPM_RH_OWNER:
383            object->attributes.spsHierarchy = SET;
384            break;
385        case TPM_RH_ENDORSEMENT:
386            object->attributes.epsHierarchy = SET;
387            break;
388        case TPM_RH_NULL:
389            break;
390        default:
391            pAssert(FALSE);
392            break;
393    }
394    return TPM_RC_SUCCESS;
395 ErrorExit:
396    ObjectFlush(*handle);
397    return result;
398 }
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
AllocateSequenceSlot(TPM_HANDLE * newHandle,HASH_OBJECT ** object,TPM2B_AUTH * auth)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 {
414    OBJECT                   *objectHash;                   // the hash as an object
415    if(!ObjectAllocateSlot(newHandle, &objectHash))
416        return FALSE;
417    *object = (HASH_OBJECT *)objectHash;
418    // Validate that the proper location of the hash state data relative to the
419    // object state data.
420    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    (*object)->type = TPM_ALG_NULL;
424    // This has no name algorithm and the name is the Empty Buffer
425    (*object)->nameAlg = TPM_ALG_NULL;
426    // Clear the attributes
427    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    (*object)->attributes.temporary = SET;
431    // A sequence object is DA exempt.
432    (*object)->objectAttributes.noDA = SET;
433    if(auth != NULL)
434    {
435        MemoryRemoveTrailingZeros(auth);
436        (*object)->auth = *auth;
437    }
438    else
439        (*object)->auth.t.size = 0;
440    return TRUE;
441 }
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
ObjectCreateHMACSequence(TPMI_ALG_HASH hashAlg,TPM_HANDLE handle,TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)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 {
461    HASH_OBJECT               *hmacObject;
462    OBJECT                    *keyObject;
463    // Try to allocate a slot for new object
464    if(!AllocateSequenceSlot(newHandle, &hmacObject, auth))
465        return TPM_RC_OBJECT_MEMORY;
466    // Set HMAC sequence bit
467    hmacObject->attributes.hmacSeq = SET;
468    // Get pointer to the HMAC key object
469    keyObject = ObjectGet(handle);
470    CryptStartHMACSequence2B(hashAlg, &keyObject->sensitive.sensitive.bits.b,
471                             &hmacObject->state.hmacState);
472    return TPM_RC_SUCCESS;
473 }
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
ObjectCreateHashSequence(TPMI_ALG_HASH hashAlg,TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)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 {
491    HASH_OBJECT               *hashObject;
492    // Try to allocate a slot for new object
493    if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
494        return TPM_RC_OBJECT_MEMORY;
495    // Set hash sequence bit
496    hashObject->attributes.hashSeq = SET;
497    // Start hash for hash sequence
498    CryptStartHashSequence(hashAlg, &hashObject->state.hashState[0]);
499    return TPM_RC_SUCCESS;
500 }
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
ObjectCreateEventSequence(TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)512 ObjectCreateEventSequence(
513    TPM2B_AUTH          *auth,              // IN: authValue
514    TPMI_DH_OBJECT      *newHandle          // OUT: sequence object handle
515    )
516 {
517    HASH_OBJECT              *hashObject;
518    UINT32                    count;
519    TPM_ALG_ID                hash;
520    // Try to allocate a slot for new object
521    if(!AllocateSequenceSlot(newHandle, &hashObject, auth))
522        return TPM_RC_OBJECT_MEMORY;
523    // Set the event sequence attribute
524    hashObject->attributes.eventSeq = SET;
525    // Initialize hash states for each implemented PCR algorithms
526    for(count = 0; (hash = CryptGetHashAlgByIndex(count)) != TPM_ALG_NULL; count++)
527    {
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        if(auth == NULL)
531             CryptStartHash(hash, &hashObject->state.hashState[count]);
532        else
533             CryptStartHashSequence(hash, &hashObject->state.hashState[count]);
534    }
535    return TPM_RC_SUCCESS;
536 }
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
ObjectTerminateEvent(void)544 ObjectTerminateEvent(
545    void
546    )
547 {
548    HASH_OBJECT         *hashObject;
549    int                  count;
550    BYTE                 buffer[MAX_DIGEST_SIZE];
551    hashObject = (HASH_OBJECT *)ObjectGet(g_DRTMHandle);
552    // Don't assume that this is a proper sequence object
553    if(hashObject->attributes.eventSeq)
554    {
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        for(count = 0; CryptGetHashAlgByIndex(count) != TPM_ALG_NULL; count++)
560        {
561            CryptCompleteHash(&hashObject->state.hashState[count], 0, buffer);
562        }
563        // Flush sequence object
564        ObjectFlush(g_DRTMHandle);
565    }
566    g_DRTMHandle = TPM_RH_UNASSIGNED;
567 }
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
ObjectContextLoad(OBJECT * object,TPMI_DH_OBJECT * handle)580 ObjectContextLoad(
581     OBJECT              *object,               // IN: object structure from saved context
582     TPMI_DH_OBJECT      *handle                // OUT: object handle
583     )
584 {
585     OBJECT         *newObject;
586     // Try to allocate a slot for new object
587     if(!ObjectAllocateSlot(handle, &newObject))
588         return TPM_RC_OBJECT_MEMORY;
589     // Copy input object data to internal structure
590     *newObject = *object;
591     return TPM_RC_SUCCESS;
592 }
593 //
594 //
595 //          ObjectFlush()
596 //
597 //      This function frees an object slot.
598 //      This function requires that the object is loaded.
599 //
600 void
ObjectFlush(TPMI_DH_OBJECT handle)601 ObjectFlush(
602     TPMI_DH_OBJECT        handle               // IN: handle to be freed
603     )
604 {
605     UINT32      index = handle - TRANSIENT_FIRST;
606     pAssert(ObjectIsPresent(handle));
607     // Mark the handle slot as unoccupied
608     s_objects[index].occupied = FALSE;
609     // With no attributes
610     MemorySet((BYTE*)&(s_objects[index].object.entity.attributes),
611                0, sizeof(OBJECT_ATTRIBUTES));
612     return;
613 }
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
ObjectFlushHierarchy(TPMI_RH_HIERARCHY hierarchy)622 ObjectFlushHierarchy(
623     TPMI_RH_HIERARCHY          hierarchy             // IN: hierarchy to be flush
624     )
625 {
626     UINT16              i;
627     // iterate object slots
628     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
629     {
630         if(s_objects[i].occupied)           // If found an occupied slot
631         {
632             switch(hierarchy)
633             {
634                 case TPM_RH_PLATFORM:
635                     if(s_objects[i].object.entity.attributes.ppsHierarchy == SET)
636                          s_objects[i].occupied = FALSE;
637                     break;
638                 case TPM_RH_OWNER:
639                     if(s_objects[i].object.entity.attributes.spsHierarchy == SET)
640                          s_objects[i].occupied = FALSE;
641                     break;
642                 case TPM_RH_ENDORSEMENT:
643                     if(s_objects[i].object.entity.attributes.epsHierarchy == SET)
644                          s_objects[i].occupied = FALSE;
645                     break;
646                 default:
647                     pAssert(FALSE);
648                     break;
649             }
650         }
651     }
652     return;
653 }
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
ObjectLoadEvict(TPM_HANDLE * handle,TPM_CC commandCode)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 {
674     TPM_RC               result;
675     TPM_HANDLE           evictHandle = *handle;           // Save the evict handle
676     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     if(*handle >= PLATFORM_PERSISTENT)
680     {
681         // belongs to platform
682         if(g_phEnable == CLEAR)
683             return TPM_RC_HANDLE;
684     }
685     // belongs to owner
686     else if(gc.shEnable == CLEAR)
687         return TPM_RC_HANDLE;
688    // Try to allocate a slot for an object
689    if(!ObjectAllocateSlot(handle, &object))
690        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    result = NvGetEvictObject(evictHandle, object);
696    // Bail out if this failed
697    if(result != TPM_RC_SUCCESS)
698        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    if(     ObjectDataGetHierarchy(object) == TPM_RH_ENDORSEMENT
705         && gc.ehEnable == CLEAR
706         && commandCode != TPM_CC_EvictControl
707       )
708         return TPM_RC_HANDLE;
709    return result;
710 }
711 //
712 //
713 //          ObjectComputeName()
714 //
715 //      This function computes the Name of an object from its public area.
716 //
717 void
ObjectComputeName(TPMT_PUBLIC * publicArea,TPM2B_NAME * name)718 ObjectComputeName(
719    TPMT_PUBLIC         *publicArea,       // IN: public area of an object
720    TPM2B_NAME          *name              // OUT: name of the object
721    )
722 {
723    TPM2B_PUBLIC               marshalBuffer;
724    BYTE                      *buffer;               // auxiliary marshal buffer pointer
725    INT32                      bufferSize;
726    HASH_STATE                 hashState;            // hash state
727    // if the nameAlg is NULL then there is no name.
728    if(publicArea->nameAlg == TPM_ALG_NULL)
729    {
730        name->t.size = 0;
731        return;
732    }
733    // Start hash stack
734    name->t.size = CryptStartHash(publicArea->nameAlg, &hashState);
735    // Marshal the public area into its canonical form
736    buffer = marshalBuffer.b.buffer;
737    bufferSize = sizeof(TPMT_PUBLIC);
738    marshalBuffer.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, &bufferSize);
739    // Adding public area
740    CryptUpdateDigest2B(&hashState, &marshalBuffer.b);
741    // Complete hash leaving room for the name algorithm
742    CryptCompleteHash(&hashState, name->t.size, &name->t.name[2]);
743    // set the nameAlg
744    UINT16_TO_BYTE_ARRAY(publicArea->nameAlg, name->t.name);
745 //
746    name->t.size += 2;
747    return;
748 }
749 //
750 //
751 //          ObjectComputeQualifiedName()
752 //
753 //      This function computes the qualified name of an object.
754 //
755 void
ObjectComputeQualifiedName(TPM2B_NAME * parentQN,TPM_ALG_ID nameAlg,TPM2B_NAME * name,TPM2B_NAME * qualifiedName)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 {
763    HASH_STATE          hashState;         // hash state
764    //         QN_A = hash_A (QN of parent || NAME_A)
765    // Start hash
766    qualifiedName->t.size = CryptStartHash(nameAlg, &hashState);
767    // Add parent's qualified name
768    CryptUpdateDigest2B(&hashState, &parentQN->b);
769    // Add self name
770    CryptUpdateDigest2B(&hashState, &name->b);
771    // Complete hash leaving room for the name algorithm
772    CryptCompleteHash(&hashState, qualifiedName->t.size,
773                      &qualifiedName->t.name[2]);
774    UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
775    qualifiedName->t.size += 2;
776    return;
777 }
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
ObjectDataIsStorage(TPMT_PUBLIC * publicArea)791 ObjectDataIsStorage(
792    TPMT_PUBLIC         *publicArea            // IN: public area of the object
793    )
794 {
795    if(   CryptIsAsymAlgorithm(publicArea->type)                          //   must be asymmetric,
796       && publicArea->objectAttributes.restricted == SET                  //   restricted,
797       && publicArea->objectAttributes.decrypt == SET                     //   decryption key
798       && publicArea->objectAttributes.sign == CLEAR                      //   can not be sign key
799      )
800        return TRUE;
801    else
802        return FALSE;
803 }
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
ObjectIsStorage(TPMI_DH_OBJECT handle)816 ObjectIsStorage(
817      TPMI_DH_OBJECT     handle              // IN: object handle
818      )
819 {
820      OBJECT           *object = ObjectGet(handle);
821      return ObjectDataIsStorage(&object->publicArea);
822 }
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
ObjectCapGetLoaded(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)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 {
842      TPMI_YES_NO             more = NO;
843      UINT32                  i;
844      pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
845      // Initialize output handle list
846      handleList->count = 0;
847      // The maximum count of handles we may return is MAX_CAP_HANDLES
848      if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
849      // Iterate object slots to get loaded object handles
850      for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
851      {
852          if(s_objects[i].occupied == TRUE)
853          {
854              // A valid transient object can not be the copy of a persistent object
855              pAssert(s_objects[i].object.entity.attributes.evict == CLEAR);
856               if(handleList->count < count)
857               {
858                   // If we have not filled up the return list, add this object
859                   // handle to it
860                   handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
861                   handleList->count++;
862 //
863                  }
864                  else
865                  {
866                      // If the return list is full but we still have loaded object
867                      // available, report this and stop iterating
868                      more = YES;
869                      break;
870                  }
871           }
872      }
873      return more;
874 }
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
ObjectCapGetTransientAvail(void)883 ObjectCapGetTransientAvail(
884      void
885      )
886 {
887      UINT32          i;
888      UINT32          num = 0;
889      // Iterate object slot to get the number of unoccupied slots
890      for(i = 0; i < MAX_LOADED_OBJECTS; i++)
891      {
892          if(s_objects[i].occupied == FALSE) num++;
893      }
894      return num;
895 }
896