コード例 #1
0
ファイル: SlotManager.cs プロジェクト: Microsoft/TSS.MSR
        /// <summary>
        /// Dispatch a command to the underlying TPM. This method implements all significant functionality.
        /// DispatchCommand examines the command stream and performs (approximately) the following functions
        /// 1) If the command references a handle (session or transient object) then TBS makes sure that the entity 
        ///     is loaded. If it is, then the handle is "translated" to the underlying TPM handle. If it is not, then
        ///     TBS checks to see if it has a saved context for the entity, and if so loads it.
        /// 2) If the command will fill a slot, then TBS ensures that a slot is available. It does this by ContextSaving
        ///     the LRU entity of the proper type (that is not used in this command).
        /// </summary>
        /// <param name="caller"></param>
        /// <param name="active"></param>
        /// <param name="inBuf"></param>
        /// <param name="outBuf"></param>
        /// <exception cref="Exception"></exception>
        internal void DispatchCommand(TbsContext caller, CommandModifier active, byte[] inBuf, out byte[] outBuf)
        {
            lock (this)
            {
                CommandNumber++;
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (StateSaveProbability != 0.0)
                {
                    // S3 debug support
                    DebugStateSave();
                    LastStateSaveCommandNumber = CommandNumber;
                }

                CommandHeader commandHeader;
                TpmHandle[] inHandles;
                SessionIn[] inSessions;
                byte[] commandParmsNoHandles;
                bool legalCommand = CommandProcessor.CrackCommand(inBuf, out commandHeader, out inHandles, out inSessions, out commandParmsNoHandles);

                if (!legalCommand)
                {
                    // Is a diagnostics command.  Pass through to TPM (a real RM would refuse).
                    TpmDevice.DispatchCommand(active, inBuf, out outBuf);
                    return;
                }

                TpmCc commandCode = commandHeader.CommandCode;

                // Lookup command
                CommandInfo command = Tpm2.CommandInfoFromCommandCode(commandCode);
                if (command == null)
                {
                    throw new Exception("Unrecognized command");
                }

                if (commandCode == TpmCc.ContextLoad || commandCode == TpmCc.ContextSave)
                {
                    //throw new Exception("ContextLoad and ContextSave not supported in this build");
#if !NETFX_CORE
                    Console.Error.WriteLine("ContextLoad and ContextSave not supported in this build");
#endif
                    outBuf = Marshaller.GetTpmRepresentation(new Object[] {
                        TpmSt.NoSessions,
                        (uint)10,
                        TpmRc.NotUsed });
                }

                // Look up referenced objects and sessions
                ObjectContext[] neededObjects = GetReferencedObjects(caller, inHandles);
                ObjectContext[] neededSessions = GetSessions(caller, inSessions);
                ObjectContext[] neededEntities =
                        neededObjects != null
                            ? neededSessions != null
                                ? neededObjects.Concat(neededSessions).ToArray()
                                : neededObjects
                            : neededSessions;
                if (neededObjects == null || neededSessions == null)
                {
                    // This means that one or more of the handles was not registered for the context
                    byte[] ret = FormatError(TpmRc.Handle);
                    outBuf = ret;
                    return;
                }

                // Load referenced objects and sessions (free slots if needed)
                // It's important to load all object and session handles in a single call
                // to LoadEntities(), as for some commands (e.g. GetSessionAuditDigest)
                // the objects array may contain session handles. In this case the session
                // handles loaded by the invocation of LoadEntities for neededObjects
                // may be evicted again during the subsequent call for neededSessions.
                bool loadOk = LoadEntities(neededEntities);
                if (!loadOk)
                {
                    throw new Exception("Failed to make space for objects or sessions at to execute command");
                }

                // At this point everything referenced should be loaded, and there will be a free slot if needed
                // so we can translate the input handles to the underlying handles 
                ReplaceHandlesIn(inHandles, inSessions, neededObjects, neededSessions);

                // create the translated command from the various components we have been manipulating
                byte[] commandBuf = CommandProcessor.CreateCommand(commandHeader.CommandCode, inHandles, inSessions, commandParmsNoHandles);
                Debug.Assert(commandBuf.Length == inBuf.Length);

                byte[] responseBuf;
                
                // Todo: Virtualize GetCapability for handle enumeration.

                //
                // Execute command on underlying TPM device.
                // If we get an ObjectMemory or SessionMemory error we try to make more space and try again
                // Note: If the TPM device throws an error above we let it propagate out.  There should be no side 
                // effects on TPM state that the TBS cares about.
                //
                do
                {
                    TpmDevice.DispatchCommand(active, commandBuf, out responseBuf);
                    TpmRc res = GetResultCode(responseBuf);
                    if (res == TpmRc.Success)
                    {
                        break;
                    }

                    var slotType = SlotType.NoSlot;
                    if (res == TpmRc.ObjectHandles || res == TpmRc.ObjectMemory)
                    {
                        slotType = SlotType.ObjectSlot;
                    }
                    else if (res == TpmRc.SessionHandles || res == TpmRc.SessionMemory)
                    {
                        slotType = SlotType.SessionSlot;
                    }
                    else
                    {
                        // Command failure not related to resources
                        break;
                    }
                    bool slotMade = MakeSpace(slotType, neededEntities);
                    if (!slotMade)
                    {
                        throw new Exception("Failed to make an object slot in the TPM");
                    }
                } while (true);

                // Parse the response from the TPM
                // TODO: Make this use the new methods in Tpm2

                // ReSharper disable once UnusedVariable
                var mOut = new Marshaller(responseBuf);
                TpmSt responseTag;
                uint responseParamSize;
                TpmRc resultCode;
                TpmHandle[] responseHandles;
                SessionOut[] responseSessions;
                byte[] responseParmsNoHandles, responseParmsWithHandles;

                CommandProcessor.SplitResponse(responseBuf,
                                               command.HandleCountOut,
                                               out responseTag,
                                               out responseParamSize,
                                               out resultCode,
                                               out responseHandles,
                                               out responseSessions,
                                               out responseParmsNoHandles,
                                               out responseParmsWithHandles);

                // If we have an error there is no impact on the loaded sessions, but we update
                // the LRU values because the user will likely try again.
                if (resultCode != TpmRc.Success)
                {
                    outBuf = responseBuf;
                    UpdateLastUseCount(new[] {neededObjects, neededSessions});
                    return;
                }

                // Update TBS database with any newly created TPM objects
                ProcessUpdatedTpmState(caller, command, responseHandles, neededObjects);

                // And if there were any newly created objects use the new DB entries to translate the handles
                ReplaceHandlesOut(responseHandles);
                byte[] translatedResponse = CommandProcessor.CreateResponse(resultCode, responseHandles, responseSessions, responseParmsNoHandles);

                outBuf = translatedResponse;
                Debug.Assert(outBuf.Length == responseBuf.Length);
            } // lock(this)
        }
コード例 #2
0
ファイル: SlotManager.cs プロジェクト: Microsoft/TSS.MSR
 public override void DispatchCommand(CommandModifier active, byte[] inBuf, out byte[] outBuf)
 {
     Tbs.DispatchCommand(this, active, inBuf, out outBuf);
 }
コード例 #3
0
ファイル: Tpm2.cs プロジェクト: vishalishere/TSS.MSR
 /// <summary>
 /// Send TPM-command buffer to device
 /// </summary>
 /// <param name="active">Locality and priority</param>
 /// <param name="inBuf">command buffer</param>
 /// <param name="outBuf">response buffer</param>
 public virtual void DispatchCommand(CommandModifier active, byte[] inBuf, out byte[] outBuf)
 {
     outBuf = new byte[4];
     throw new Exception("Should never be here");
 }