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 //
27 static void
ContextIdSetOldest(void)28 ContextIdSetOldest(
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 //
65 void
SessionStartup(STARTUP_TYPE type)66 SessionStartup(
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 //
127 BOOL
SessionIsLoaded(TPM_HANDLE handle)128 SessionIsLoaded(
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 //
161 BOOL
SessionIsSaved(TPM_HANDLE handle)162 SessionIsSaved(
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 //
191 BOOL
SessionPCRValueIsCurrent(TPMI_SH_POLICY handle)192 SessionPCRValueIsCurrent(
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 //
213 SESSION *
SessionGet(TPM_HANDLE handle)214 SessionGet(
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 //
248 static TPM_RC
ContextIdSessionCreate(TPM_HANDLE * handle,UINT32 sessionIndex)249 ContextIdSessionCreate (
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 //
303 TPM_RC
SessionCreate(TPM_SE sessionType,TPMI_ALG_HASH authHash,TPM2B_NONCE * nonceCaller,TPMT_SYM_DEF * symmetric,TPMI_DH_ENTITY bind,TPM2B_DATA * seed,TPM_HANDLE * sessionHandle)304 SessionCreate(
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 //
426 TPM_RC
SessionContextSave(TPM_HANDLE handle,CONTEXT_COUNTER * contextID)427 SessionContextSave (
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 //
493 TPM_RC
SessionContextLoad(SESSION * session,TPM_HANDLE * handle)494 SessionContextLoad(
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 //
544 void
SessionFlush(TPM_HANDLE handle)545 SessionFlush(
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 //
591 void
SessionComputeBoundEntity(TPMI_DH_ENTITY entityHandle,TPM2B_NAME * bind)592 SessionComputeBoundEntity(
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 //
639 void
SessionInitPolicyData(SESSION * session)640 SessionInitPolicyData(
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 //
658 void
SessionResetPolicyData(SESSION * session)659 SessionResetPolicyData(
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 //
692 TPMI_YES_NO
SessionCapGetLoaded(TPMI_SH_POLICY handle,UINT32 count,TPML_HANDLE * handleList)693 SessionCapGetLoaded(
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 //
752 TPMI_YES_NO
SessionCapGetSaved(TPMI_SH_HMAC handle,UINT32 count,TPML_HANDLE * handleList)753 SessionCapGetSaved(
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 //
800 UINT32
SessionCapGetLoadedNumber(void)801 SessionCapGetLoadedNumber(
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 //
817 UINT32
SessionCapGetLoadedAvail(void)818 SessionCapGetLoadedAvail(
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 //
830 UINT32
SessionCapGetActiveNumber(void)831 SessionCapGetActiveNumber(
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 //
852 UINT32
SessionCapGetActiveAvail(void)853 SessionCapGetActiveAvail(
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