Coverage Report

Created: 2023-06-07 06:46

/src/tpm2/Session.c
Line
Count
Source (jump to first uncovered line)
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
28
ContextIdSetOldest(
29
    void
30
    )
31
0
{
32
0
    CONTEXT_SLOT         lowBits;
33
0
    CONTEXT_SLOT         entry;
34
0
    CONTEXT_SLOT         smallest = ((CONTEXT_SLOT) ~0);
35
0
    UINT32 i;
36
//
37
   // Set oldestSaveContext to a value indicating none assigned
38
0
   s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
39
0
   lowBits = (CONTEXT_SLOT)gr.contextCounter;
40
0
   for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
41
0
   {
42
0
       entry = gr.contextArray[i];
43
        // only look at entries that are saved contexts
44
0
        if(entry > MAX_LOADED_SESSIONS)
45
0
        {
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
0
            if(((CONTEXT_SLOT) (entry - lowBits)) <= smallest)
50
0
            {
51
0
                smallest = (entry - lowBits);
52
0
                s_oldestSavedSession = i;
53
0
            }
54
0
        }
55
0
   }
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
0
}
59
//
60
//
61
//         Startup Function -- SessionStartup()
62
//
63
//     This function initializes the session subsystem on TPM2_Startup().
64
//
65
void
66
SessionStartup(
67
   STARTUP_TYPE         type
68
   )
69
5.63k
{
70
5.63k
   UINT32                    i;
71
   // Initialize session slots. At startup, all the in-memory session slots
72
   // are cleared and marked as not occupied
73
22.5k
   for(i = 0; i < MAX_LOADED_SESSIONS; i++)
74
16.9k
       s_sessions[i].occupied = FALSE;   // session slot is not occupied
75
   // The free session slots the number of maximum allowed loaded sessions
76
5.63k
   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
5.63k
   if(type == SU_RESUME || type == SU_RESTART)
82
0
   {
83
       // On ST_SAVE we preserve the contexts that were saved but not the            ones
84
       // in memory
85
0
       for (i = 0; i < MAX_ACTIVE_SESSIONS; i++)
86
0
       {
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
0
           if (gr.contextArray[i] <= MAX_LOADED_SESSIONS)
91
0
               gr.contextArray[i] = 0;
92
0
       }
93
       // Find the oldest session in context ID data and set it in
94
       // s_oldestSavedSession
95
0
       ContextIdSetOldest();
96
//
97
0
   }
98
5.63k
   else
99
5.63k
   {
100
       // For STARTUP_CLEAR, clear out the contextArray
101
366k
       for (i = 0; i < MAX_ACTIVE_SESSIONS; i++)
102
360k
           gr.contextArray[i] = 0;
103
         // reset the context counter
104
5.63k
         gr.contextCounter = MAX_LOADED_SESSIONS + 1;
105
         // Initialize oldest saved session
106
5.63k
         s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1;
107
5.63k
   }
108
5.63k
   return;
109
5.63k
}
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
128
SessionIsLoaded(
129
   TPM_HANDLE             handle                // IN: session handle
130
   )
131
32
{
132
32
   pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
133
32
           || HandleGetType(handle) == TPM_HT_HMAC_SESSION);
134
32
   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
32
   if(   handle >= MAX_ACTIVE_SESSIONS
138
32
      || gr.contextArray[handle] == 0
139
32
      || gr.contextArray[handle] > MAX_LOADED_SESSIONS
140
32
     )
141
32
       return FALSE;
142
0
   return TRUE;
143
32
}
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
162
SessionIsSaved(
163
   TPM_HANDLE            handle                // IN: session handle
164
   )
165
11
{
166
11
   pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
167
11
           || HandleGetType(handle) == TPM_HT_HMAC_SESSION);
168
11
   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
11
   if(   handle >= MAX_ACTIVE_SESSIONS
172
11
      || gr.contextArray[handle] == 0
173
11
      || gr.contextArray[handle] <= MAX_LOADED_SESSIONS
174
11
     )
175
11
       return FALSE;
176
0
   return TRUE;
177
11
}
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
192
SessionPCRValueIsCurrent(
193
   TPMI_SH_POLICY        handle                // IN: session handle
194
   )
195
0
{
196
0
   SESSION                   *session;
197
0
   pAssert(SessionIsLoaded(handle));
198
0
   session = SessionGet(handle);
199
0
   if(   session->pcrCounter != 0
200
0
      && session->pcrCounter != gr.pcrCounter
201
0
     )
202
0
       return FALSE;
203
0
   else
204
0
       return TRUE;
205
0
}
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 *
214
SessionGet(
215
    TPM_HANDLE           handle              // IN: session handle
216
    )
217
15
{
218
15
    CONTEXT_SLOT        sessionIndex;
219
15
    pAssert(   HandleGetType(handle) == TPM_HT_POLICY_SESSION
220
15
            || HandleGetType(handle) == TPM_HT_HMAC_SESSION
221
15
           );
222
15
    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
15
    sessionIndex = gr.contextArray[handle & HR_HANDLE_MASK] - 1;
226
15
    pAssert(sessionIndex < MAX_LOADED_SESSIONS);
227
15
    return &s_sessions[sessionIndex].session;
228
15
}
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
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
15
{
258
15
    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
15
    if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
265
15
       && s_freeSessionSlots == 1)
266
0
    {
267
        // See if the gap is at maximum
268
0
         if(      (CONTEXT_SLOT)gr.contextCounter
269
0
               == 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
0
               return TPM_RC_CONTEXT_GAP;
274
0
   }
275
   // Find an unoccupied entry in the contextArray
276
15
   for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++)
277
15
   {
278
15
       if(gr.contextArray[*handle] == 0)
279
15
       {
280
           // indicate that the session associated with this handle
281
           // references a loaded session
282
15
           gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex+1);
283
15
           return TPM_RC_SUCCESS;
284
15
       }
285
15
   }
286
0
   return TPM_RC_SESSION_HANDLES;
287
15
}
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
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
15
{
314
15
   TPM_RC                     result = TPM_RC_SUCCESS;
315
15
   CONTEXT_SLOT               slotIndex;
316
15
   SESSION                   *session = NULL;
317
15
   pAssert(   sessionType == TPM_SE_HMAC
318
15
           || sessionType == TPM_SE_POLICY
319
15
           || sessionType == TPM_SE_TRIAL);
320
   // If there are no open spots in the session array, then no point in searching
321
15
   if(s_freeSessionSlots == 0)
322
0
       return TPM_RC_SESSION_MEMORY;
323
   // Find a space for loading a session
324
15
   for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
325
15
   {
326
        // Is this available?
327
15
        if(s_sessions[slotIndex].occupied == FALSE)
328
15
        {
329
15
            session = &s_sessions[slotIndex].session;
330
15
            break;
331
15
        }
332
15
   }
333
   // if no spot found, then this is an internal error
334
15
   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
15
   result = ContextIdSessionCreate(sessionHandle, slotIndex);
338
15
   if(result != TPM_RC_SUCCESS)
339
0
       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
15
   s_freeSessionSlots--;
343
15
   s_sessions[slotIndex].occupied = TRUE;
344
   // Initialize the session data
345
15
   MemorySet(session, 0, sizeof(SESSION));
346
   // Initialize internal session data
347
15
   session->authHashAlg = authHash;
348
   // Initialize session type
349
15
   if(sessionType == TPM_SE_HMAC)
350
10
   {
351
10
       *sessionHandle += HMAC_SESSION_FIRST;
352
10
   }
353
5
   else
354
5
   {
355
5
       *sessionHandle += POLICY_SESSION_FIRST;
356
        // For TPM_SE_POLICY or TPM_SE_TRIAL
357
5
        session->attributes.isPolicy = SET;
358
5
        if(sessionType == TPM_SE_TRIAL)
359
2
            session->attributes.isTrialPolicy = SET;
360
        // Initialize policy session data
361
5
        SessionInitPolicyData(session);
362
5
   }
363
   // Create initial session nonce
364
15
   session->nonceTPM.t.size = nonceCaller->t.size;
365
15
   CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer);
366
   // Set up session parameter encryption algorithm
367
15
   session->symmetric = *symmetric;
368
   // If there is a bind object or a session secret, then need to compute
369
   // a sessionKey.
370
15
   if(bind != TPM_RH_NULL || seed->t.size != 0)
371
14
   {
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
14
       TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer)));
377
14
       TPM2B_KEY            key;
378
14
        UINT16                   hashSize;     // The size of the hash used by the
379
                                               // session crated by this command
380
14
        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
14
         hashSize = CryptGetHashDigestSize(session->authHashAlg);
384
         // Get authValue of associated entity
385
14
         entityAuth.t.size = EntityGetAuthValue(bind, &entityAuth.t.buffer);
386
         // Concatenate authValue and seed
387
14
         pAssert(entityAuth.t.size + seed->t.size <= sizeof(key.t.buffer));
388
14
         MemoryCopy2B(&key.b, &entityAuth.b, sizeof(key.t.buffer));
389
14
         MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer));
390
14
         session->sessionKey.t.size = hashSize;
391
         // Compute the session key
392
14
         KDFa(session->authHashAlg, &key.b, "ATH", &session->nonceTPM.b,
393
14
              &nonceCaller->b, hashSize * 8, session->sessionKey.t.buffer, NULL);
394
14
   }
395
   // Copy the name of the entity that the HMAC session is bound to
396
   // Policy session is not bound to an entity
397
15
   if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC)
398
9
   {
399
9
       session->attributes.isBound = SET;
400
9
       SessionComputeBoundEntity(bind, &session->u1.boundEntity);
401
9
   }
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
15
   session->attributes.isDaBound =    (bind != TPM_RH_NULL)
405
15
                                   && (IsDAExempted(bind) == FALSE);
406
   // If the session is bound, then check to see if it is bound to lockoutAuth
407
15
   session->attributes.isLockoutBound =    (session->attributes.isDaBound == SET)
408
15
                                        && (bind == TPM_RH_LOCKOUT);
409
15
   return TPM_RC_SUCCESS;
410
15
}
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
427
SessionContextSave (
428
   TPM_HANDLE                 handle,           // IN: session handle
429
   CONTEXT_COUNTER           *contextID         // OUT: assigned contextID
430
   )
431
0
{
432
0
   UINT32                            contextIndex;
433
0
   CONTEXT_SLOT                      slotIndex;
434
0
   pAssert(SessionIsLoaded(handle));
435
   // check to see if the gap is already maxed out
436
   // Need to have a saved session
437
0
   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
0
      && gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter)
441
0
       return TPM_RC_CONTEXT_GAP;
442
   // if the caller wants the context counter, set it
443
0
   if(contextID != NULL)
444
0
       *contextID = gr.contextCounter;
445
0
   pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS);
446
0
   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
0
   slotIndex = gr.contextArray[contextIndex] - 1;
451
   // Set the contextID for the contextArray
452
0
   gr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter;
453
   // Increment the counter
454
0
   gr.contextCounter++;
455
   // In the unlikely event that the 64-bit context counter rolls over...
456
0
   if(gr.contextCounter == 0)
457
0
   {
458
       // back it up
459
0
       gr.contextCounter--;
460
       // return an error
461
0
       return TPM_RC_TOO_MANY_CONTEXTS;
462
0
   }
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
0
   if(((CONTEXT_SLOT)gr.contextCounter) == 0)
466
0
       gr.contextCounter += MAX_LOADED_SESSIONS + 1;
467
   // If no other sessions are saved, this is now the oldest.
468
0
   if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS)
469
0
       s_oldestSavedSession = contextIndex;
470
   // Mark the session slot as unoccupied
471
0
   s_sessions[slotIndex].occupied = FALSE;
472
   // and indicate that there is an additional open slot
473
0
   s_freeSessionSlots++;
474
0
   return TPM_RC_SUCCESS;
475
0
}
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
494
SessionContextLoad(
495
   SESSION            *session,            // IN: session structure from saved context
496
   TPM_HANDLE         *handle              // IN/OUT: session handle
497
   )
498
0
{
499
0
   UINT32                    contextIndex;
500
0
   CONTEXT_SLOT              slotIndex;
501
0
   pAssert(   HandleGetType(*handle) == TPM_HT_POLICY_SESSION
502
0
           || HandleGetType(*handle) == TPM_HT_HMAC_SESSION);
503
   // Don't bother looking if no openings
504
0
   if(s_freeSessionSlots == 0)
505
0
       return TPM_RC_SESSION_MEMORY;
506
   // Find a free session slot to load the session
507
0
   for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
508
0
       if(s_sessions[slotIndex].occupied == FALSE) break;
509
   // if no spot found, then this is an internal error
510
0
   pAssert (slotIndex < MAX_LOADED_SESSIONS);
511
0
   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
0
   if(   s_oldestSavedSession < MAX_ACTIVE_SESSIONS
515
0
      && s_freeSessionSlots == 1
516
0
      && (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession]
517
0
      && contextIndex != s_oldestSavedSession
518
0
     )
519
0
       return TPM_RC_CONTEXT_GAP;
520
0
   pAssert(contextIndex < MAX_ACTIVE_SESSIONS);
521
   // set the contextArray value to point to the session slot where
522
   // the context is loaded
523
0
   gr.contextArray[contextIndex] = slotIndex + 1;
524
   // if this was the oldest context, find the new oldest
525
0
   if(contextIndex == s_oldestSavedSession)
526
0
       ContextIdSetOldest();
527
   // Copy session data to session slot
528
0
   s_sessions[slotIndex].session = *session;
529
   // Set session slot as occupied
530
0
   s_sessions[slotIndex].occupied = TRUE;
531
   // Reduce the number of open spots
532
0
   s_freeSessionSlots--;
533
0
   return TPM_RC_SUCCESS;
534
0
}
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
545
SessionFlush(
546
    TPM_HANDLE           handle             // IN: loaded or saved session handle
547
    )
548
0
{
549
0
    CONTEXT_SLOT              slotIndex;
550
0
    UINT32                    contextIndex;       // Index into contextArray
551
0
    pAssert(      (    HandleGetType(handle) == TPM_HT_POLICY_SESSION
552
0
                    || HandleGetType(handle) == TPM_HT_HMAC_SESSION
553
0
                  )
554
0
               && (SessionIsLoaded(handle) || SessionIsSaved(handle))
555
0
              );
556
    // Flush context ID of this session
557
    // Convert handle to an index into the contextArray
558
0
    contextIndex = handle & HR_HANDLE_MASK;
559
0
    pAssert(contextIndex < sizeof(gr.contextArray)/sizeof(gr.contextArray[0]));
560
    // Get the current contents of the array
561
0
    slotIndex = gr.contextArray[contextIndex];
562
    // Mark context array entry as available
563
0
    gr.contextArray[contextIndex] = 0;
564
    // Is this a saved session being flushed
565
0
    if(slotIndex > MAX_LOADED_SESSIONS)
566
0
    {
567
        // Flushing the oldest session?
568
0
        if(contextIndex == s_oldestSavedSession)
569
            // If so, find a new value for oldest.
570
0
            ContextIdSetOldest();
571
0
    }
572
0
    else
573
0
    {
574
        // Adjust slot index to point to session array index
575
0
        slotIndex -= 1;
576
         // Free session array index
577
0
         s_sessions[slotIndex].occupied = FALSE;
578
0
         s_freeSessionSlots++;
579
0
    }
580
0
    return;
581
0
}
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
592
SessionComputeBoundEntity(
593
    TPMI_DH_ENTITY      entityHandle,     // IN: handle of entity
594
    TPM2B_NAME         *bind              // OUT: binding value
595
    )
596
9
{
597
9
    TPM2B_AUTH               auth;
598
9
    INT16                    overlap;
599
    // Get name
600
9
    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
9
    auth.t.size = EntityGetAuthValue(entityHandle, &auth.t.buffer);
607
9
    pAssert(auth.t.size <= sizeof(TPMU_HA));
608
    // Figure out if there will be any overlap
609
9
    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
9
    if(overlap > 0)
612
0
    {
613
        // The overlap area is at the end of the Name
614
0
        BYTE    *result = &bind->t.name[bind->t.size - overlap];
615
0
        int     i;
616
         // XOR the auth value into the Name for the overlap area
617
0
         for(i = 0; i < overlap; i++)
618
0
             result[i] ^= auth.t.buffer[i];
619
0
    }
620
9
    else
621
9
    {
622
        // There is no overlap
623
9
        overlap = 0;
624
9
    }
625
    //copy the remainder of the authData to the end of the name
626
9
    MemoryCopy(&bind->t.name[bind->t.size], &auth.t.buffer[overlap],
627
9
               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
9
    bind->t.size += auth.t.size-overlap;
630
9
    return;
631
9
}
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
640
SessionInitPolicyData(
641
    SESSION            *session           // IN: session handle
642
    )
643
5
{
644
    // Initialize start time
645
5
    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
5
     session->u2.policyDigest.t.size = CryptGetHashDigestSize(session->authHashAlg);
650
5
     return;
651
5
}
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
659
SessionResetPolicyData(
660
     SESSION            *session             // IN: the session to reset
661
     )
662
0
{
663
0
     session->commandCode = 0;              // No command
664
     // No locality selected
665
0
     MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality));
666
     // The cpHash size to zero
667
0
     session->u1.cpHash.b.size = 0;
668
     // No timeout
669
0
     session->timeOut = 0;
670
     // Reset the pcrCounter
671
0
     session->pcrCounter = 0;
672
     // Reset the policy hash
673
0
     MemorySet(&session->u2.policyDigest.t.buffer, 0,
674
0
               session->u2.policyDigest.t.size);
675
     // Reset the session attributes
676
0
     MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES));
677
     // set the policy attribute
678
0
     session->attributes.isPolicy = SET;
679
0
}
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
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
34
{
699
34
     TPMI_YES_NO        more = NO;
700
34
     UINT32             i;
701
34
     pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION);
702
     // Initialize output handle list
703
34
     handleList->count = 0;
704
     // The maximum count of handles we may return is MAX_CAP_HANDLES
705
34
     if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
706
     // Iterate session context ID slots to get loaded session handles
707
246
     for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++)
708
212
     {
709
         // If session is active
710
212
         if(gr.contextArray[i] != 0)
711
0
         {
712
             // If session is loaded
713
0
             if (gr.contextArray[i] <= MAX_LOADED_SESSIONS)
714
0
             {
715
0
                 if(handleList->count < count)
716
0
                 {
717
0
                     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
0
                        handle = i + HMAC_SESSION_FIRST;
722
0
                        session = SessionGet(handle);
723
0
                        if(session->attributes.isPolicy)
724
0
                            handle = i + POLICY_SESSION_FIRST;
725
0
                        handleList->handle[handleList->count] = handle;
726
0
                        handleList->count++;
727
0
                   }
728
0
                   else
729
0
                   {
730
                       // If the return list is full but we still have loaded object
731
                       // available, report this and stop iterating
732
0
                       more = YES;
733
0
                       break;
734
0
                   }
735
0
               }
736
0
          }
737
212
     }
738
34
     return more;
739
34
}
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
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
55
{
759
55
     TPMI_YES_NO        more = NO;
760
55
     UINT32             i;
761
55
   pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION);
762
   // Initialize output handle list
763
55
   handleList->count = 0;
764
   // The maximum count of handles we may return is MAX_CAP_HANDLES
765
55
   if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
766
   // Iterate session context ID slots to get loaded session handles
767
405
   for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++)
768
350
   {
769
       // If session is active
770
350
       if(gr.contextArray[i] != 0)
771
0
       {
772
           // If session is saved
773
0
           if (gr.contextArray[i] > MAX_LOADED_SESSIONS)
774
0
           {
775
0
               if(handleList->count < count)
776
0
               {
777
                   // If we have not filled up the return list, add this
778
                   // session handle to it
779
0
                   handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST;
780
0
                   handleList->count++;
781
0
               }
782
0
               else
783
0
               {
784
                   // If the return list is full but we still have loaded object
785
                   // available, report this and stop iterating
786
0
                   more = YES;
787
0
                   break;
788
0
               }
789
0
           }
790
0
       }
791
350
   }
792
55
   return more;
793
55
}
794
//
795
//
796
//          SessionCapGetLoadedNumber()
797
//
798
//      This function return the number of authorization sessions currently loaded into TPM RAM.
799
//
800
UINT32
801
SessionCapGetLoadedNumber(
802
   void
803
   )
804
23
{
805
23
   return MAX_LOADED_SESSIONS - s_freeSessionSlots;
806
23
}
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
818
SessionCapGetLoadedAvail(
819
   void
820
   )
821
23
{
822
23
     return s_freeSessionSlots;
823
23
}
824
//
825
//
826
//           SessionCapGetActiveNumber()
827
//
828
//      This function returns the number of active authorization sessions currently being tracked by the TPM.
829
//
830
UINT32
831
SessionCapGetActiveNumber(
832
     void
833
     )
834
22
{
835
22
     UINT32                  i;
836
22
     UINT32                  num = 0;
837
     // Iterate the context array to find the number of non-zero slots
838
1.43k
     for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
839
1.40k
     {
840
1.40k
         if(gr.contextArray[i] != 0) num++;
841
1.40k
     }
842
22
     return num;
843
22
}
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
853
SessionCapGetActiveAvail(
854
     void
855
     )
856
22
{
857
22
     UINT32                  i;
858
22
     UINT32                  num = 0;
859
     // Iterate the context array to find the number of zero slots
860
1.43k
     for(i = 0; i < MAX_ACTIVE_SESSIONS; i++)
861
1.40k
     {
862
1.40k
         if(gr.contextArray[i] == 0) num++;
863
1.40k
     }
864
22
     return num;
865
22
}