// This file was extracted from the TCG Published // Trusted Platform Module Library // Part 4: Supporting Routines // Family "2.0" // Level 00 Revision 01.16 // October 30, 2014 #define SESSION_C #include "InternalRoutines.h" #include "Platform.h" #include "SessionProcess_fp.h" // // // File Scope Function -- ContextIdSetOldest() // // This function is called when the oldest contextID is being loaded or deleted. Once a saved context // becomes the oldest, it stays the oldest until it is deleted. // Finding the oldest is a bit tricky. It is not just the numeric comparison of values but is dependent on the // value of contextCounter. // Assume we have a small contextArray with 8, 4-bit values with values 1 and 2 used to indicate the loaded // context slot number. Also assume that the array contains hex values of (0 0 1 0 3 0 9 F) and that the // contextCounter is an 8-bit counter with a value of 0x37. Since the low nibble is 7, that means that values // above 7 are older than values below it and, in this example, 9 is the oldest value. // Note if we subtract the counter value, from each slot that contains a saved contextID we get (- - - - B - 2 - // 8) and the oldest entry is now easy to find. // static void ContextIdSetOldest( void ) { CONTEXT_SLOT lowBits; CONTEXT_SLOT entry; CONTEXT_SLOT smallest = ((CONTEXT_SLOT) ~0); UINT32 i; // // Set oldestSaveContext to a value indicating none assigned s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; lowBits = (CONTEXT_SLOT)gr.contextCounter; for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { entry = gr.contextArray[i]; // only look at entries that are saved contexts if(entry > MAX_LOADED_SESSIONS) { // Use a less than or equal in case the oldest // is brand new (= lowBits-1) and equal to our initial // value for smallest. if(((CONTEXT_SLOT) (entry - lowBits)) <= smallest) { smallest = (entry - lowBits); s_oldestSavedSession = i; } } } // When we finish, either the s_oldestSavedSession still has its initial // value, or it has the index of the oldest saved context. } // // // Startup Function -- SessionStartup() // // This function initializes the session subsystem on TPM2_Startup(). // void SessionStartup( STARTUP_TYPE type ) { UINT32 i; // Initialize session slots. At startup, all the in-memory session slots // are cleared and marked as not occupied for(i = 0; i < MAX_LOADED_SESSIONS; i++) s_sessions[i].occupied = FALSE; // session slot is not occupied // The free session slots the number of maximum allowed loaded sessions s_freeSessionSlots = MAX_LOADED_SESSIONS; // Initialize context ID data. On a ST_SAVE or hibernate sequence, it will // scan the saved array of session context counts, and clear any entry that // references a session that was in memory during the state save since that // memory was not preserved over the ST_SAVE. if(type == SU_RESUME || type == SU_RESTART) { // On ST_SAVE we preserve the contexts that were saved but not the ones // in memory for (i = 0; i < MAX_ACTIVE_SESSIONS; i++) { // If the array value is unused or references a loaded session then // that loaded session context is lost and the array entry is // reclaimed. if (gr.contextArray[i] <= MAX_LOADED_SESSIONS) gr.contextArray[i] = 0; } // Find the oldest session in context ID data and set it in // s_oldestSavedSession ContextIdSetOldest(); // } else { // For STARTUP_CLEAR, clear out the contextArray for (i = 0; i < MAX_ACTIVE_SESSIONS; i++) gr.contextArray[i] = 0; // reset the context counter gr.contextCounter = MAX_LOADED_SESSIONS + 1; // Initialize oldest saved session s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; } return; } // // // Access Functions // // SessionIsLoaded() // // This function test a session handle references a loaded session. The handle must have previously been // checked to make sure that it is a valid handle for an authorization session. // // NOTE: A PWAP authorization does not have a session. // // // Return Value Meaning // // TRUE if session is loaded // FALSE if it is not loaded // BOOL SessionIsLoaded( TPM_HANDLE handle // IN: session handle ) { pAssert( HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION); handle = handle & HR_HANDLE_MASK; // if out of range of possible active session, or not assigned to a loaded // session return false if( handle >= MAX_ACTIVE_SESSIONS || gr.contextArray[handle] == 0 || gr.contextArray[handle] > MAX_LOADED_SESSIONS ) return FALSE; return TRUE; } // // // SessionIsSaved() // // This function test a session handle references a saved session. The handle must have previously been // checked to make sure that it is a valid handle for an authorization session. // // NOTE: An password authorization does not have a session. // // This function requires that the handle be a valid session handle. // // // Return Value Meaning // // TRUE if session is saved // FALSE if it is not saved // BOOL SessionIsSaved( TPM_HANDLE handle // IN: session handle ) { pAssert( HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION); handle = handle & HR_HANDLE_MASK; // if out of range of possible active session, or not assigned, or // assigned to a loaded session, return false if( handle >= MAX_ACTIVE_SESSIONS || gr.contextArray[handle] == 0 || gr.contextArray[handle] <= MAX_LOADED_SESSIONS ) return FALSE; return TRUE; } // // // SessionPCRValueIsCurrent() // // This function is used to check if PCR values have been updated since the last time they were checked in // a policy session. // This function requires the session is loaded. // // Return Value Meaning // // TRUE if PCR value is current // FALSE if PCR value is not current // BOOL SessionPCRValueIsCurrent( TPMI_SH_POLICY handle // IN: session handle ) { SESSION *session; pAssert(SessionIsLoaded(handle)); session = SessionGet(handle); if( session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter ) return FALSE; else return TRUE; } // // // SessionGet() // // This function returns a pointer to the session object associated with a session handle. // The function requires that the session is loaded. // SESSION * SessionGet( TPM_HANDLE handle // IN: session handle ) { CONTEXT_SLOT sessionIndex; pAssert( HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION ); pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS); // get the contents of the session array. Because session is loaded, we // should always get a valid sessionIndex sessionIndex = gr.contextArray[handle & HR_HANDLE_MASK] - 1; pAssert(sessionIndex < MAX_LOADED_SESSIONS); return &s_sessions[sessionIndex].session; } // // // Utility Functions // // ContextIdSessionCreate() // // This function is called when a session is created. It will check to see if the current gap would prevent a // context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find an // open slot in contextArray, set contextArray to the slot. // This routine requires that the caller has determined the session array index for the session. // // return type TPM_RC // // TPM_RC_SUCCESS context ID was assigned // TPM_RC_CONTEXT_GAP can't assign a new contextID until the oldest saved session context is // recycled // TPM_RC_SESSION_HANDLE there is no slot available in the context array for tracking of this // session context // static TPM_RC ContextIdSessionCreate ( TPM_HANDLE *handle, // OUT: receives the assigned handle. This will // be an index that must be adjusted by the // caller according to the type of the // session created UINT32 sessionIndex // IN: The session context array entry that will // be occupied by the created session ) { pAssert(sessionIndex < MAX_LOADED_SESSIONS); // check to see if creating the context is safe // Is this going to be an assignment for the last session context // array entry? If so, then there will be no room to recycle the // oldest context if needed. If the gap is not at maximum, then // it will be possible to save a context if it becomes necessary. if( s_oldestSavedSession < MAX_ACTIVE_SESSIONS && s_freeSessionSlots == 1) { // See if the gap is at maximum if( (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession]) // Note: if this is being used on a TPM.combined, this return // code should be transformed to an appropriate 1.2 error // code for this case. return TPM_RC_CONTEXT_GAP; } // Find an unoccupied entry in the contextArray for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++) { if(gr.contextArray[*handle] == 0) { // indicate that the session associated with this handle // references a loaded session gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex+1); return TPM_RC_SUCCESS; } } return TPM_RC_SESSION_HANDLES; } // // // SessionCreate() // // This function does the detailed work for starting an authorization session. This is done in a support // routine rather than in the action code because the session management may differ in implementations. // This implementation uses a fixed memory allocation to hold sessions and a fixed allocation to hold the // contextID for the saved contexts. // // Error Returns Meaning // // TPM_RC_CONTEXT_GAP need to recycle sessions // TPM_RC_SESSION_HANDLE active session space is full // TPM_RC_SESSION_MEMORY loaded session space is full // TPM_RC SessionCreate( TPM_SE sessionType, // IN: the session type TPMI_ALG_HASH authHash, // IN: the hash algorithm TPM2B_NONCE *nonceCaller, // IN: initial nonceCaller TPMT_SYM_DEF *symmetric, // IN: the symmetric algorithm TPMI_DH_ENTITY bind, // IN: the bind object TPM2B_DATA *seed, // IN: seed data TPM_HANDLE *sessionHandle // OUT: the session handle ) { TPM_RC result = TPM_RC_SUCCESS; CONTEXT_SLOT slotIndex; SESSION *session = NULL; pAssert( sessionType == TPM_SE_HMAC || sessionType == TPM_SE_POLICY || sessionType == TPM_SE_TRIAL); // If there are no open spots in the session array, then no point in searching if(s_freeSessionSlots == 0) return TPM_RC_SESSION_MEMORY; // Find a space for loading a session for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) { // Is this available? if(s_sessions[slotIndex].occupied == FALSE) { session = &s_sessions[slotIndex].session; break; } } // if no spot found, then this is an internal error pAssert (slotIndex < MAX_LOADED_SESSIONS); // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be // returned from ContextIdHandelAssign() result = ContextIdSessionCreate(sessionHandle, slotIndex); if(result != TPM_RC_SUCCESS) return result; //*** Only return from this point on is TPM_RC_SUCCESS // Can now indicate that the session array entry is occupied. s_freeSessionSlots--; s_sessions[slotIndex].occupied = TRUE; // Initialize the session data MemorySet(session, 0, sizeof(SESSION)); // Initialize internal session data session->authHashAlg = authHash; // Initialize session type if(sessionType == TPM_SE_HMAC) { *sessionHandle += HMAC_SESSION_FIRST; } else { *sessionHandle += POLICY_SESSION_FIRST; // For TPM_SE_POLICY or TPM_SE_TRIAL session->attributes.isPolicy = SET; if(sessionType == TPM_SE_TRIAL) session->attributes.isTrialPolicy = SET; // Initialize policy session data SessionInitPolicyData(session); } // Create initial session nonce session->nonceTPM.t.size = nonceCaller->t.size; CryptGenerateRandom(session->nonceTPM.t.size, session->nonceTPM.t.buffer); // Set up session parameter encryption algorithm session->symmetric = *symmetric; // If there is a bind object or a session secret, then need to compute // a sessionKey. if(bind != TPM_RH_NULL || seed->t.size != 0) { // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM, // nonceCaller, bits) // The HMAC key for generating the sessionSecret can be the concatenation // of an authorization value and a seed value TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer))); TPM2B_KEY key; UINT16 hashSize; // The size of the hash used by the // session crated by this command TPM2B_AUTH entityAuth; // The authValue of the entity // associated with HMAC session // Get hash size, which is also the length of sessionKey hashSize = CryptGetHashDigestSize(session->authHashAlg); // Get authValue of associated entity entityAuth.t.size = EntityGetAuthValue(bind, &entityAuth.t.buffer); // Concatenate authValue and seed pAssert(entityAuth.t.size + seed->t.size <= sizeof(key.t.buffer)); MemoryCopy2B(&key.b, &entityAuth.b, sizeof(key.t.buffer)); MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer)); session->sessionKey.t.size = hashSize; // Compute the session key KDFa(session->authHashAlg, &key.b, "ATH", &session->nonceTPM.b, &nonceCaller->b, hashSize * 8, session->sessionKey.t.buffer, NULL); } // Copy the name of the entity that the HMAC session is bound to // Policy session is not bound to an entity if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC) { session->attributes.isBound = SET; SessionComputeBoundEntity(bind, &session->u1.boundEntity); } // If there is a bind object and it is subject to DA, then use of this session // is subject to DA regardless of how it is used. session->attributes.isDaBound = (bind != TPM_RH_NULL) && (IsDAExempted(bind) == FALSE); // If the session is bound, then check to see if it is bound to lockoutAuth session->attributes.isLockoutBound = (session->attributes.isDaBound == SET) && (bind == TPM_RH_LOCKOUT); return TPM_RC_SUCCESS; } // // // SessionContextSave() // // This function is called when a session context is to be saved. The contextID of the saved session is // returned. If no contextID can be assigned, then the routine returns TPM_RC_CONTEXT_GAP. If the // function completes normally, the session slot will be freed. // This function requires that handle references a loaded session. Otherwise, it should not be called at the // first place. // // Error Returns Meaning // // TPM_RC_CONTEXT_GAP a contextID could not be assigned. // TPM_RC_TOO_MANY_CONTEXTS the counter maxed out // TPM_RC SessionContextSave ( TPM_HANDLE handle, // IN: session handle CONTEXT_COUNTER *contextID // OUT: assigned contextID ) { UINT32 contextIndex; CONTEXT_SLOT slotIndex; pAssert(SessionIsLoaded(handle)); // check to see if the gap is already maxed out // Need to have a saved session if( s_oldestSavedSession < MAX_ACTIVE_SESSIONS // if the oldest saved session has the same value as the low bits // of the contextCounter, then the GAP is maxed out. && gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter) return TPM_RC_CONTEXT_GAP; // if the caller wants the context counter, set it if(contextID != NULL) *contextID = gr.contextCounter; pAssert((handle & HR_HANDLE_MASK) < MAX_ACTIVE_SESSIONS); contextIndex = handle & HR_HANDLE_MASK; // Extract the session slot number referenced by the contextArray // because we are going to overwrite this with the low order // contextID value. slotIndex = gr.contextArray[contextIndex] - 1; // Set the contextID for the contextArray gr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter; // Increment the counter gr.contextCounter++; // In the unlikely event that the 64-bit context counter rolls over... if(gr.contextCounter == 0) { // back it up gr.contextCounter--; // return an error return TPM_RC_TOO_MANY_CONTEXTS; } // if the low-order bits wrapped, need to advance the value to skip over // the values used to indicate that a session is loaded if(((CONTEXT_SLOT)gr.contextCounter) == 0) gr.contextCounter += MAX_LOADED_SESSIONS + 1; // If no other sessions are saved, this is now the oldest. if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS) s_oldestSavedSession = contextIndex; // Mark the session slot as unoccupied s_sessions[slotIndex].occupied = FALSE; // and indicate that there is an additional open slot s_freeSessionSlots++; return TPM_RC_SUCCESS; } // // // SessionContextLoad() // // This function is used to load a session from saved context. The session handle must be for a saved // context. // If the gap is at a maximum, then the only session that can be loaded is the oldest session, otherwise // TPM_RC_CONTEXT_GAP is returned. // This function requires that handle references a valid saved session. // // // // Error Returns Meaning // // TPM_RC_SESSION_MEMORY no free session slots // TPM_RC_CONTEXT_GAP the gap count is maximum and this is not the oldest saved context // TPM_RC SessionContextLoad( SESSION *session, // IN: session structure from saved context TPM_HANDLE *handle // IN/OUT: session handle ) { UINT32 contextIndex; CONTEXT_SLOT slotIndex; pAssert( HandleGetType(*handle) == TPM_HT_POLICY_SESSION || HandleGetType(*handle) == TPM_HT_HMAC_SESSION); // Don't bother looking if no openings if(s_freeSessionSlots == 0) return TPM_RC_SESSION_MEMORY; // Find a free session slot to load the session for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) if(s_sessions[slotIndex].occupied == FALSE) break; // if no spot found, then this is an internal error pAssert (slotIndex < MAX_LOADED_SESSIONS); contextIndex = *handle & HR_HANDLE_MASK; // extract the index // If there is only one slot left, and the gap is at maximum, the only session // context that we can safely load is the oldest one. if( s_oldestSavedSession < MAX_ACTIVE_SESSIONS && s_freeSessionSlots == 1 && (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession] && contextIndex != s_oldestSavedSession ) return TPM_RC_CONTEXT_GAP; pAssert(contextIndex < MAX_ACTIVE_SESSIONS); // set the contextArray value to point to the session slot where // the context is loaded gr.contextArray[contextIndex] = slotIndex + 1; // if this was the oldest context, find the new oldest if(contextIndex == s_oldestSavedSession) ContextIdSetOldest(); // Copy session data to session slot s_sessions[slotIndex].session = *session; // Set session slot as occupied s_sessions[slotIndex].occupied = TRUE; // Reduce the number of open spots s_freeSessionSlots--; return TPM_RC_SUCCESS; } // // // // SessionFlush() // // This function is used to flush a session referenced by its handle. If the session associated with handle is // loaded, the session array entry is marked as available. // This function requires that handle be a valid active session. // void SessionFlush( TPM_HANDLE handle // IN: loaded or saved session handle ) { CONTEXT_SLOT slotIndex; UINT32 contextIndex; // Index into contextArray pAssert( ( HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION ) && (SessionIsLoaded(handle) || SessionIsSaved(handle)) ); // Flush context ID of this session // Convert handle to an index into the contextArray contextIndex = handle & HR_HANDLE_MASK; pAssert(contextIndex < sizeof(gr.contextArray)/sizeof(gr.contextArray[0])); // Get the current contents of the array slotIndex = gr.contextArray[contextIndex]; // Mark context array entry as available gr.contextArray[contextIndex] = 0; // Is this a saved session being flushed if(slotIndex > MAX_LOADED_SESSIONS) { // Flushing the oldest session? if(contextIndex == s_oldestSavedSession) // If so, find a new value for oldest. ContextIdSetOldest(); } else { // Adjust slot index to point to session array index slotIndex -= 1; // Free session array index s_sessions[slotIndex].occupied = FALSE; s_freeSessionSlots++; } return; } // // // SessionComputeBoundEntity() // // This function computes the binding value for a session. The binding value for a reserved handle is the // handle itself. For all the other entities, the authValue at the time of binding is included to prevent // squatting. For those values, the Name and the authValue are concatenated into the bind buffer. If they // will not both fit, the will be overlapped by XORing() bytes. If XOR is required, the bind value will be full. // void SessionComputeBoundEntity( TPMI_DH_ENTITY entityHandle, // IN: handle of entity TPM2B_NAME *bind // OUT: binding value ) { TPM2B_AUTH auth; INT16 overlap; // Get name bind->t.size = EntityGetName(entityHandle, &bind->t.name); // // The bound value of a reserved handle is the handle itself // if(bind->t.size == sizeof(TPM_HANDLE)) return; // For all the other entities, concatenate the auth value to the name. // Get a local copy of the auth value because some overlapping // may be necessary. auth.t.size = EntityGetAuthValue(entityHandle, &auth.t.buffer); pAssert(auth.t.size <= sizeof(TPMU_HA)); // Figure out if there will be any overlap overlap = bind->t.size + auth.t.size - sizeof(bind->t.name); // There is overlap if the combined sizes are greater than will fit if(overlap > 0) { // The overlap area is at the end of the Name BYTE *result = &bind->t.name[bind->t.size - overlap]; int i; // XOR the auth value into the Name for the overlap area for(i = 0; i < overlap; i++) result[i] ^= auth.t.buffer[i]; } else { // There is no overlap overlap = 0; } //copy the remainder of the authData to the end of the name MemoryCopy(&bind->t.name[bind->t.size], &auth.t.buffer[overlap], auth.t.size - overlap, sizeof(bind->t.name) - bind->t.size); // Increase the size of the bind data by the size of the auth - the overlap bind->t.size += auth.t.size-overlap; return; } // // // SessionInitPolicyData() // // This function initializes the portions of the session policy data that are not set by the allocation of a // session. // void SessionInitPolicyData( SESSION *session // IN: session handle ) { // Initialize start time session->startTime = go.clock; // Initialize policyDigest. policyDigest is initialized with a string of 0 of // session algorithm digest size. Since the policy already contains all zeros // it is only necessary to set the size session->u2.policyDigest.t.size = CryptGetHashDigestSize(session->authHashAlg); return; } // // // SessionResetPolicyData() // // This function is used to reset the policy data without changing the nonce or the start time of the session. // void SessionResetPolicyData( SESSION *session // IN: the session to reset ) { session->commandCode = 0; // No command // No locality selected MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality)); // The cpHash size to zero session->u1.cpHash.b.size = 0; // No timeout session->timeOut = 0; // Reset the pcrCounter session->pcrCounter = 0; // Reset the policy hash MemorySet(&session->u2.policyDigest.t.buffer, 0, session->u2.policyDigest.t.size); // Reset the session attributes MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES)); // set the policy attribute session->attributes.isPolicy = SET; } // // // SessionCapGetLoaded() // // This function returns a list of handles of loaded session, started from input handle // Handle must be in valid loaded session handle range, but does not have to point to a loaded session. // // Return Value Meaning // // YES if there are more handles available // NO all the available handles has been returned // TPMI_YES_NO SessionCapGetLoaded( TPMI_SH_POLICY handle, // IN: start handle UINT32 count, // IN: count of returned handle TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate session context ID slots to get loaded session handles for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) { // If session is active if(gr.contextArray[i] != 0) { // If session is loaded if (gr.contextArray[i] <= MAX_LOADED_SESSIONS) { if(handleList->count < count) { SESSION *session; // If we have not filled up the return list, add this // session handle to it // assume that this is going to be an HMAC session handle = i + HMAC_SESSION_FIRST; session = SessionGet(handle); if(session->attributes.isPolicy) handle = i + POLICY_SESSION_FIRST; handleList->handle[handleList->count] = handle; handleList->count++; } else { // If the return list is full but we still have loaded object // available, report this and stop iterating more = YES; break; } } } } return more; } // // // SessionCapGetSaved() // // This function returns a list of handles for saved session, starting at handle. // Handle must be in a valid handle range, but does not have to point to a saved session // // Return Value Meaning // // YES if there are more handles available // NO all the available handles has been returned // TPMI_YES_NO SessionCapGetSaved( TPMI_SH_HMAC handle, // IN: start handle UINT32 count, // IN: count of returned handle TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate session context ID slots to get loaded session handles for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) { // If session is active if(gr.contextArray[i] != 0) { // If session is saved if (gr.contextArray[i] > MAX_LOADED_SESSIONS) { if(handleList->count < count) { // If we have not filled up the return list, add this // session handle to it handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST; handleList->count++; } else { // If the return list is full but we still have loaded object // available, report this and stop iterating more = YES; break; } } } } return more; } // // // SessionCapGetLoadedNumber() // // This function return the number of authorization sessions currently loaded into TPM RAM. // UINT32 SessionCapGetLoadedNumber( void ) { return MAX_LOADED_SESSIONS - s_freeSessionSlots; } // // // SessionCapGetLoadedAvail() // // This function returns the number of additional authorization sessions, of any type, that could be loaded // into TPM RAM. // // NOTE: In other implementations, this number may just be an estimate. The only requirement for the estimate is, if it is // one or more, then at least one session must be loadable. // UINT32 SessionCapGetLoadedAvail( void ) { return s_freeSessionSlots; } // // // SessionCapGetActiveNumber() // // This function returns the number of active authorization sessions currently being tracked by the TPM. // UINT32 SessionCapGetActiveNumber( void ) { UINT32 i; UINT32 num = 0; // Iterate the context array to find the number of non-zero slots for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { if(gr.contextArray[i] != 0) num++; } return num; } // // // SessionCapGetActiveAvail() // // This function returns the number of additional authorization sessions, of any type, that could be created. // This not the number of slots for sessions, but the number of additional sessions that the TPM is capable // of tracking. // UINT32 SessionCapGetActiveAvail( void ) { UINT32 i; UINT32 num = 0; // Iterate the context array to find the number of zero slots for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { if(gr.contextArray[i] == 0) num++; } return num; }