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 { 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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