/// <summary> /// Make a space in the TPM for an entity of type neededSlot (while not evicting another needed entity) /// </summary> /// <param name="neededSlot"></param> /// <param name="doNotEvict"></param> private bool MakeSpace(SlotType neededSlot, ObjectContext[] doNotEvict) { ObjectContext entityToEvict = ContextManager.GetBestEvictionCandidate(neededSlot, doNotEvict); if (entityToEvict == null) { return false; } // Candidate is the entity that we need to evict. Save it, and then update our internal database. Context b = Tpm.ContextSave(entityToEvict.TheTpmHandle); entityToEvict.Context = b; // Non-session objects evict on their own. Transient objects need to be evicted explictly. // TODO: Manage the saved-context array. if (neededSlot != SlotType.SessionSlot) { Tpm.FlushContext(entityToEvict.TheTpmHandle); } entityToEvict.TheTpmHandle = null; entityToEvict.Loaded = false; return true; }
/// <summary> /// Modifies the handles and sessions arrays so that they contain the translated handles. /// </summary> /// <param name="handles"></param> /// <param name="sessions"></param> /// <param name="theObjects"></param> /// <param name="theSessions"></param> private void ReplaceHandlesIn(TpmHandle[] handles, SessionIn[] sessions, ObjectContext[] theObjects, ObjectContext[] theSessions) { for (int j = 0; j < handles.Length; j++) { handles[j] = theObjects[j].TheTpmHandle; } for (int j = 0; j < sessions.Length; j++) { sessions[j].handle = theSessions[j].TheTpmHandle; } }
/// <summary> /// Ensure that all referenced objects are loaded. /// </summary> /// <param name="neededContexts"></param> private bool LoadEntities(ObjectContext[] neededContexts) { return (from t in neededContexts where !t.Loaded select LoadObject(t, neededContexts)).All(loaded => loaded); }
/// <summary> /// Load an object making a space if needed. If we need to make a space then we are /// mindful not to evict anything in the doNotEvict array. /// </summary> /// <param name="contextToLoad"></param> /// <param name="doNotEvict"></param> private bool LoadObject(ObjectContext contextToLoad, ObjectContext[] doNotEvict) { do { contextToLoad.TheTpmHandle = Tpm._AllowErrors().ContextLoad(contextToLoad.Context); if (Tpm._LastCommandSucceeded()) { break; } bool spaceMade = MakeSpace(contextToLoad.TheSlotType, doNotEvict); if (!spaceMade) { return false; } } while (true); contextToLoad.Loaded = true; return true; }
/// <summary> /// Get the TBS ObjectContext given SessionIn objects collected from the inputs stream. /// </summary> /// <param name="caller"></param> /// <param name="inSessions"></param> /// <returns></returns> private ObjectContext[] GetSessions(TbsContext caller, SessionIn[] inSessions) { var contexts = new ObjectContext[inSessions.Length]; for (int j = 0; j < inSessions.Length; j++) { contexts[j] = ContextManager.GetContext(caller, inSessions[j].handle); if (contexts[j] == null) { return null; } } return contexts; }
/// <summary> /// Look up TBS ObjectContext records given the handles in the inHandles input parms. /// </summary> /// <param name="caller"></param> /// <param name="inHandles"></param> /// <returns></returns> private ObjectContext[] GetReferencedObjects(TbsContext caller, TpmHandle[] inHandles) { var neededContexts = new ObjectContext[inHandles.Length]; for (int j = 0; j < inHandles.Length; j++) { neededContexts[j] = ContextManager.GetContext(caller, inHandles[j]); if (neededContexts[j] == null) { return null; } } return neededContexts; }
/// <summary> /// Updates TBS context database for commands that either fill or empty slots. /// </summary> /// <param name="caller"></param> /// <param name="command"></param> /// <param name="responseHandles"></param> /// <param name="inputObjects"></param> private void ProcessUpdatedTpmState(TbsContext caller, CommandInfo command, TpmHandle[] responseHandles, ObjectContext[] inputObjects) { switch (command.CommandCode) { // Commands that fill a slot (apart from contextLoad, which is more complex) case TpmCc.Load: case TpmCc.LoadExternal: case TpmCc.CreatePrimary: case TpmCc.HmacStart: case TpmCc.HashSequenceStart: case TpmCc.StartAuthSession: var t = new TpmHandle(responseHandles[0].handle); // ReSharper disable once UnusedVariable ObjectContext context2 = ContextManager.CreateObjectContext(caller, t); break; case TpmCc.ContextLoad: case TpmCc.ContextSave: throw new Exception("ProcessUpdatedTpmState: Should not be here"); case TpmCc.FlushContext: case TpmCc.SequenceComplete: ContextManager.Remove(inputObjects[0]); break; case TpmCc.EventSequenceComplete: ContextManager.Remove(inputObjects[1]); break; } }
internal ObjectContext CreateObjectContext(Tbs.TbsContext owner, TpmHandle tpmHandle) { Tbs.SlotType newSlotType = Tbs.SlotTypeFromHandle(tpmHandle); if (newSlotType == Tbs.SlotType.NoSlot) { throw new Exception("CreateObjectContext: Should not be here"); } // Make a new slot context of the requisite type uint tbsHandle = GetFreeHandle(owner, tpmHandle); var newContext = new ObjectContext { OwnerHandle = new TpmHandle(tbsHandle), TheTpmHandle = tpmHandle, TheSlotType = newSlotType, LastUseCount = GetUseCount(), Loaded = true, Owner = owner }; ObjectContexts.Add(newContext); return newContext; }
public void Remove(ObjectContext c) { ObjectContexts.Remove(c); }
/// <summary> /// Gets the best eviction candidate for entities of given type. May return NULL. /// </summary> /// <param name="neededSlot"></param> /// <param name="neededEntities"></param> /// <returns></returns> internal ObjectContext GetBestEvictionCandidate(Tbs.SlotType neededSlot, ObjectContext[] neededEntities) { ObjectContext candidate = null; foreach (ObjectContext c in ObjectContexts) { // See if this context is a candidate for eviction if (!c.Loaded) { continue; } if (c.TheSlotType != neededSlot) { continue; } // Currently loaded entity of correct type, but is it referenced in this operation? if (neededEntities.Contains(c)) { continue; } // ObjectContext c is a candidate for removal. If we don't already // have a candidate then see if the new candidate is staler than the old. if (candidate == null) { candidate = c; } else { if (c.LastUseCount < candidate.LastUseCount) { candidate = c; } } } return candidate; }
internal ObjectContext GetContext(Tbs.TbsContext caller, TpmHandle callerHandle) { if (Tbs.SlotTypeFromHandle(callerHandle) == Tbs.SlotType.NoSlot) { // Indicates that this is a TPM resident object (NV-slot, primary-handle, PWAP-handle, etc.) var temp = new ObjectContext {TheTpmHandle = callerHandle}; return temp; } ObjectContext x = ObjectContexts.Find(item => (item.Owner == caller) && item.OwnerHandle.handle == callerHandle.handle); // Note that x may be null return x; }