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 SESSION_C
9#include "InternalRoutines.h"
10#include "Platform.h"
11#include "SessionProcess_fp.h"
12//
13//
14//           File Scope Function -- ContextIdSetOldest()
15//
16//     This function is called when the oldest contextID is being loaded or deleted. Once a saved context
17//     becomes the oldest, it stays the oldest until it is deleted.
18//     Finding the oldest is a bit tricky. It is not just the numeric comparison of values but is dependent on the
19//     value of contextCounter.
20//     Assume we have a small contextArray with 8, 4-bit values with values 1 and 2 used to indicate the loaded
21//     context slot number. Also assume that the array contains hex values of (0 0 1 0 3 0 9 F) and that the
22//     contextCounter is an 8-bit counter with a value of 0x37. Since the low nibble is 7, that means that values
23//     above 7 are older than values below it and, in this example, 9 is the oldest value.
24//     Note if we subtract the counter value, from each slot that contains a saved contextID we get (- - - - B - 2 -
25//     8) and the oldest entry is now easy to find.
26//
27static void
28ContextIdSetOldest(
29    void
30    )
31{
32    CONTEXT_SLOT         lowBits;
33    CONTEXT_SLOT         entry;
34    CONTEXT_SLOT         smallest = ((CONTEXT_SLOT) ~0);
35    UINT32 i;
36//
37   // Set oldestSaveContext to a value indicating none assigned
38   s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
39   lowBits = (CONTEXT_SLOT)gr.contextCounter;
40   for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
41   {
42       entry = gr.contextArray[i];
43        // only look at entries that are saved contexts
44        if(entry > MAX_LOADED_SESSIONS)
45        {
46            // Use a less than or equal in case the oldest
47            // is brand new (= lowBits-1) and equal to our initial
48            // value for smallest.
49            if(((CONTEXT_SLOT) (entry - lowBits)) <= smallest)
50            {
51                smallest = (entry - lowBits);
52                s_oldestSavedSession = i;
53            }
54        }
55   }
56   // When we finish, either the s_oldestSavedSession still has its initial
57   // value, or it has the index of the oldest saved context.
58}
59//
60//
61//         Startup Function -- SessionStartup()
62//
63//     This function initializes the session subsystem on TPM2_Startup().
64//
65void
66SessionStartup(
67   STARTUP_TYPE         type
68   )
69{
70   UINT32                    i;
71   // Initialize session slots. At startup, all the in-memory session slots
72   // are cleared and marked as not occupied
73   for(i = 0; i < MAX_LOADED_SESSIONS; i++)
74       s_sessions[i].occupied = FALSE;   // session slot is not occupied
75   // The free session slots the number of maximum allowed loaded sessions
76   s_freeSessionSlots = MAX_LOADED_SESSIONS;
77   // Initialize context ID data. On a ST_SAVE or hibernate sequence, it             will
78   // scan the saved array of session context counts, and clear any entry            that
79   // references a session that was in memory during the state save since            that
80   // memory was not preserved over the ST_SAVE.
81   if(type == SU_RESUME || type == SU_RESTART)
82   {
83       // On ST_SAVE we preserve the contexts that were saved but not the            ones
84       // in memory
85       for (i = 0; i < MAX_ACTIVE_SESSIONS; i++)
86       {
87           // If the array value is unused or references a loaded session            then
88           // that loaded session context is lost and the array entry is
89           // reclaimed.
90           if (gr.contextArray[i] <= MAX_LOADED_SESSIONS)
91               gr.contextArray[i] = 0;
92       }
93       // Find the oldest session in context ID data and set it in
94       // s_oldestSavedSession
95       ContextIdSetOldest();
96//
97   }
98   else
99   {
100       // For STARTUP_CLEAR, clear out the contextArray
101       for (i = 0; i < MAX_ACTIVE_SESSIONS; i++)
102           gr.contextArray[i] = 0;
103         // reset the context counter
104         gr.contextCounter = MAX_LOADED_SESSIONS + 1;
105         // Initialize oldest saved session
106         s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
107   }
108   return;
109}
110//
111//
112//           Access Functions
113//
114//           SessionIsLoaded()
115//
116//      This function test a session handle references a loaded session. The handle must have previously been
117//      checked to make sure that it is a valid handle for an authorization session.
118//
119//      NOTE:           A PWAP authorization does not have a session.
120//
121//
122//      Return Value                       Meaning
123//
124//      TRUE                               if session is loaded
125//      FALSE                              if it is not loaded
126//
127BOOL
128SessionIsLoaded(
129   TPM_HANDLE             handle                // IN: session handle
130   )
131{
132   pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
133           || HandleGetType(handle) == TPM_HT_HMAC_SESSION);
134   handle = handle & HR_HANDLE_MASK;
135   // if out of range of possible active session, or not assigned to a loaded
136   // session return false
137   if(   handle >= MAX_ACTIVE_SESSIONS
138      || gr.contextArray[handle] == 0
139      || gr.contextArray[handle] > MAX_LOADED_SESSIONS
140     )
141       return FALSE;
142   return TRUE;
143}
144//
145//
146//           SessionIsSaved()
147//
148//      This function test a session handle references a saved session. The handle must have previously been
149//      checked to make sure that it is a valid handle for an authorization session.
150//
151//      NOTE:           An password authorization does not have a session.
152//
153//      This function requires that the handle be a valid session handle.
154//
155//
156//      Return Value                     Meaning
157//
158//      TRUE                             if session is saved
159//      FALSE                            if it is not saved
160//
161BOOL
162SessionIsSaved(
163   TPM_HANDLE            handle                // IN: session handle
164   )
165{
166   pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
167           || HandleGetType(handle) == TPM_HT_HMAC_SESSION);
168   handle = handle & HR_HANDLE_MASK;
169   // if out of range of possible active session, or not assigned, or
170   // assigned to a loaded session, return false
171   if(   handle >= MAX_ACTIVE_SESSIONS
172      || gr.contextArray[handle] == 0
173      || gr.contextArray[handle] <= MAX_LOADED_SESSIONS
174     )
175       return FALSE;
176   return TRUE;
177}
178//
179//
180//           SessionPCRValueIsCurrent()
181//
182//      This function is used to check if PCR values have been updated since the last time they were checked in
183//      a policy session.
184//      This function requires the session is loaded.
185//
186//      Return Value                     Meaning
187//
188//      TRUE                             if PCR value is current
189//      FALSE                            if PCR value is not current
190//
191BOOL
192SessionPCRValueIsCurrent(
193   TPMI_SH_POLICY        handle                // IN: session handle
194   )
195{
196   SESSION                   *session;
197   pAssert(SessionIsLoaded(handle));
198   session = SessionGet(handle);
199   if(   session->pcrCounter != 0
200      && session->pcrCounter != gr.pcrCounter
201     )
202       return FALSE;
203   else
204       return TRUE;
205}
206//
207//
208//           SessionGet()
209//
210//      This function returns a pointer to the session object associated with a session handle.
211//      The function requires that the session is loaded.
212//
213SESSION *
214SessionGet(
215    TPM_HANDLE           handle              // IN: session handle
216    )
217{
218    CONTEXT_SLOT        sessionIndex;
219    pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
220            || HandleGetType(handle) == TPM_HT_HMAC_SESSION
221           );
222    pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS);
223    // get the contents of the session array. Because session is loaded, we
224    // should always get a valid sessionIndex
225    sessionIndex = gr.contextArray[handle & HR_HANDLE_MASK] - 1;
226    pAssert(sessionIndex < MAX_LOADED_SESSIONS);
227    return &s_sessions[sessionIndex].session;
228}
229//
230//
231//           Utility Functions
232//
233//             ContextIdSessionCreate()
234//
235//      This function is called when a session is created. It will check to see if the current gap would prevent a
236//      context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find an
237//      open slot in contextArray, set contextArray to the slot.
238//      This routine requires that the caller has determined the session array index for the session.
239//
240//      return type                       TPM_RC
241//
242//      TPM_RC_SUCCESS                    context ID was assigned
243//      TPM_RC_CONTEXT_GAP                can't assign a new contextID until the oldest saved session context is
244//                                        recycled
245//      TPM_RC_SESSION_HANDLE             there is no slot available in the context array for tracking of this
246//                                        session context
247//
248static TPM_RC
249ContextIdSessionCreate (
250    TPM_HANDLE          *handle,             // OUT: receives the assigned handle. This will
251                                             //     be an index that must be adjusted by the
252                                             //     caller according to the type of the
253                                             //     session created
254    UINT32               sessionIndex        // IN: The session context array entry that will
255                                             //     be occupied by the created session
256    )
257{
258    pAssert(sessionIndex < MAX_LOADED_SESSIONS);
259    // check to see if creating the context is safe
260    // Is this going to be an assignment for the last session context
261    // array entry? If so, then there will be no room to recycle the
262    // oldest context if needed. If the gap is not at maximum, then
263    // it will be possible to save a context if it becomes necessary.
264    if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
265       && s_freeSessionSlots == 1)
266    {
267        // See if the gap is at maximum
268         if(      (CONTEXT_SLOT)gr.contextCounter
269               == gr.contextArray[s_oldestSavedSession])
270               // Note: if this is being used on a TPM.combined, this return
271               //       code should be transformed to an appropriate 1.2 error
272               //       code for this case.
273               return TPM_RC_CONTEXT_GAP;
274   }
275   // Find an unoccupied entry in the contextArray
276   for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++)
277   {
278       if(gr.contextArray[*handle] == 0)
279       {
280           // indicate that the session associated with this handle
281           // references a loaded session
282           gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex+1);
283           return TPM_RC_SUCCESS;
284       }
285   }
286   return TPM_RC_SESSION_HANDLES;
287}
288//
289//
290//           SessionCreate()
291//
292//      This function does the detailed work for starting an authorization session. This is done in a support
293//      routine rather than in the action code because the session management may differ in implementations.
294//      This implementation uses a fixed memory allocation to hold sessions and a fixed allocation to hold the
295//      contextID for the saved contexts.
296//
297//      Error Returns                   Meaning
298//
299//      TPM_RC_CONTEXT_GAP              need to recycle sessions
300//      TPM_RC_SESSION_HANDLE           active session space is full
301//      TPM_RC_SESSION_MEMORY           loaded session space is full
302//
303TPM_RC
304SessionCreate(
305   TPM_SE               sessionType,        //   IN: the session type
306   TPMI_ALG_HASH        authHash,           //   IN: the hash algorithm
307   TPM2B_NONCE         *nonceCaller,        //   IN: initial nonceCaller
308   TPMT_SYM_DEF        *symmetric,          //   IN: the symmetric algorithm
309   TPMI_DH_ENTITY       bind,               //   IN: the bind object
310   TPM2B_DATA          *seed,               //   IN: seed data
311   TPM_HANDLE          *sessionHandle       //   OUT: the session handle
312   )
313{
314   TPM_RC                     result = TPM_RC_SUCCESS;
315   CONTEXT_SLOT               slotIndex;
316   SESSION                   *session = NULL;
317   pAssert(   sessionType == TPM_SE_HMAC
318           || sessionType == TPM_SE_POLICY
319           || sessionType == TPM_SE_TRIAL);
320   // If there are no open spots in the session array, then no point in searching
321   if(s_freeSessionSlots == 0)
322       return TPM_RC_SESSION_MEMORY;
323   // Find a space for loading a session
324   for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
325   {
326        // Is this available?
327        if(s_sessions[slotIndex].occupied == FALSE)
328        {
329            session = &s_sessions[slotIndex].session;
330            break;
331        }
332   }
333   // if no spot found, then this is an internal error
334   pAssert (slotIndex < MAX_LOADED_SESSIONS);
335   // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be
336   // returned from ContextIdHandelAssign()
337   result = ContextIdSessionCreate(sessionHandle, slotIndex);
338   if(result != TPM_RC_SUCCESS)
339       return result;
340   //*** Only return from this point on is TPM_RC_SUCCESS
341   // Can now indicate that the session array entry is occupied.
342   s_freeSessionSlots--;
343   s_sessions[slotIndex].occupied = TRUE;
344   // Initialize the session data
345   MemorySet(session, 0, sizeof(SESSION));
346   // Initialize internal session data
347   session->authHashAlg = authHash;
348   // Initialize session type
349   if(sessionType == TPM_SE_HMAC)
350   {
351       *sessionHandle += HMAC_SESSION_FIRST;
352   }
353   else
354   {
355       *sessionHandle += POLICY_SESSION_FIRST;
356        // For TPM_SE_POLICY or TPM_SE_TRIAL
357        session->attributes.isPolicy = SET;
358        if(sessionType == TPM_SE_TRIAL)
359            session->attributes.isTrialPolicy = SET;
360        // Initialize policy session data
361        SessionInitPolicyData(session);
362   }
363   // Create initial session nonce
364   session->nonceTPM.t.size = nonceCaller->t.size;
365   CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer);
366   // Set up session parameter encryption algorithm
367   session->symmetric = *symmetric;
368   // If there is a bind object or a session secret, then need to compute
369   // a sessionKey.
370   if(bind != TPM_RH_NULL || seed->t.size != 0)
371   {
372       // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM,
373       //                      nonceCaller, bits)
374       // The HMAC key for generating the sessionSecret can be the concatenation
375       // of an authorization value and a seed value
376       TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer)));
377       TPM2B_KEY            key;
378        UINT16                   hashSize;     // The size of the hash used by the
379                                               // session crated by this command
380        TPM2B_AUTH    entityAuth;              // The authValue of the entity
381                                                     // associated with HMAC session
382         // Get hash size, which is also the length of sessionKey
383         hashSize = CryptGetHashDigestSize(session->authHashAlg);
384         // Get authValue of associated entity
385         entityAuth.t.size = EntityGetAuthValue(bind, &entityAuth.t.buffer);
386         // Concatenate authValue and seed
387         pAssert(entityAuth.t.size + seed->t.size <= sizeof(key.t.buffer));
388         MemoryCopy2B(&key.b, &entityAuth.b, sizeof(key.t.buffer));
389         MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer));
390         session->sessionKey.t.size = hashSize;
391         // Compute the session key
392         KDFa(session->authHashAlg, &key.b, "ATH", &session->nonceTPM.b,
393              &nonceCaller->b, hashSize * 8, session->sessionKey.t.buffer, NULL);
394   }
395   // Copy the name of the entity that the HMAC session is bound to
396   // Policy session is not bound to an entity
397   if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC)
398   {
399       session->attributes.isBound = SET;
400       SessionComputeBoundEntity(bind, &session->u1.boundEntity);
401   }
402   // If there is a bind object and it is subject to DA, then use of this session
403   // is subject to DA regardless of how it is used.
404   session->attributes.isDaBound =    (bind != TPM_RH_NULL)
405                                   && (IsDAExempted(bind) == FALSE);
406   // If the session is bound, then check to see if it is bound to lockoutAuth
407   session->attributes.isLockoutBound =    (session->attributes.isDaBound == SET)
408                                        && (bind == TPM_RH_LOCKOUT);
409   return TPM_RC_SUCCESS;
410}
411//
412//
413//           SessionContextSave()
414//
415//      This function is called when a session context is to be saved. The contextID of the saved session is
416//      returned. If no contextID can be assigned, then the routine returns TPM_RC_CONTEXT_GAP. If the
417//      function completes normally, the session slot will be freed.
418//      This function requires that handle references a loaded session. Otherwise, it should not be called at the
419//      first place.
420//
421//      Error Returns                      Meaning
422//
423//      TPM_RC_CONTEXT_GAP                 a contextID could not be assigned.
424//      TPM_RC_TOO_MANY_CONTEXTS           the counter maxed out
425//
426TPM_RC
427SessionContextSave (
428   TPM_HANDLE                 handle,           // IN: session handle
429   CONTEXT_COUNTER           *contextID         // OUT: assigned contextID
430   )
431{
432   UINT32                            contextIndex;
433   CONTEXT_SLOT                      slotIndex;
434   pAssert(SessionIsLoaded(handle));
435   // check to see if the gap is already maxed out
436   // Need to have a saved session
437   if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
438         // if the oldest saved session has the same value as the low bits
439         // of the contextCounter, then the GAP is maxed out.
440      && gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter)
441       return TPM_RC_CONTEXT_GAP;
442   // if the caller wants the context counter, set it
443   if(contextID != NULL)
444       *contextID = gr.contextCounter;
445   pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS);
446   contextIndex = handle & HR_HANDLE_MASK;
447   // Extract the session slot number referenced by the contextArray
448   // because we are going to overwrite this with the low order
449   // contextID value.
450   slotIndex = gr.contextArray[contextIndex] - 1;
451   // Set the contextID for the contextArray
452   gr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter;
453   // Increment the counter
454   gr.contextCounter++;
455   // In the unlikely event that the 64-bit context counter rolls over...
456   if(gr.contextCounter == 0)
457   {
458       // back it up
459       gr.contextCounter--;
460       // return an error
461       return TPM_RC_TOO_MANY_CONTEXTS;
462   }
463   // if the low-order bits wrapped, need to advance the value to skip over
464   // the values used to indicate that a session is loaded
465   if(((CONTEXT_SLOT)gr.contextCounter) == 0)
466       gr.contextCounter += MAX_LOADED_SESSIONS + 1;
467   // If no other sessions are saved, this is now the oldest.
468   if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS)
469       s_oldestSavedSession = contextIndex;
470   // Mark the session slot as unoccupied
471   s_sessions[slotIndex].occupied = FALSE;
472   // and indicate that there is an additional open slot
473   s_freeSessionSlots++;
474   return TPM_RC_SUCCESS;
475}
476//
477//
478//           SessionContextLoad()
479//
480//      This function is used to load a session from saved context. The session handle must be for a saved
481//      context.
482//      If the gap is at a maximum, then the only session that can be loaded is the oldest session, otherwise
483//      TPM_RC_CONTEXT_GAP is returned.
484//      This function requires that handle references a valid saved session.
485//
486//
487//
488//      Error Returns                   Meaning
489//
490//      TPM_RC_SESSION_MEMORY           no free session slots
491//      TPM_RC_CONTEXT_GAP              the gap count is maximum and this is not the oldest saved context
492//
493TPM_RC
494SessionContextLoad(
495   SESSION            *session,            // IN: session structure from saved context
496   TPM_HANDLE         *handle              // IN/OUT: session handle
497   )
498{
499   UINT32                    contextIndex;
500   CONTEXT_SLOT              slotIndex;
501   pAssert(   HandleGetType(*handle) == TPM_HT_POLICY_SESSION
502           || HandleGetType(*handle) == TPM_HT_HMAC_SESSION);
503   // Don't bother looking if no openings
504   if(s_freeSessionSlots == 0)
505       return TPM_RC_SESSION_MEMORY;
506   // Find a free session slot to load the session
507   for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
508       if(s_sessions[slotIndex].occupied == FALSE) break;
509   // if no spot found, then this is an internal error
510   pAssert (slotIndex < MAX_LOADED_SESSIONS);
511   contextIndex = *handle & HR_HANDLE_MASK;               // extract the index
512   // If there is only one slot left, and the gap is at maximum, the only session
513   // context that we can safely load is the oldest one.
514   if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
515      && s_freeSessionSlots == 1
516      && (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession]
517      && contextIndex != s_oldestSavedSession
518     )
519       return TPM_RC_CONTEXT_GAP;
520   pAssert(contextIndex < MAX_ACTIVE_SESSIONS);
521   // set the contextArray value to point to the session slot where
522   // the context is loaded
523   gr.contextArray[contextIndex] = slotIndex + 1;
524   // if this was the oldest context, find the new oldest
525   if(contextIndex == s_oldestSavedSession)
526       ContextIdSetOldest();
527   // Copy session data to session slot
528   s_sessions[slotIndex].session = *session;
529   // Set session slot as occupied
530   s_sessions[slotIndex].occupied = TRUE;
531   // Reduce the number of open spots
532   s_freeSessionSlots--;
533   return TPM_RC_SUCCESS;
534}
535//
536//
537//
538//           SessionFlush()
539//
540//      This function is used to flush a session referenced by its handle. If the session associated with handle is
541//      loaded, the session array entry is marked as available.
542//      This function requires that handle be a valid active session.
543//
544void
545SessionFlush(
546    TPM_HANDLE           handle             // IN: loaded or saved session handle
547    )
548{
549    CONTEXT_SLOT              slotIndex;
550    UINT32                    contextIndex;       // Index into contextArray
551    pAssert(      (    HandleGetType(handle) == TPM_HT_POLICY_SESSION
552                    || HandleGetType(handle) == TPM_HT_HMAC_SESSION
553                  )
554               && (SessionIsLoaded(handle) || SessionIsSaved(handle))
555              );
556    // Flush context ID of this session
557    // Convert handle to an index into the contextArray
558    contextIndex = handle & HR_HANDLE_MASK;
559    pAssert(contextIndex < sizeof(gr.contextArray)/sizeof(gr.contextArray[0]));
560    // Get the current contents of the array
561    slotIndex = gr.contextArray[contextIndex];
562    // Mark context array entry as available
563    gr.contextArray[contextIndex] = 0;
564    // Is this a saved session being flushed
565    if(slotIndex > MAX_LOADED_SESSIONS)
566    {
567        // Flushing the oldest session?
568        if(contextIndex == s_oldestSavedSession)
569            // If so, find a new value for oldest.
570            ContextIdSetOldest();
571    }
572    else
573    {
574        // Adjust slot index to point to session array index
575        slotIndex -= 1;
576         // Free session array index
577         s_sessions[slotIndex].occupied = FALSE;
578         s_freeSessionSlots++;
579    }
580    return;
581}
582//
583//
584//           SessionComputeBoundEntity()
585//
586//      This function computes the binding value for a session. The binding value for a reserved handle is the
587//      handle itself. For all the other entities, the authValue at the time of binding is included to prevent
588//      squatting. For those values, the Name and the authValue are concatenated into the bind buffer. If they
589//      will not both fit, the will be overlapped by XORing() bytes. If XOR is required, the bind value will be full.
590//
591void
592SessionComputeBoundEntity(
593    TPMI_DH_ENTITY      entityHandle,     // IN: handle of entity
594    TPM2B_NAME         *bind              // OUT: binding value
595    )
596{
597    TPM2B_AUTH               auth;
598    INT16                    overlap;
599    // Get name
600    bind->t.size = EntityGetName(entityHandle, &bind->t.name);
601//     // The bound value of a reserved handle is the handle itself
602//     if(bind->t.size == sizeof(TPM_HANDLE)) return;
603    // For all the other entities, concatenate the auth value to the name.
604    // Get a local copy of the auth value because some overlapping
605    // may be necessary.
606    auth.t.size = EntityGetAuthValue(entityHandle, &auth.t.buffer);
607    pAssert(auth.t.size <= sizeof(TPMU_HA));
608    // Figure out if there will be any overlap
609    overlap = bind->t.size + auth.t.size - sizeof(bind->t.name);
610    // There is overlap if the combined sizes are greater than will fit
611    if(overlap > 0)
612    {
613        // The overlap area is at the end of the Name
614        BYTE    *result = &bind->t.name[bind->t.size - overlap];
615        int     i;
616         // XOR the auth value into the Name for the overlap area
617         for(i = 0; i < overlap; i++)
618             result[i] ^= auth.t.buffer[i];
619    }
620    else
621    {
622        // There is no overlap
623        overlap = 0;
624    }
625    //copy the remainder of the authData to the end of the name
626    MemoryCopy(&bind->t.name[bind->t.size], &auth.t.buffer[overlap],
627               auth.t.size - overlap, sizeof(bind->t.name) - bind->t.size);
628    // Increase the size of the bind data by the size of the auth - the overlap
629    bind->t.size += auth.t.size-overlap;
630    return;
631}
632//
633//
634//           SessionInitPolicyData()
635//
636//      This function initializes the portions of the session policy data that are not set by the allocation of a
637//      session.
638//
639void
640SessionInitPolicyData(
641    SESSION            *session           // IN: session handle
642    )
643{
644    // Initialize start time
645    session->startTime = go.clock;
646    // Initialize policyDigest. policyDigest is initialized with a string of 0 of
647    // session algorithm digest size. Since the policy already contains all zeros
648    // it is only necessary to set the size
649     session->u2.policyDigest.t.size = CryptGetHashDigestSize(session->authHashAlg);
650     return;
651}
652//
653//
654//           SessionResetPolicyData()
655//
656//      This function is used to reset the policy data without changing the nonce or the start time of the session.
657//
658void
659SessionResetPolicyData(
660     SESSION            *session             // IN: the session to reset
661     )
662{
663     session->commandCode = 0;              // No command
664     // No locality selected
665     MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality));
666     // The cpHash size to zero
667     session->u1.cpHash.b.size = 0;
668     // No timeout
669     session->timeOut = 0;
670     // Reset the pcrCounter
671     session->pcrCounter = 0;
672     // Reset the policy hash
673     MemorySet(&session->u2.policyDigest.t.buffer, 0,
674               session->u2.policyDigest.t.size);
675     // Reset the session attributes
676     MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES));
677     // set the policy attribute
678     session->attributes.isPolicy = SET;
679}
680//
681//
682//           SessionCapGetLoaded()
683//
684//      This function returns a list of handles of loaded session, started from input handle
685//      Handle must be in valid loaded session handle range, but does not have to point to a loaded session.
686//
687//      Return Value                      Meaning
688//
689//      YES                               if there are more handles available
690//      NO                                all the available handles has been returned
691//
692TPMI_YES_NO
693SessionCapGetLoaded(
694     TPMI_SH_POLICY      handle,             // IN: start handle
695     UINT32              count,              // IN: count of returned handle
696     TPML_HANDLE        *handleList          // OUT: list of handle
697     )
698{
699     TPMI_YES_NO        more = NO;
700     UINT32             i;
701     pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION);
702     // Initialize output handle list
703     handleList->count = 0;
704     // The maximum count of handles we may return is MAX_CAP_HANDLES
705     if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
706     // Iterate session context ID slots to get loaded session handles
707     for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++)
708     {
709         // If session is active
710         if(gr.contextArray[i] != 0)
711         {
712             // If session is loaded
713             if (gr.contextArray[i] <= MAX_LOADED_SESSIONS)
714             {
715                 if(handleList->count < count)
716                 {
717                     SESSION         *session;
718                        // If we have not filled up the return list, add this
719                        // session handle to it
720                        // assume that this is going to be an HMAC session
721                        handle = i + HMAC_SESSION_FIRST;
722                        session = SessionGet(handle);
723                        if(session->attributes.isPolicy)
724                            handle = i + POLICY_SESSION_FIRST;
725                        handleList->handle[handleList->count] = handle;
726                        handleList->count++;
727                   }
728                   else
729                   {
730                       // If the return list is full but we still have loaded object
731                       // available, report this and stop iterating
732                       more = YES;
733                       break;
734                   }
735               }
736          }
737     }
738     return more;
739}
740//
741//
742//             SessionCapGetSaved()
743//
744//      This function returns a list of handles for saved session, starting at handle.
745//      Handle must be in a valid handle range, but does not have to point to a saved session
746//
747//      Return Value                      Meaning
748//
749//      YES                               if there are more handles available
750//      NO                                all the available handles has been returned
751//
752TPMI_YES_NO
753SessionCapGetSaved(
754     TPMI_SH_HMAC        handle,             // IN: start handle
755     UINT32              count,              // IN: count of returned handle
756     TPML_HANDLE        *handleList          // OUT: list of handle
757     )
758{
759     TPMI_YES_NO        more = NO;
760     UINT32             i;
761   pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION);
762   // Initialize output handle list
763   handleList->count = 0;
764   // The maximum count of handles we may return is MAX_CAP_HANDLES
765   if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
766   // Iterate session context ID slots to get loaded session handles
767   for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++)
768   {
769       // If session is active
770       if(gr.contextArray[i] != 0)
771       {
772           // If session is saved
773           if (gr.contextArray[i] > MAX_LOADED_SESSIONS)
774           {
775               if(handleList->count < count)
776               {
777                   // If we have not filled up the return list, add this
778                   // session handle to it
779                   handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST;
780                   handleList->count++;
781               }
782               else
783               {
784                   // If the return list is full but we still have loaded object
785                   // available, report this and stop iterating
786                   more = YES;
787                   break;
788               }
789           }
790       }
791   }
792   return more;
793}
794//
795//
796//          SessionCapGetLoadedNumber()
797//
798//      This function return the number of authorization sessions currently loaded into TPM RAM.
799//
800UINT32
801SessionCapGetLoadedNumber(
802   void
803   )
804{
805   return MAX_LOADED_SESSIONS - s_freeSessionSlots;
806}
807//
808//
809//          SessionCapGetLoadedAvail()
810//
811//      This function returns the number of additional authorization sessions, of any type, that could be loaded
812//      into TPM RAM.
813//
814//      NOTE:           In other implementations, this number may just be an estimate. The only requirement for the estimate is, if it is
815//                      one or more, then at least one session must be loadable.
816//
817UINT32
818SessionCapGetLoadedAvail(
819   void
820   )
821{
822     return s_freeSessionSlots;
823}
824//
825//
826//           SessionCapGetActiveNumber()
827//
828//      This function returns the number of active authorization sessions currently being tracked by the TPM.
829//
830UINT32
831SessionCapGetActiveNumber(
832     void
833     )
834{
835     UINT32                  i;
836     UINT32                  num = 0;
837     // Iterate the context array to find the number of non-zero slots
838     for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
839     {
840         if(gr.contextArray[i] != 0) num++;
841     }
842     return num;
843}
844//
845//
846//           SessionCapGetActiveAvail()
847//
848//      This function returns the number of additional authorization sessions, of any type, that could be created.
849//      This not the number of slots for sessions, but the number of additional sessions that the TPM is capable
850//      of tracking.
851//
852UINT32
853SessionCapGetActiveAvail(
854     void
855     )
856{
857     UINT32                  i;
858     UINT32                  num = 0;
859     // Iterate the context array to find the number of zero slots
860     for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
861     {
862         if(gr.contextArray[i] == 0) num++;
863     }
864     return num;
865}
866