Home | History | Annotate | Download | only in tpm2
      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 {
     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
     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
     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
    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*
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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