• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Introduction
36 // This file contains the functions that manage the object store of the TPM.
37 
38 //** Includes and Data Definitions
39 #define OBJECT_C
40 
41 #include "Tpm.h"
42 
43 //** Functions
44 
45 //*** ObjectFlush()
46 // This function marks an object slot as available.
47 // Since there is no checking of the input parameters, it should be used
48 // judiciously.
49 // Note: This could be converted to a macro.
50 void
ObjectFlush(OBJECT * object)51 ObjectFlush(
52     OBJECT          *object
53     )
54 {
55     object->attributes.occupied = CLEAR;
56 }
57 
58 //*** ObjectSetInUse()
59 // This access function sets the occupied attribute of an object slot.
60 void
ObjectSetInUse(OBJECT * object)61 ObjectSetInUse(
62     OBJECT          *object
63     )
64 {
65     object->attributes.occupied = SET;
66 }
67 
68 //*** ObjectStartup()
69 // This function is called at TPM2_Startup() to initialize the object subsystem.
70 BOOL
ObjectStartup(void)71 ObjectStartup(
72     void
73     )
74 {
75     UINT32      i;
76 //
77     // object slots initialization
78     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
79     {
80         //Set the slot to not occupied
81         ObjectFlush(&s_objects[i]);
82     }
83     return TRUE;
84 }
85 
86 //*** ObjectCleanupEvict()
87 //
88 // In this implementation, a persistent object is moved from NV into an object slot
89 // for processing. It is flushed after command execution. This function is called
90 // from ExecuteCommand().
91 void
ObjectCleanupEvict(void)92 ObjectCleanupEvict(
93     void
94     )
95 {
96     UINT32      i;
97 //
98     // This has to be iterated because a command may have two handles
99     // and they may both be persistent.
100     // This could be made to be more efficient so that a search is not needed.
101     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
102     {
103         // If an object is a temporary evict object, flush it from slot
104         OBJECT      *object = &s_objects[i];
105         if(object->attributes.evict == SET)
106             ObjectFlush(object);
107     }
108     return;
109 }
110 
111 //*** IsObjectPresent()
112 // This function checks to see if a transient handle references a loaded
113 // object.  This routine should not be called if the handle is not a
114 // transient handle. The function validates that the handle is in the
115 // implementation-dependent allowed in range for loaded transient objects.
116 //  Return Type: BOOL
117 //      TRUE(1)         handle references a loaded object
118 //      FALSE(0)        handle is not an object handle, or it does not
119 //                      reference to a loaded object
120 BOOL
IsObjectPresent(TPMI_DH_OBJECT handle)121 IsObjectPresent(
122     TPMI_DH_OBJECT   handle         // IN: handle to be checked
123     )
124 {
125     UINT32          slotIndex = handle - TRANSIENT_FIRST;
126     // Since the handle is just an index into the array that is zero based, any
127     // handle value outsize of the range of:
128     //    TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1)
129     // will now be greater than or equal to MAX_LOADED_OBJECTS
130     if(slotIndex >= MAX_LOADED_OBJECTS)
131         return FALSE;
132     // Indicate if the slot is occupied
133     return (s_objects[slotIndex].attributes.occupied == TRUE);
134 }
135 
136 //*** ObjectIsSequence()
137 // This function is used to check if the object is a sequence object. This function
138 // should not be called if the handle does not reference a loaded object.
139 //  Return Type: BOOL
140 //      TRUE(1)         object is an HMAC, hash, or event sequence object
141 //      FALSE(0)        object is not an HMAC, hash, or event sequence object
142 BOOL
ObjectIsSequence(OBJECT * object)143 ObjectIsSequence(
144     OBJECT          *object         // IN: handle to be checked
145     )
146 {
147     pAssert(object != NULL);
148     return (object->attributes.hmacSeq == SET
149             || object->attributes.hashSeq == SET
150             || object->attributes.eventSeq == SET);
151 }
152 
153 //*** HandleToObject()
154 // This function is used to find the object structure associated with a handle.
155 //
156 // This function requires that 'handle' references a loaded object or a permanent
157 // handle.
158 OBJECT*
HandleToObject(TPMI_DH_OBJECT handle)159 HandleToObject(
160     TPMI_DH_OBJECT   handle         // IN: handle of the object
161     )
162 {
163     UINT32              index;
164 //
165     // Return NULL if the handle references a permanent handle because there is no
166     // associated OBJECT.
167     if(HandleGetType(handle) == TPM_HT_PERMANENT)
168         return NULL;
169     // In this implementation, the handle is determined by the slot occupied by the
170     // object.
171     index = handle - TRANSIENT_FIRST;
172     pAssert(index < MAX_LOADED_OBJECTS);
173     pAssert(s_objects[index].attributes.occupied);
174     return &s_objects[index];
175 }
176 
177 
178 //*** GetQualifiedName()
179 // This function returns the Qualified Name of the object. In this implementation,
180 // the Qualified Name is computed when the object is loaded and is saved in the
181 // internal representation of the object. The alternative would be to retain the
182 // Name of the parent and compute the QN when needed. This would take the same
183 // amount of space so it is not recommended that the alternate be used.
184 //
185 // This function requires that 'handle' references a loaded object.
186 void
GetQualifiedName(TPMI_DH_OBJECT handle,TPM2B_NAME * qualifiedName)187 GetQualifiedName(
188     TPMI_DH_OBJECT   handle,        // IN: handle of the object
189     TPM2B_NAME      *qualifiedName  // OUT: qualified name of the object
190     )
191 {
192     OBJECT      *object;
193 //
194     switch(HandleGetType(handle))
195     {
196         case TPM_HT_PERMANENT:
197             qualifiedName->t.size = sizeof(TPM_HANDLE);
198             UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name);
199             break;
200         case TPM_HT_TRANSIENT:
201             object = HandleToObject(handle);
202             if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL)
203                 qualifiedName->t.size = 0;
204             else
205                 // Copy the name
206                 *qualifiedName = object->qualifiedName;
207             break;
208         default:
209             FAIL(FATAL_ERROR_INTERNAL);
210     }
211     return;
212 }
213 
214 //*** ObjectGetHierarchy()
215 // This function returns the handle for the hierarchy of an object.
216 TPMI_RH_HIERARCHY
ObjectGetHierarchy(OBJECT * object)217 ObjectGetHierarchy(
218     OBJECT          *object         // IN :object
219     )
220 {
221     if(object->attributes.spsHierarchy)
222     {
223         return TPM_RH_OWNER;
224     }
225     else if(object->attributes.epsHierarchy)
226     {
227         return TPM_RH_ENDORSEMENT;
228     }
229     else if(object->attributes.ppsHierarchy)
230     {
231         return TPM_RH_PLATFORM;
232     }
233     else
234     {
235         return TPM_RH_NULL;
236     }
237 }
238 
239 //*** GetHierarchy()
240 // This function returns the handle of the hierarchy to which a handle belongs.
241 // This function is similar to ObjectGetHierarchy() but this routine takes
242 // a handle but ObjectGetHierarchy() takes an pointer to an object.
243 //
244 // This function requires that 'handle' references a loaded object.
245 TPMI_RH_HIERARCHY
GetHierarchy(TPMI_DH_OBJECT handle)246 GetHierarchy(
247     TPMI_DH_OBJECT   handle         // IN :object handle
248     )
249 {
250     OBJECT          *object = HandleToObject(handle);
251 //
252     return ObjectGetHierarchy(object);
253 }
254 
255 //*** FindEmptyObjectSlot()
256 // This function finds an open object slot, if any. It will clear the attributes
257 // but will not set the occupied attribute. This is so that a slot may be used
258 // and discarded if everything does not go as planned.
259 //  Return Type: OBJECT *
260 //      NULL        no open slot found
261 //      != NULL     pointer to available slot
262 OBJECT *
FindEmptyObjectSlot(TPMI_DH_OBJECT * handle)263 FindEmptyObjectSlot(
264     TPMI_DH_OBJECT  *handle         // OUT: (optional)
265     )
266 {
267     UINT32               i;
268     OBJECT              *object;
269 //
270     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
271     {
272         object = &s_objects[i];
273         if(object->attributes.occupied == CLEAR)
274         {
275             if(handle)
276                 *handle = i + TRANSIENT_FIRST;
277             // Initialize the object attributes
278             MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES));
279             return object;
280         }
281     }
282     return NULL;
283 }
284 
285 //*** ObjectAllocateSlot()
286 // This function is used to allocate a slot in internal object array.
287 OBJECT *
ObjectAllocateSlot(TPMI_DH_OBJECT * handle)288 ObjectAllocateSlot(
289     TPMI_DH_OBJECT  *handle        // OUT: handle of allocated object
290     )
291 {
292     OBJECT          *object = FindEmptyObjectSlot(handle);
293 //
294     if(object != NULL)
295     {
296         // if found, mark as occupied
297         ObjectSetInUse(object);
298     }
299     return object;
300 }
301 
302 //*** ObjectSetLoadedAttributes()
303 // This function sets the internal attributes for a loaded object. It is called to
304 // finalize the OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded
305 // object.
306 void
ObjectSetLoadedAttributes(OBJECT * object,TPM_HANDLE parentHandle)307 ObjectSetLoadedAttributes(
308     OBJECT          *object,        // IN: object attributes to finalize
309     TPM_HANDLE       parentHandle   // IN: the parent handle
310     )
311 {
312     OBJECT              *parent = HandleToObject(parentHandle);
313     TPMA_OBJECT          objectAttributes = object->publicArea.objectAttributes;
314 //
315     // Copy the stClear attribute from the public area. This could be overwritten
316     // if the parent has stClear SET
317     object->attributes.stClear =
318         IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear);
319     // If parent handle is a permanent handle, it is a primary (unless it is NULL
320     if(parent == NULL)
321     {
322         object->attributes.primary = SET;
323         switch(parentHandle)
324         {
325             case TPM_RH_ENDORSEMENT:
326                 object->attributes.epsHierarchy = SET;
327                 break;
328             case TPM_RH_OWNER:
329                 object->attributes.spsHierarchy = SET;
330                 break;
331             case TPM_RH_PLATFORM:
332                 object->attributes.ppsHierarchy = SET;
333                 break;
334             default:
335                 // Treat the temporary attribute as a hierarchy
336                 object->attributes.temporary = SET;
337                 object->attributes.primary = CLEAR;
338                 break;
339         }
340     }
341     else
342     {
343         // is this a stClear object
344         object->attributes.stClear =
345             (IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear)
346              || (parent->attributes.stClear == SET));
347         object->attributes.epsHierarchy = parent->attributes.epsHierarchy;
348         object->attributes.spsHierarchy = parent->attributes.spsHierarchy;
349         object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy;
350         // An object is temporary if its parent is temporary or if the object
351         // is external
352         object->attributes.temporary = parent->attributes.temporary
353             || object->attributes.external;
354     }
355     // If this is an external object, set the QN == name but don't SET other
356     // key properties ('parent' or 'derived')
357     if(object->attributes.external)
358         object->qualifiedName = object->name;
359     else
360     {
361         // check attributes for different types of parents
362         if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted)
363            && !object->attributes.publicOnly
364            && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt)
365            && object->publicArea.nameAlg != TPM_ALG_NULL)
366         {
367             // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent.
368             // Otherwise, it is a derivation parent.
369             if(object->publicArea.type == TPM_ALG_KEYEDHASH)
370                 object->attributes.derivation = SET;
371             else
372                 object->attributes.isParent = SET;
373         }
374         ComputeQualifiedName(parentHandle, object->publicArea.nameAlg,
375                              &object->name, &object->qualifiedName);
376     }
377     // Set slot occupied
378     ObjectSetInUse(object);
379     return;
380 }
381 
382 //*** ObjectLoad()
383 // Common function to load an object. A loaded object has its public area validated
384 // (unless its 'nameAlg' is TPM_ALG_NULL). If a sensitive part is loaded, it is
385 // verified to be correct and if both public and sensitive parts are loaded, then
386 // the cryptographic binding between the objects is validated. This function does
387 // not cause the allocated slot to be marked as in use.
388 TPM_RC
ObjectLoad(OBJECT * object,OBJECT * parent,TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM_RC blamePublic,TPM_RC blameSensitive,TPM2B_NAME * name)389 ObjectLoad(
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;
404 //
405 // Do validations of public area object descriptions
406     pAssert(publicArea != NULL);
407 
408     // Is this public only or a no-name object?
409     if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL)
410     {
411         // Need to have schemes checked so that we do the right thing with the
412         // public key.
413         result = SchemeChecks(NULL, publicArea);
414     }
415     else
416     {
417         // For any sensitive area, make sure that the seedSize is no larger than the
418         // digest size of nameAlg
419         if(sensitive->seedValue.t.size > CryptHashGetDigestSize(publicArea->nameAlg))
420             return TPM_RCS_KEY_SIZE + blameSensitive;
421         // Check attributes and schemes for consistency
422         result = PublicAttributesValidation(parent, publicArea);
423     }
424     if(result != TPM_RC_SUCCESS)
425         return RcSafeAddToResult(result, blamePublic);
426 
427 // Sensitive area and binding checks
428 
429     // On load, check nothing if the parent is fixedTPM. For all other cases, validate
430     // the keys.
431     if((parent == NULL)
432        || ((parent != NULL) && !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
433                                              TPMA_OBJECT, fixedTPM)))
434     {
435         // Do the cryptographic key validation
436         result = CryptValidateKeys(publicArea, sensitive, blamePublic,
437                                    blameSensitive);
438         if(result != TPM_RC_SUCCESS)
439             return result;
440     }
441 #if ALG_RSA
442     // If this is an RSA key, then expand the private exponent.
443     // Note: ObjectLoad() is only called by TPM2_Import() if the parent is fixedTPM.
444     // For any key that does not have a fixedTPM parent, the exponent is computed
445     // whenever it is loaded
446     if((publicArea->type == TPM_ALG_RSA) && (sensitive != NULL))
447     {
448         result = CryptRsaLoadPrivateExponent(publicArea, sensitive);
449         if(result != TPM_RC_SUCCESS)
450             return result;
451     }
452 #endif // ALG_RSA
453     // See if there is an object to populate
454     if((result == TPM_RC_SUCCESS) && (object != NULL))
455     {
456         // Initialize public
457         object->publicArea = *publicArea;
458         // Copy sensitive if there is one
459         if(sensitive == NULL)
460             object->attributes.publicOnly = SET;
461         else
462             object->sensitive = *sensitive;
463         // Set the name, if one was provided
464         if(name != NULL)
465             object->name = *name;
466         else
467             object->name.t.size = 0;
468     }
469     return result;
470 }
471 
472 //*** AllocateSequenceSlot()
473 // This function allocates a sequence slot and initializes the parts that
474 // are used by the normal objects so that a sequence object is not inadvertently
475 // used for an operation that is not appropriate for a sequence.
476 //
477 static HASH_OBJECT *
AllocateSequenceSlot(TPM_HANDLE * newHandle,TPM2B_AUTH * auth)478 AllocateSequenceSlot(
479     TPM_HANDLE      *newHandle,     // OUT: receives the allocated handle
480     TPM2B_AUTH      *auth           // IN: the authValue for the slot
481     )
482 {
483     HASH_OBJECT      *object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle);
484 //
485     // Validate that the proper location of the hash state data relative to the
486     // object state data. It would be good if this could have been done at compile
487     // time but it can't so do it in something that can be removed after debug.
488     cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy));
489 
490     if(object != NULL)
491     {
492 
493     // Set the common values that a sequence object shares with an ordinary object
494         // First, clear all attributes
495         MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT));
496 
497         // The type is TPM_ALG_NULL
498         object->type = TPM_ALG_NULL;
499 
500         // This has no name algorithm and the name is the Empty Buffer
501         object->nameAlg = TPM_ALG_NULL;
502 
503         // A sequence object is considered to be in the NULL hierarchy so it should
504         // be marked as temporary so that it can't be persisted
505         object->attributes.temporary = SET;
506 
507         // A sequence object is DA exempt.
508         SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA);
509 
510         // Copy the authorization value
511         if(auth != NULL)
512             object->auth = *auth;
513         else
514             object->auth.t.size = 0;
515     }
516     return object;
517 }
518 
519 
520 #if CC_HMAC_Start || CC_MAC_Start
521 //*** ObjectCreateHMACSequence()
522 // This function creates an internal HMAC sequence object.
523 //  Return Type: TPM_RC
524 //      TPM_RC_OBJECT_MEMORY        if there is no free slot for an object
525 TPM_RC
ObjectCreateHMACSequence(TPMI_ALG_HASH hashAlg,OBJECT * keyObject,TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)526 ObjectCreateHMACSequence(
527     TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
528     OBJECT          *keyObject,     // IN: the object containing the HMAC key
529     TPM2B_AUTH      *auth,          // IN: authValue
530     TPMI_DH_OBJECT  *newHandle      // OUT: HMAC sequence object handle
531     )
532 {
533     HASH_OBJECT         *hmacObject;
534 //
535     // Try to allocate a slot for new object
536     hmacObject = AllocateSequenceSlot(newHandle, auth);
537 
538     if(hmacObject == NULL)
539         return TPM_RC_OBJECT_MEMORY;
540     // Set HMAC sequence bit
541     hmacObject->attributes.hmacSeq = SET;
542 
543 #if !SMAC_IMPLEMENTED
544     if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg,
545                    keyObject->sensitive.sensitive.bits.b.size,
546                    keyObject->sensitive.sensitive.bits.b.buffer) == 0)
547 #else
548     if(CryptMacStart(&hmacObject->state.hmacState,
549                      &keyObject->publicArea.parameters,
550                      hashAlg, &keyObject->sensitive.sensitive.any.b) == 0)
551 #endif // SMAC_IMPLEMENTED
552         return TPM_RC_FAILURE;
553     return TPM_RC_SUCCESS;
554 }
555 #endif
556 
557 //*** ObjectCreateHashSequence()
558 // This function creates a hash sequence object.
559 //  Return Type: TPM_RC
560 //      TPM_RC_OBJECT_MEMORY        if there is no free slot for an object
561 TPM_RC
ObjectCreateHashSequence(TPMI_ALG_HASH hashAlg,TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)562 ObjectCreateHashSequence(
563     TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
564     TPM2B_AUTH      *auth,          // IN: authValue
565     TPMI_DH_OBJECT  *newHandle      // OUT: sequence object handle
566     )
567 {
568     HASH_OBJECT         *hashObject = AllocateSequenceSlot(newHandle, auth);
569 //
570     // See if slot allocated
571     if(hashObject == NULL)
572         return TPM_RC_OBJECT_MEMORY;
573     // Set hash sequence bit
574     hashObject->attributes.hashSeq = SET;
575 
576     // Start hash for hash sequence
577     CryptHashStart(&hashObject->state.hashState[0], hashAlg);
578 
579     return TPM_RC_SUCCESS;
580 }
581 
582 //*** ObjectCreateEventSequence()
583 // This function creates an event sequence object.
584 //  Return Type: TPM_RC
585 //      TPM_RC_OBJECT_MEMORY        if there is no free slot for an object
586 TPM_RC
ObjectCreateEventSequence(TPM2B_AUTH * auth,TPMI_DH_OBJECT * newHandle)587 ObjectCreateEventSequence(
588     TPM2B_AUTH      *auth,          // IN: authValue
589     TPMI_DH_OBJECT  *newHandle      // OUT: sequence object handle
590     )
591 {
592     HASH_OBJECT         *hashObject = AllocateSequenceSlot(newHandle, auth);
593     UINT32               count;
594     TPM_ALG_ID           hash;
595 //
596     // See if slot allocated
597     if(hashObject == NULL)
598         return TPM_RC_OBJECT_MEMORY;
599     // Set the event sequence attribute
600     hashObject->attributes.eventSeq = SET;
601 
602     // Initialize hash states for each implemented PCR algorithms
603     for(count = 0; (hash = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++)
604         CryptHashStart(&hashObject->state.hashState[count], hash);
605     return TPM_RC_SUCCESS;
606 }
607 
608 //*** ObjectTerminateEvent()
609 // This function is called to close out the event sequence and clean up the hash
610 // context states.
611 void
ObjectTerminateEvent(void)612 ObjectTerminateEvent(
613     void
614     )
615 {
616     HASH_OBJECT         *hashObject;
617     int                  count;
618     BYTE                 buffer[MAX_DIGEST_SIZE];
619 //
620     hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
621 
622     // Don't assume that this is a proper sequence object
623     if(hashObject->attributes.eventSeq)
624     {
625         // If it is, close any open hash contexts. This is done in case
626         // the cryptographic implementation has some context values that need to be
627         // cleaned up (hygiene).
628         //
629         for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++)
630         {
631             CryptHashEnd(&hashObject->state.hashState[count], 0, buffer);
632         }
633         // Flush sequence object
634         FlushObject(g_DRTMHandle);
635     }
636     g_DRTMHandle = TPM_RH_UNASSIGNED;
637 }
638 
639 //*** ObjectContextLoad()
640 // This function loads an object from a saved object context.
641 //  Return Type: OBJECT *
642 //      NULL        if there is no free slot for an object
643 //      != NULL     points to the loaded object
644 OBJECT *
ObjectContextLoad(ANY_OBJECT_BUFFER * object,TPMI_DH_OBJECT * handle)645 ObjectContextLoad(
646     ANY_OBJECT_BUFFER   *object,        // IN: pointer to object structure in saved
647                                         //     context
648     TPMI_DH_OBJECT      *handle         // OUT: object handle
649     )
650 {
651     OBJECT      *newObject = ObjectAllocateSlot(handle);
652 //
653     // Try to allocate a slot for new object
654     if(newObject != NULL)
655     {
656         // Copy the first part of the object
657         MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state));
658         // See if this is a sequence object
659         if(ObjectIsSequence(newObject))
660         {
661             // If this is a sequence object, import the data
662             SequenceDataImport((HASH_OBJECT *)newObject,
663                                (HASH_OBJECT_BUFFER *)object);
664         }
665         else
666         {
667             // Copy input object data to internal structure
668             MemoryCopy(newObject, object, sizeof(OBJECT));
669         }
670     }
671     return newObject;
672 }
673 
674 //*** FlushObject()
675 // This function frees an object slot.
676 //
677 // This function requires that the object is loaded.
678 void
FlushObject(TPMI_DH_OBJECT handle)679 FlushObject(
680     TPMI_DH_OBJECT   handle         // IN: handle to be freed
681     )
682 {
683     UINT32      index = handle - TRANSIENT_FIRST;
684 //
685     pAssert(index < MAX_LOADED_OBJECTS);
686     // Clear all the object attributes
687     MemorySet((BYTE*)&(s_objects[index].attributes),
688               0, sizeof(OBJECT_ATTRIBUTES));
689     return;
690 }
691 
692 //*** ObjectFlushHierarchy()
693 // This function is called to flush all the loaded transient objects associated
694 // with a hierarchy when the hierarchy is disabled.
695 void
ObjectFlushHierarchy(TPMI_RH_HIERARCHY hierarchy)696 ObjectFlushHierarchy(
697     TPMI_RH_HIERARCHY    hierarchy      // IN: hierarchy to be flush
698     )
699 {
700     UINT16          i;
701 //
702     // iterate object slots
703     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
704     {
705         if(s_objects[i].attributes.occupied)          // If found an occupied slot
706         {
707             switch(hierarchy)
708             {
709                 case TPM_RH_PLATFORM:
710                     if(s_objects[i].attributes.ppsHierarchy == SET)
711                         s_objects[i].attributes.occupied = FALSE;
712                     break;
713                 case TPM_RH_OWNER:
714                     if(s_objects[i].attributes.spsHierarchy == SET)
715                         s_objects[i].attributes.occupied = FALSE;
716                     break;
717                 case TPM_RH_ENDORSEMENT:
718                     if(s_objects[i].attributes.epsHierarchy == SET)
719                         s_objects[i].attributes.occupied = FALSE;
720                     break;
721                 default:
722                     FAIL(FATAL_ERROR_INTERNAL);
723                     break;
724             }
725         }
726     }
727 
728     return;
729 }
730 
731 //*** ObjectLoadEvict()
732 // This function loads a persistent object into a transient object slot.
733 //
734 // This function requires that 'handle' is associated with a persistent object.
735 //  Return Type: TPM_RC
736 //      TPM_RC_HANDLE               the persistent object does not exist
737 //                                  or the associated hierarchy is disabled.
738 //      TPM_RC_OBJECT_MEMORY        no object slot
739 TPM_RC
ObjectLoadEvict(TPM_HANDLE * handle,COMMAND_INDEX commandIndex)740 ObjectLoadEvict(
741     TPM_HANDLE      *handle,        // IN:OUT: evict object handle.  If success, it
742                                     // will be replace by the loaded object handle
743     COMMAND_INDEX    commandIndex   // IN: the command being processed
744     )
745 {
746     TPM_RC          result;
747     TPM_HANDLE      evictHandle = *handle;   // Save the evict handle
748     OBJECT          *object;
749 //
750     // If this is an index that references a persistent object created by
751     // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE
752     if(*handle >= PLATFORM_PERSISTENT)
753     {
754         // belongs to platform
755         if(g_phEnable == CLEAR)
756             return TPM_RC_HANDLE;
757     }
758     // belongs to owner
759     else if(gc.shEnable == CLEAR)
760         return TPM_RC_HANDLE;
761     // Try to allocate a slot for an object
762     object = ObjectAllocateSlot(handle);
763     if(object == NULL)
764         return TPM_RC_OBJECT_MEMORY;
765     // Copy persistent object to transient object slot.  A TPM_RC_HANDLE
766     // may be returned at this point. This will mark the slot as containing
767     // a transient object so that it will be flushed at the end of the
768     // command
769     result = NvGetEvictObject(evictHandle, object);
770 
771     // Bail out if this failed
772     if(result != TPM_RC_SUCCESS)
773         return result;
774     // check the object to see if it is in the endorsement hierarchy
775     // if it is and this is not a TPM2_EvictControl() command, indicate
776     // that the hierarchy is disabled.
777     // If the associated hierarchy is disabled, make it look like the
778     // handle is not defined
779     if(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT
780        && gc.ehEnable == CLEAR
781        && GetCommandCode(commandIndex) != TPM_CC_EvictControl)
782         return TPM_RC_HANDLE;
783 
784     return result;
785 }
786 
787 //*** ObjectComputeName()
788 // This does the name computation from a public area (can be marshaled or not).
789 TPM2B_NAME *
ObjectComputeName(UINT32 size,BYTE * publicArea,TPM_ALG_ID nameAlg,TPM2B_NAME * name)790 ObjectComputeName(
791     UINT32           size,          // IN: the size of the area to digest
792     BYTE            *publicArea,    // IN: the public area to digest
793     TPM_ALG_ID       nameAlg,       // IN: the hash algorithm to use
794     TPM2B_NAME      *name           // OUT: Computed name
795     )
796 {
797     // Hash the publicArea into the name buffer leaving room for the nameAlg
798     name->t.size = CryptHashBlock(nameAlg, size, publicArea,
799                                   sizeof(name->t.name) - 2,
800                                   &name->t.name[2]);
801     // set the nameAlg
802     UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name);
803     name->t.size += 2;
804     return name;
805 }
806 
807 //*** PublicMarshalAndComputeName()
808 // This function computes the Name of an object from its public area.
809 TPM2B_NAME *
PublicMarshalAndComputeName(TPMT_PUBLIC * publicArea,TPM2B_NAME * name)810 PublicMarshalAndComputeName(
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
818                                         //  marshaled TPMT_PUBLIC
819     BYTE                *buffer = (BYTE *)&marshaled.t.buffer;
820 //
821     // if the nameAlg is NULL then there is no name.
822     if(publicArea->nameAlg == TPM_ALG_NULL)
823         name->t.size = 0;
824     else
825     {
826         // Marshal the public area into its canonical form
827         marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL);
828         // and compute the name
829         ObjectComputeName(marshaled.t.size, marshaled.t.buffer,
830                           publicArea->nameAlg, name);
831     }
832     return name;
833 }
834 
835 //*** ComputeQualifiedName()
836 // This function computes the qualified name of an object.
837 void
ComputeQualifiedName(TPM_HANDLE parentHandle,TPM_ALG_ID nameAlg,TPM2B_NAME * name,TPM2B_NAME * qualifiedName)838 ComputeQualifiedName(
839     TPM_HANDLE       parentHandle,  // IN: parent's handle
840     TPM_ALG_ID       nameAlg,       // IN: name hash
841     TPM2B_NAME      *name,          // IN: name of the object
842     TPM2B_NAME      *qualifiedName  // OUT: qualified name of the object
843     )
844 {
845     HASH_STATE      hashState;   // hash state
846     TPM2B_NAME      parentName;
847 //
848     if(parentHandle == TPM_RH_UNASSIGNED)
849     {
850         MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name));
851         *qualifiedName = *name;
852     }
853     else
854     {
855         GetQualifiedName(parentHandle, &parentName);
856 
857         //      QN_A = hash_A (QN of parent || NAME_A)
858 
859         // Start hash
860         qualifiedName->t.size = CryptHashStart(&hashState, nameAlg);
861 
862         // Add parent's qualified name
863         CryptDigestUpdate2B(&hashState, &parentName.b);
864 
865         // Add self name
866         CryptDigestUpdate2B(&hashState, &name->b);
867 
868         // Complete hash leaving room for the name algorithm
869         CryptHashEnd(&hashState, qualifiedName->t.size,
870                      &qualifiedName->t.name[2]);
871         UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name);
872         qualifiedName->t.size += 2;
873     }
874     return;
875 }
876 
877 //*** ObjectIsStorage()
878 // This function determines if an object has the attributes associated
879 // with a parent. A parent is an asymmetric or symmetric block cipher key
880 // that has its 'restricted' and 'decrypt' attributes SET, and 'sign' CLEAR.
881 //  Return Type: BOOL
882 //      TRUE(1)         object is a storage key
883 //      FALSE(0)        object is not a storage key
884 BOOL
ObjectIsStorage(TPMI_DH_OBJECT handle)885 ObjectIsStorage(
886     TPMI_DH_OBJECT   handle         // IN: object handle
887     )
888 {
889     OBJECT           *object = HandleToObject(handle);
890     TPMT_PUBLIC      *publicArea = ((object != NULL) ? &object->publicArea : NULL);
891 //
892     return (publicArea != NULL
893             && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
894             && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
895             && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
896             && (object->publicArea.type == TPM_ALG_RSA
897                 || object->publicArea.type == TPM_ALG_ECC));
898 }
899 
900 //*** ObjectCapGetLoaded()
901 // This function returns a a list of handles of loaded object, starting from
902 // 'handle'. 'Handle' must be in the range of valid transient object handles,
903 // but does not have to be the handle of a loaded transient object.
904 //  Return Type: TPMI_YES_NO
905 //      YES         if there are more handles available
906 //      NO          all the available handles has been returned
907 TPMI_YES_NO
ObjectCapGetLoaded(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)908 ObjectCapGetLoaded(
909     TPMI_DH_OBJECT   handle,        // IN: start handle
910     UINT32           count,         // IN: count of returned handles
911     TPML_HANDLE     *handleList     // OUT: list of handle
912     )
913 {
914     TPMI_YES_NO          more = NO;
915     UINT32               i;
916 //
917     pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
918 
919     // Initialize output handle list
920     handleList->count = 0;
921 
922     // The maximum count of handles we may return is MAX_CAP_HANDLES
923     if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
924 
925     // Iterate object slots to get loaded object handles
926     for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
927     {
928         if(s_objects[i].attributes.occupied == TRUE)
929         {
930             // A valid transient object can not be the copy of a persistent object
931             pAssert(s_objects[i].attributes.evict == CLEAR);
932 
933             if(handleList->count < count)
934             {
935                 // If we have not filled up the return list, add this object
936                 // handle to it
937                 handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
938                 handleList->count++;
939             }
940             else
941             {
942                 // If the return list is full but we still have loaded object
943                 // available, report this and stop iterating
944                 more = YES;
945                 break;
946             }
947         }
948     }
949 
950     return more;
951 }
952 
953 //*** ObjectCapGetTransientAvail()
954 // This function returns an estimate of the number of additional transient
955 // objects that could be loaded into the TPM.
956 UINT32
ObjectCapGetTransientAvail(void)957 ObjectCapGetTransientAvail(
958     void
959     )
960 {
961     UINT32      i;
962     UINT32      num = 0;
963 //
964     // Iterate object slot to get the number of unoccupied slots
965     for(i = 0; i < MAX_LOADED_OBJECTS; i++)
966     {
967         if(s_objects[i].attributes.occupied == FALSE) num++;
968     }
969 
970     return num;
971 }
972 
973 //*** ObjectGetPublicAttributes()
974 // Returns the attributes associated with an object handles.
975 TPMA_OBJECT
ObjectGetPublicAttributes(TPM_HANDLE handle)976 ObjectGetPublicAttributes(
977     TPM_HANDLE       handle
978     )
979 {
980     return HandleToObject(handle)->publicArea.objectAttributes;
981 }
982 
983 OBJECT_ATTRIBUTES
ObjectGetProperties(TPM_HANDLE handle)984 ObjectGetProperties(
985     TPM_HANDLE       handle
986     )
987 {
988     return HandleToObject(handle)->attributes;
989 }