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