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