Ejemplo n.º 1
0
        void TestFailureMode(Tpm2 tpm, TestContext testCtx)
        {
            tpm._GetUnderlyingDevice().TestFailureMode();
            tpm._ExpectError(TpmRc.Failure)
            .SelfTest(1);

            TpmRc testResult = TpmRc.None;

            byte[] outData = tpm.GetTestResult(out testResult);
            testCtx.Assert("TestResult", testResult == TpmRc.Failure);
            testCtx.Assert("OutData", outData != null && outData.Length > 0);

            // Make sure that selected capabilities can be retrieved even when TPM is in failure mode
            Tpm2.GetProperty(tpm, Pt.Manufacturer);
            Tpm2.GetProperty(tpm, Pt.VendorString1);
            Tpm2.GetProperty(tpm, Pt.VendorTpmType);
            Tpm2.GetProperty(tpm, Pt.FirmwareVersion1);

            // Check if other commands fail as expected while in failure mode.
            tpm._ExpectError(TpmRc.Failure)
            .GetRandom(8);

            // Bring TPM back to normal.
            tpm._GetUnderlyingDevice().PowerCycle();
            tpm.Startup(Su.Clear);
        } // TestFailureMode
Ejemplo n.º 2
0
        private void LogCommandExecution(TpmCc cc, TpmRc rc, TimeSpan executionTime)
        {
            NumCommands++;

            if (!KnownCommandCodes.Contains(cc.ToString()))
            {
                cc = TpmCc.None;
            }
            if (!CmdStats.ContainsKey(cc))
            {
                CmdStats.Add(cc, new CommandStats());
            }

            CommandStats stat = CmdStats[cc];

            if (rc == TpmRc.Success)
            {
                stat.NumSuccess++;
                stat.SuccessExecutionTime += executionTime;
            }
            else
            {
                stat.NumFailures++;
                stat.FailureExecutionTime += executionTime;
                if (!stat.FailureResponses.Contains(rc))
                {
                    stat.FailureResponses.Add(rc);
                }
            }
            // No need to update stat.CallerTests here. Current test will be logged
            // in the command execution statistics in the TestCompleted() notification.
        }
Ejemplo n.º 3
0
 public TpmException(TpmRc rawResponse, string errorDescription, TpmStructureBase cmdParms)
     : base(errorDescription)
 {
     ErrorString = TpmErrorHelpers.ErrorNumber(rawResponse).ToString();
     RawResponse = rawResponse;
     CmdParms    = cmdParms;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Composes and returns a valid TPM response buffer containg the given
 /// error response code.
 /// </summary>
 /// <param name="errorCode"></param>
 /// <returns></returns>
 public static byte[] BuildErrorResponseBuffer(TpmRc errorCode)
 {
     return(Marshaller.GetTpmRepresentation(new Object[] {
         TpmSt.NoSessions,
         (uint)10,
         errorCode
     }));
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Returns error number, i.e. what is left after masking out auxiliary data
        /// (such as format selector, version, and bad parameter index) from the
        /// response code returned by TPM.
        /// </summary>
        public static TpmRc ErrorNumber(TpmRc rawResponse)
        {
            const uint Fmt1 = (uint)TpmRc.RcFmt1;   // Format 1 code (TPM 2 only)
            const uint Ver1 = (uint)TpmRc.RcVer1;   // TPM 1 code (format 0 only)
            const uint Warn = (uint)TpmRc.RcWarn;   // Code is a warning (format 0 only)
            uint       mask = IsFmt1(rawResponse) ? Fmt1 | 0x3F : Warn | Ver1 | 0x7F;

            return((TpmRc)((uint)rawResponse & mask));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Create a 10 byte error response that matches TPM error responses.
        /// </summary>
        /// <param name="errorCode"></param>
        /// <returns></returns>
        private byte[] FormatError(TpmRc errorCode)
        {
            var m = new Marshaller();

            m.Put(TpmSt.NoSessions, "");
            m.Put((uint)10, "");
            m.Put(errorCode, "");
            return(m.GetBytes());
        }
Ejemplo n.º 7
0
        public override void CancelContext()
        {
            TpmRc result = TbsWrapper.NativeMethods.Tbsip_Cancel_Commands(TbsHandle);

            if (result != TpmRc.Success)
            {
                Debug.WriteLine("TbsStubs.Tbsip_Cancel_Command error 0x{0:x}", result);
                throw new Exception("Tbsip_Cancel_Command() failed. Error {" + result + "}");
            }
        }
Ejemplo n.º 8
0
        internal override TpmRc Execute(Tpm2 tpm, AuthSession sess, PolicyTree policy)
        {
            byte[] nonceTpm = UseNonceTpm ? Globs.CopyData(sess.NonceTpm) : new byte[0];

            TpmHandle sigKey;

            // If we have both the authorizing signature and the corresponding
            // signing key handle, we are good to go.
            if (AuthSig == null)
            {
                var dataToSign = new Marshaller();
                dataToSign.Put(nonceTpm, "");

                // If we have a signing key we can build the challenge here
                // (else we need to call out)
                if (SwSigningKey != null)
                {
                    dataToSign.Put(ExpirationTime, "");
                    dataToSign.Put(CpHash, "");
                    dataToSign.Put(PolicyRef, "");
                    // Just ask the key to sign the challenge
                    AuthSig = SwSigningKey.Sign(dataToSign.GetBytes());
                    sigKey  = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner);
                }
                else
                {
                    TpmPublic verifier;
                    AuthSig = AssociatedPolicy.ExecuteSignerCallback(this, nonceTpm,
                                                                     out verifier);
                    sigKey = tpm.LoadExternal(null, verifier, TpmRh.Owner);
                }
            }
            else
            {
                sigKey = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner);
            }
            Timeout = tpm.PolicySigned(sigKey, sess, nonceTpm,
                                       CpHash, PolicyRef, ExpirationTime,
                                       AuthSig, out Ticket);

            TpmRc responseCode = tpm._GetLastResponseCode();

            tpm.FlushContext(sigKey);
            if (!KeepAuth)
            {
                AuthSig = null;
            }
            return(responseCode);
        }
Ejemplo n.º 9
0
        public override void Connect()
        {
            TbsWrapper.TBS_CONTEXT_PARAMS contextParams;

            UIntPtr tbsContext = UIntPtr.Zero;

            contextParams.Version = TbsWrapper.TBS_CONTEXT_VERSION.TWO;
            contextParams.Flags   = TbsWrapper.TBS_CONTEXT_CREATE_FLAGS.IncludeTpm20;
            TpmRc result = TbsWrapper.NativeMethods.Tbsi_Context_Create(ref contextParams, ref tbsContext);

            Debug.WriteLine(Globs.GetResourceString("TbsHandle:") + tbsContext.ToUInt32());

            if (result != TpmRc.Success)
            {
                throw new Exception("Can't create TBS context: Error {" + result + "}");
            }

            TbsHandle      = tbsContext;
            OriginalHandle = tbsContext;
        }
Ejemplo n.º 10
0
        public override void DispatchCommand(CommandModifier active, byte[] inBuf, out byte[] outBuf)
        {
            if (TbsHandle == UIntPtr.Zero)
            {
                throw new Exception("TBS context not created.");
            }

            var   resultBuf       = new byte[4096];
            uint  resultByteCount = (uint)resultBuf.Length;
            TpmRc result          = TpmRc.Success;

            TbsWrapper.TBS_RESULT tbsRes = TbsWrapper.NativeMethods.
                                           Tbsip_Submit_Command(TbsHandle,
                                                                (TbsWrapper.TBS_COMMAND_LOCALITY)active.ActiveLocality,
                                                                active.ActivePriority,
                                                                inBuf,
                                                                (uint)inBuf.Length,
                                                                resultBuf,
                                                                ref resultByteCount);
            string errMsg;

            if (tbsRes == TbsWrapper.TBS_RESULT.SUCCESS)
            {
                if (resultByteCount != 0)
                {
                    outBuf = new byte[resultByteCount];
                    Array.Copy(resultBuf, outBuf, (int)resultByteCount);
                    return;
                }
                result = TpmRc.TbsUnknownError;
                errMsg = Globs.GetResourceString("SubmitError2");
            }
            else
            {
                errMsg = new Win32Exception((int)result).Message;
            }

            outBuf = TpmErrorHelpers.BuildErrorResponseBuffer(result);
        } // TbsDevice.DispatchCommand
Ejemplo n.º 11
0
 public CancelationCtx (Tpm2 t, string cmd)
 {
     tpm = t;
     cmdName = cmd;
     origTolerateErrors = tpm.TolerateErrors;
     origLastError = tpm.LastError;
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Checks if the given response code uses Format-One.
 /// </summary>
 public static bool IsFmt1(TpmRc responseCode)
 {
     return(((uint)responseCode & 0x80) != 0);
 }
Ejemplo n.º 13
0
        /// <summary>
        /// The response hash includes the command ordinal, response code, and the actual command bytes.
        /// </summary>
        /// <param name="hashAlg"></param>
        /// <param name="commandCode"></param>
        /// <param name="responseCode"></param>
        /// <param name="responseParmsNoHandles"></param>
        /// <returns></returns>
        private byte[] GetExpectedResponseHash(
            TpmAlgId hashAlg,
            byte[] responseParmsNoHandles,
            TpmCc commandCode,
            TpmRc responseCode)
        {
            var temp = new Marshaller();
            temp.Put(responseCode, "responseCode");
            temp.Put(commandCode, "currentCommand");
            temp.Put(responseParmsNoHandles, null);

            byte[] parmsHash = CryptoLib.HashData(hashAlg, temp.GetBytes());
            return parmsHash;
        }
Ejemplo n.º 14
0
 public bool NeedRetry()
 {
     lastError = tpm.LastError;
     if (lastError == TpmRc.Canceled)
         thereWasCancelation = true;
     else
         return false;
     return attempt++ < 25;
 }
Ejemplo n.º 15
0
        /// <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");
                    Console.Error.WriteLine("ContextLoad and ContextSave not supported in this build");
                    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);
                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)
                bool loadOk  = LoadEntities(neededObjects);
                bool loadOk2 = LoadEntities(neededSessions);
                if (!loadOk || !loadOk2)
                {
                    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 resCode = GetResultCode(responseBuf);
                    if (resCode == TpmRc.Success)
                    {
                        break;
                    }
                    if (resCode == TpmRc.ObjectMemory)
                    {
                        bool slotMade = MakeSpace(SlotType.ObjectSlot, neededObjects);
                        if (!slotMade)
                        {
                            throw new Exception("Failed to make an object slot in the TPM");
                        }
                        continue;
                    }
                    if (resCode == TpmRc.SessionMemory)
                    {
                        bool slotMade = MakeSpace(SlotType.SessionSlot, neededSessions);
                        if (!slotMade)
                        {
                            throw new Exception("Failed to make a session slot in the TPM");
                        }
                        continue;
                    }
                    break;
                } 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)
        }
Ejemplo n.º 16
0
        // This is installed as the raw command callback handler on the underlying TPM.
        // It is used to generate low-level test statistics (number of commands executed,
        // etc.), dumps of the conversation with the TPM and to keep a record of all
        // command sequences seen that contain types that we haven't seen before.
        // In the case of a multi-context TPM this will be called on different threads,
        // but locking should be handled safely by MainTestLogger.
        void ICommandCallbacks.PostCallback(byte[] inBuf, byte[] outBuf)
        {
            TimeSpan cmdExecutionTime = DateTime.Now - CurCmdStartTime;

            if (inBuf.Length < 10)
            {
                return;
            }
            Marshaller m           = new Marshaller(inBuf);
            TpmSt      sessionTag  = m.Get <TpmSt>();
            uint       parmSize    = m.Get <UInt32>();
            TpmCc      commandCode = m.Get <TpmCc>();

            if (commandCode == TpmCc.Clear)
            {
                ClearWasExecuted = true;
            }

            Marshaller mOut              = new Marshaller(outBuf);
            TpmSt      responseTag       = mOut.Get <TpmSt>();
            uint       responseParamSize = mOut.Get <uint>();
            TpmRc      responseCode      = mOut.Get <TpmRc>();

            if (ValidateTestAttributes)
            {
                // ValidateTestAttributes should not be set for a stress run
                LogTestAttributes(sessionTag, commandCode);
                try
                {
                    if (responseCode == TpmRc.Success)
                    {
                        ValidateHandleUsage(commandCode, inBuf);
                    }
                }
                catch (Exception)
                {
                    // Invalid command buffer can mess this up
                }
            }

            if (sessionTag.Equals(TpmSt.Null))
            {
                return;
            }

            // There are two encoding for errors - formats 0 and 1. Decode the error type
            uint resultCodeValue    = (uint)responseCode;
            bool formatOneErrorType = ((resultCodeValue & 0x80) != 0);
            uint resultCodeMask     = formatOneErrorType ? 0xBFU : 0x97FU;

            TpmRc maskedError = (TpmRc)((uint)responseCode & resultCodeMask);

            lock (this)
            {
                // log the command info to the test logger so that it can collect stats
                LogCommandExecution(commandCode, maskedError, cmdExecutionTime);
            }

#if false
            // Keep a copy of successfully executed commands that contain types we have
            // not seen so far. This is for tests that need good-command candidate strings,
            // like TestCommandDispatcherCoverage.
            // Code 0x80280400 is returned by TBS when the command is blocked by Windows.
            if (maskedError == TpmRc.Success && !Tpm2.IsTbsError(resultCodeValue))
            {
                // look at all types in command string.  If we have a new type we keep it
                CrackedCommand cc   = CommandProcessor.CrackCommand(inBuf);
                CommandInfo    info = CommandInformation.Info.First(x =>
                                                                    x.CommandCode == cc.Header.CommandCode);
                byte[] inStructBytes = Globs.Concatenate(
                    Globs.GetZeroBytes((int)info.HandleCountIn * 4),
                    cc.CommandParms);
                Marshaller mx = new Marshaller(inStructBytes);

                TpmStructureBase bb = (TpmStructureBase)mx.Get(info.InStructType, "");

                // If a new type is contained, save this command for testing in
                // TestDispatcherCoverage.
                if (HasNewTypes(bb))
                {
                    ExecutedCommandInfo.Add(inBuf);
                }
            }
            else
#else
            if (maskedError != TpmRc.Success)
#endif
            {
                // If a command failed, we can get here only if the corresponding
                // expected error assertion was specified.
                ++NumAsserts;
            }
            ReportProgress();

            // output TPM IO to a text file for later processing
            if (Logger.LogTpmIo)
            {
                while (TpmIoWriter == null)
                {
                    try
                    {
                        string ioLogPath;
                        if (Logger.LogPath != null)
                        {
                            ioLogPath = System.IO.Path.Combine(Logger.LogPath, "tpm_io.txt");
                        }
                        else
                        {
                            string fileName;
                            lock (this)
                            {
                                fileName = "tpm_io-" + DateTime.Now.ToString("yyyy-MMM-dd-HH");
                                if (PrevLogName == fileName)
                                {
                                    fileName += "(" + ++PrevLogInstance + ")";
                                }
                                else
                                {
                                    PrevLogName     = fileName;
                                    PrevLogInstance = 1;
                                }
                            }
                            fileName += ".txt";

#if TSS_MIN_API
                            ioLogPath = fileName;
#else
                            string docsPath = Environment.GetFolderPath(
                                Environment.SpecialFolder.MyDocuments);
                            ioLogPath = System.IO.Path.Combine(docsPath, fileName);
#endif
                        }

                        TpmIoWriter = new StreamWriter(new FileStream(ioLogPath,
                                                                      FileMode.Create));
                        Logger.WriteToLog("Dumping TPM I/O to " + ioLogPath);
                    }
                    catch (Exception e)
                    {
                        string message = "Failed to open the tpm_io.txt file for writing.\n" +
                                         "Error: " + e.Message;
                        Logger.WriteErrorToLog(message);
                    }
                }

                // get the test source code line that initiated the command
                string caller = "unknown";
#if !TSS_NO_STACK
                StackTrace   trace      = new StackTrace(true);
                StackFrame[] frames     = trace.GetFrames();
                int          frameCount = frames.Length;
                StackFrame   f          = null;
                // start at 1 to not count the currently executing function
                for (int j = 1; j < frameCount; j++)
                {
                    f = frames[j];
                    if (f.GetMethod().DeclaringType.Assembly == Logger.TestAssembly)
                    {
                        caller = f.GetFileName() + ":" + f.GetFileLineNumber();
                        break;
                    }
                }
#endif
                string commandCodeString = Enum.GetName(typeof(TpmCc), commandCode);
                string inString          = "{MALFORMED COMMAND BUFFER}";
                string outString         = "{MALFORMED RESPONSE BUFFER}";

                try { inString = CommandProcessor.ParseCommand(inBuf); }
                catch (Exception) { }
                try { outString = CommandProcessor.ParseResponse(commandCodeString, outBuf); }
                catch (Exception) { }

                lock (this)
                {
                    TpmIoWriter.WriteLine(commandCode);
                    TpmIoWriter.WriteLine(caller);

                    TpmIoWriter.WriteLine(">>>> Raw input");
                    TpmIoWriter.WriteLine(Globs.HexFromByteArray(inBuf));
                    TpmIoWriter.WriteLine(">>>> Raw output");
                    TpmIoWriter.WriteLine(Globs.HexFromByteArray(outBuf));

                    TpmIoWriter.WriteLine(">>>> Parsed input");
                    TpmIoWriter.WriteLine(inString);
                    TpmIoWriter.WriteLine(">>>> Parsed output");
                    TpmIoWriter.WriteLine(outString);

                    TpmIoWriter.WriteLine("-----------------------------------------");
                    TpmIoWriter.Flush();
                }
            }

            if (ChainedCallbacks != null)
            {
                ChainedCallbacks.PostCallback(inBuf, outBuf);
            }
        } // ICommandCallbacks.PostCallback
Ejemplo n.º 17
0
 public Tpm2GetTestResultResponse()
 {
     outData = null;
     testResult = new TpmRc();
 }
Ejemplo n.º 18
0
        public static string GetErrorString(Type inParmsType, uint resultCode, out TpmRc theMaskedError)
        {
            // There are two encoding for errors - format 0 and format 1.  Decode the error type
            var resultCodeValue = resultCode;
            bool formatOneErrorType = ((resultCodeValue & 0x80) != 0);
            uint resultCodeMask = formatOneErrorType ? 0xBFU : 0x97FU;

            // Extract the actual error code
            uint maskedErrorVal = resultCode & resultCodeMask;
            var maskedError = (TpmRc)maskedErrorVal;
            theMaskedError = maskedError;

            string errorEntity = "Unknown";
            uint errorEntityIndex = 0;
            string errorParmName = "Unknown";
            if (formatOneErrorType)
            {
                errorEntityIndex = (resultCodeValue & 0xF00U) >> 8;
                if (errorEntityIndex == 0)
                {
                    // ReSharper disable once RedundantAssignment
                    errorEntity = "Unknown";
                }
                if ((resultCodeValue & 0x40) != 0)
                {
                    errorEntity = "Parameter";
                    errorParmName = GetParmName(inParmsType, errorEntityIndex);
                }
                else
                {
                    if (errorEntityIndex >= 8)
                    {
                        errorEntityIndex -= 8;
                        errorEntity = "Session";
                    }
                    else
                    {
                        errorEntity = "handle";
                    }
                }
            }

            string errorString = String.Format(
                                               "[Code=TpmRc.{0}],[FullVal=0x{1:X},{1}]\n" +
                                               "[ErrorEntity={2}],[ParmNum={3}]" +
                                               "[ParmName={4}]",
                                               new Object[] {
                                                   maskedError.ToString(), 
                                                   //(uint)maskedError, 
                                                   resultCodeValue,
                                                   errorEntity,
                                                   errorEntityIndex,
                                                   errorParmName
                                               });
            return errorString;
        }
Ejemplo n.º 19
0
 private bool IsErrorAllowed(TpmRc rc)
 {
     return TolerateErrors ||
            AreErrorsExpected() && ExpectedResponses.Count(x => x == rc) > 0;
 }
Ejemplo n.º 20
0
        /// <summary>
        /// Dispatch a command to the underlying TPM. This method implements all
        /// significant functionality. It examines the command stream and performs
        /// (approximately) the following actions:
        /// 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 cc = commandHeader.CommandCode;

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

                if (cc == TpmCc.ContextLoad || cc == TpmCc.ContextSave)
                {
                    Debug.WriteLine("ContextLoad and ContextSave are not supported in this build");
                    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 false
                // LibTester may intentionally use invalid handles, therefore it always
                // work in the passthru mode (all correctness checks by TSS infra suppressed)
                if (!Tpm2._TssBehavior.Passthrough &&
                    (neededObjects == null || neededSessions == null))
#endif
                if (neededObjects == null || neededSessions == null)
                {
                    // 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.
                var expectedResponses = Tpm._GetExpectedResponses();
                if (!LoadEntities(neededEntities))
                {
                    throw new Exception("Failed to make space for objects or sessions");
                }
                else
                {
                    // 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);
                }

                // Re-create the command using translated object and session handles
                byte[] commandBuf = CommandProcessor.CreateCommand(commandHeader.CommandCode,
                                                                   inHandles, inSessions, commandParmsNoHandles);
                if (!Tpm2._TssBehavior.Passthrough)
                {
                    Debug.Assert(commandBuf.Length == inBuf.Length);
                }

                byte[] responseBuf;

                // TODO: Virtualize TPM2_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.
                //
                ulong firstCtxSeqNum = 0;
                while (true)
                {
                    Tpm._ExpectResponses(expectedResponses);
                    TpmDevice.DispatchCommand(active, commandBuf, out responseBuf);

                    TpmRc res = GetResultCode(responseBuf);
                    if (res == TpmRc.Success ||
                        expectedResponses != null && expectedResponses.Contains(res))
                    {
                        break;
                    }

                    if (res == TpmRc.ContextGap)
                    {
                        ulong seqNum = ShortenSessionContextGap(firstCtxSeqNum);
                        if (seqNum == 0)
                        {
                            break;  // Failed to handle CONTEXT_GAP error
                        }
                        if (firstCtxSeqNum == 0)
                        {
                            firstCtxSeqNum = seqNum;
                        }

                        //if (firstCtxSeqNum != 0)
                        //    Console.WriteLine("DispatchCommand: CONTEXT_GAP handled");
                        continue;
                    }

                    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;
                    }
                    if (!MakeSpace(slotType, neededEntities))
                    {
                        // Failed to make an object slot in the TPM
                        responseBuf = TpmErrorHelpers.BuildErrorResponseBuffer(TpmRc.Memory);
                        break;
                    }
                }

                // Parse the response from the TPM
                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);

                // In case of 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);
                outBuf = CommandProcessor.CreateResponse(resultCode, responseHandles,
                                                         responseSessions, responseParmsNoHandles);

                Debug.Assert(outBuf.Length == responseBuf.Length);
            } // lock(this)
        }
Ejemplo n.º 21
0
 /// <summary>
 /// Tpm2 will typically throw an exception if an error is returned.  If an error is expected then this command instructs the Tpm2 to 
 /// throw an exception in anything other than the expected error is returned.  This behavior is cleared when a command is invoked.
 /// </summary>
 /// <param name="errorCode"></param>
 /// <returns></returns>
 public Tpm2 _ExpectError(TpmRc errorCode)
 {
     return _ExpectResponses(errorCode);
 }
Ejemplo n.º 22
0
        public static byte[] CreateResponse(
            TpmRc responseCode,
            TpmHandle[] handles,
            SessionOut[] sessions,
            byte[] responseParmsNoHandles)
        {
            var m = new Marshaller();
            TpmSt tag = sessions.Length == 0 ? TpmSt.NoSessions : TpmSt.Sessions;

            m.Put(tag, "tag");
            m.PushLength(4);
            m.Put(responseCode, "responseCode");

            foreach (TpmHandle h in handles)
            {
                m.Put(h, "handle");
            }

            if (tag == TpmSt.Sessions)
            {
                m.Put((uint)responseParmsNoHandles.Length, "parmsLenght");
            }

            m.Put(responseParmsNoHandles, "parms");
            foreach (SessionOut s in sessions)
                m.Put(s, "session");
            m.PopAndSetLengthToTotalLength();
            return m.GetBytes();
        }
Ejemplo n.º 23
0
        public static void SplitResponse(
            byte[] response,
            uint numHandles,
            out TpmSt tag,
            out uint paramSize,
            out TpmRc responseCode,
            out TpmHandle[] handles,
            out SessionOut[] sessions,
            out byte[] responseParmsNoHandles,
            out byte[] responseParmsWithHandles)
        {
            var m = new Marshaller(response);
            tag = m.Get<TpmSt>();
            paramSize = m.Get<uint>();
            responseCode = m.Get<TpmRc>();
            // If error we only get the header
            if (responseCode != TpmRc.Success)
            {
                handles = new TpmHandle[0];
                sessions = new SessionOut[0];
                responseParmsNoHandles = new byte[0];
                responseParmsWithHandles = new byte[0];
                return;
            }

            handles = new TpmHandle[numHandles];
            for (int j = 0; j < numHandles; j++)
            {
                handles[j] = m.Get<TpmHandle>();
            }
            uint parmsEnd = m.GetValidLength();
            if (tag == TpmSt.Sessions)
            {
                var sessionOffset = m.Get<uint>();
                uint startOfParmsX = m.GetGetPos();
                parmsEnd = startOfParmsX + sessionOffset;
                m.SetGetPos(parmsEnd);
                var sessX = new List<SessionOut>();
                while (m.GetGetPos() < m.GetValidLength())
                {
                    var s = m.Get<SessionOut>();
                    sessX.Add(s);
                }
                sessions = sessX.ToArray();
                m.SetGetPos(startOfParmsX);
            }
            else
            {
                sessions = new SessionOut[0];
            }

            uint startOfParms = m.GetGetPos();
            uint parmsLength = parmsEnd - m.GetGetPos();

            // Get the response buf with no handles
            responseParmsNoHandles = new byte[parmsLength];
            Array.Copy(response, (int)startOfParms, responseParmsNoHandles, 0, (int)parmsLength);

            // Get the response buf with handles
            responseParmsWithHandles = new byte[parmsLength + numHandles * 4];
            Array.Copy(response, 10, responseParmsWithHandles, 0, (int)numHandles * 4);
            Array.Copy(response, (int)startOfParms, responseParmsWithHandles, (int)numHandles * 4, (int)parmsLength);
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Handles TPM response value.
        /// Converts the error code into a human-readable form, invokes callbacks and
        /// encapsulates error info into a .Net exception.
        /// </summary>
        /// <param name="responseTag"></param>
        /// <param name="responseParamSize"></param>
        /// <param name="resultCode"></param>
        /// <param name="inParms"></param>
        /// <returns></returns>
        // ReSharper disable once UnusedParameter.Local
        private bool ProcessError(TpmSt responseTag, uint responseParamSize,
                                  TpmRc resultCode, TpmStructureBase inParms)
        {
            string errorString;

            AssertExpectedResponsesValid();

            // Process TPM success case (both expected success, and unexpected success)
            if (resultCode == TpmRc.Success)
            {
                LastError = TpmRc.Success;
                if (IsSuccessExpected())
                {
                    return true;
                }
                // Else we have unexpectedly succeeded

                // If TolerateErrors is set, then no error indication is provided apart
                // from setting LastReponseCode (the caller must query to find that
                // the error does not match).
                if (TolerateErrors)
                {
                    return false;
                }
                // If there is an installed error handler invoke it.
                if (TheErrorHandler != null)
                {
                    TheErrorHandler(resultCode, ExpectedResponses);
                    return false;
                }
                // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                if (ExpectedResponses.Length == 1)
                {
                    errorString = string.Format("Error {0} was expected but command {1} succeeded",
                                                ExpectedResponses[0],
                                                CurrentCommand);
                }
                else
                {
                    errorString = string.Format("Errors {{{0}}} were expected but command {1} succeeded",
                                                string.Join(", ", ExpectedResponses),
                                                CurrentCommand);
                }

                _ClearCommandContext();
                throw new TssException(errorString);
            }
            // Else we have an error
            if (responseTag != TpmSt.NoSessions)
            {
                throw new Exception("Ill-formed responseTag (not NoSessions)");
            }
            if (responseParamSize != 10)
            {
                throw new Exception("Ill-formed reponseParamSize (not 10)");
            }

            // There are two encodings for errors - format 0 and format 1.
            var resultCodeValue = (uint)resultCode;
            bool formatOneErrorType = TpmErrorHelpers.IsFmt1(resultCode);

            // Extract the actual error number
            LastError = TpmErrorHelpers.ErrorNumber(resultCode);

            string errorEntity = "Unknown";
            uint errorEntityIndex = 0;
            string errorParmName = "Unknown";
            if (formatOneErrorType)
            {
                errorEntityIndex = (resultCodeValue & 0xF00U) >> 8;
                if ((resultCodeValue & 0x40) != 0)
                {
                    errorEntity = "Parameter";
                    errorParmName = GetParmName(inParms.GetType(), errorEntityIndex);
                }
                else
                {
                    if (errorEntityIndex >= 8)
                    {
                        errorEntityIndex -= 8;
                        errorEntity = "Session";
                    }
                    else
                    {
                        errorEntity = "Handle";
                    }
                }
            }
            string errorDetails = FormatString("\r\n" +
                                               "Details: \n" +
                                               "[Code=TpmRc.{0}],"+
                                               "[RawCode=0x{1:X},{1}]\n" +
                                               "[ErrorEntity={2}], [ParmNum={3}]\n" +
                                               "[ParmName={4}]",
                                               new Object[] {
                                                   LastError.ToString(), 
                                                   resultCodeValue,
                                                   errorEntity,
                                                   errorEntityIndex,
                                                   errorParmName
                                               });
            // We have found out all we can about the error.  Now process it according to the tpm context

            // AllowErrors() specifies that errors should be handled silently
            if ((OuterCommand == TpmCc.None && IsErrorAllowed(LastError)) ||
                (OuterCommand != TpmCc.None && LastError == TpmRc.Canceled))
            {
                return false;
            }

            if (OuterCommand != TpmCc.None || ExpectedResponses == null)
            {
                errorString = string.Format("Error {{{0}}} was returned for command {1}.",
                                            LastError, CurrentCommand);
            }
            else
            {
                errorString = string.Format("Error {{{0}}} was returned instead of {{{1}}} for command {2}.",
                                            LastError,
                                            string.Join(", ", ExpectedResponses),
                                            CurrentCommand);
            }

            if (AreErrorsExpected())
            {
                // We have a mismatched error. If a warning handler is installed, call it.
                if (TheWarningHandler != null)
                {
                    TheWarningHandler(errorString);
                    _ClearCommandContext();
                    return false;
                }
            }

            // Otherwise propagate the unexpected error as an exception
            _ClearCommandContext();
            errorString += errorDetails;
            throw new TpmException(resultCode, errorString);
        }
Ejemplo n.º 25
0
 public Tpm2GetTestResultResponse(Tpm2GetTestResultResponse the_Tpm2GetTestResultResponse)
 {
     if((Object) the_Tpm2GetTestResultResponse == null ) throw new ArgumentException(Globs.GetResourceString("parmError"));
     outData = the_Tpm2GetTestResultResponse.outData;
     testResult = the_Tpm2GetTestResultResponse.testResult;
 }
Ejemplo n.º 26
0
        // Send TPM-command buffer to device
        public override void DispatchCommand(
            CommandModifier mod,
            byte[] cmdBuf,
            out byte[] respBuf)
        {
            if (TctiCtx != null && TctiCtxPtr != IntPtr.Zero)
            {
                TpmRc rc = TctiCtx.transmit(TctiCtxPtr, (ulong)cmdBuf.Length, cmdBuf);
                if (rc != TpmRc.Success)
                {
                    throw new TssException($"TCTI_CTX::transmit() failed: error {rc}");
                }

                ulong bytesReceived = (ulong)_responseBuffer.Length;
                rc = TctiCtx.receive(TctiCtxPtr, ref bytesReceived, _responseBuffer, 5 * 60 * 1000);
                if (rc != TpmRc.Success)
                {
                    throw new TssException($"TCTI_CTX::receive() failed: error {rc}");
                }

                respBuf = new byte[bytesReceived];
                Array.Copy(_responseBuffer, respBuf, (int)bytesReceived);
            }
            else if (TrmDevice != null)
            {
                TrmDevice.DispatchCommand(mod, cmdBuf, out respBuf);
                return;
            }
            else if (_tpmIO != null)
            {
                _tpmIO.Write(cmdBuf, 0, cmdBuf.Length);

                int count     = 0;
                int bytesRead = 0;
                do
                {
                    bytesRead = _tpmIO.Read(_responseBuffer, 0, _responseBuffer.Length);
                    if (bytesRead > 0)
                    {
                        break;
                    }

    #if WINDOWS_UWP
                    Task.Delay(TpmIORetryBackoffTime).Wait();
    #else
                    Thread.Sleep(TpmIORetryBackoffTime);
    #endif
                    Debug.WriteLine($"TPM {_tpmDevicePath} retry {count}.");
                } while (count++ < TpmIORetryCount);

                if (bytesRead <= 0)
                {
                    throw new IOException($"No response from {_tpmDevicePath}");
                }

                respBuf = new byte[bytesRead];
                Array.Copy(_responseBuffer, respBuf, bytesRead);
            }
            else
            {
                throw new InvalidOperationException("TPM context is not initialized.");
            }
        }
Ejemplo n.º 27
0
 ///<param name = "the_outData">test result data contains manufacturer-specific information</param>
 ///<param name = "the_testResult"></param>
 public Tpm2GetTestResultResponse(
 byte[] the_outData,
 TpmRc the_testResult
 )
 {
     this.outData = the_outData;
     this.testResult = the_testResult;
 }
Ejemplo n.º 28
0
        /// <summary>
        /// This sample illustrates the use of a simple TPM policy session. The policy demands
        /// PCR 1, 2, 3 set to current values, and the command be issued at locality zero.
        /// </summary>
        static void SimplePolicy(Tpm2 tpm)
        {
            Console.WriteLine("Simple Policy sample:");

            //
            // Check if policy commands are implemented by TPM. This list
            // could include all the other used commands as well.
            // This check here makes sense for policy commands, because
            // usually a policy has to be executed in full. If a command
            // out of the chain of policy commands is not implemented in the
            // TPM, the policy cannot be satisfied.
            //
            var usedCommands = new[] { TpmCc.PolicyPCR };

            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Simple Policy sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // First read the PCR values
            //
            var pcrs = new uint[] { 1, 2, 3 };
            var sel  = new PcrSelection(TpmAlgId.Sha, pcrs);

            PcrSelection[] selOut;
            Tpm2bDigest[]  pcrValues;

            tpm.PcrRead(new[] { sel }, out selOut, out pcrValues);

            Console.WriteLine("PCR Selections:\n");
            foreach (PcrSelection s in selOut)
            {
                Console.WriteLine(s.ToString());
            }

            Console.WriteLine("PCR Values:\n");
            foreach (var v in pcrValues)
            {
                Console.WriteLine(v.ToString());
            }

            //
            // Save the current PCR values in a convenient data structure
            //
            var expectedPcrVals = new PcrValueCollection(selOut, pcrValues);

            //
            // Tpm2Lib encapsulates a set of policy assertions as the PolicyTree class.
            //
            var policy = new PolicyTree(TpmAlgId.Sha256);

            //
            // Set the policy: Locality AND PolicyPcr. This form of CreatePOlicy
            // only creates a single chain. Note that all well-formed policy chains
            // must have leaf identifiers. Leaf identifiers are just strings that
            // are unique in a policy so that the framework can be told what
            // chain to evaluate.
            //
            policy.Create(
                new PolicyAce[]
            {
                new TpmPolicyPcr(expectedPcrVals),
                "leaf"
            }
                );

            //
            // Ask Tpm2Lib for the expected policy-hash for this policy
            //
            TpmHash expectedPolicyHash = policy.GetPolicyDigest();

            //
            // Create a sealed primary object with the policy-hash we just calculated
            //
            var       dataToSeal = new byte[] { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
            TpmHandle primHandle = CreateSealedPrimaryObject(tpm,
                                                             dataToSeal,
                                                             null,
                                                             expectedPolicyHash.HashData);
            //
            // Create an actual TPM policy session to evaluate the policy
            //
            AuthSession session = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);

            //
            // Run the policy on the TPM
            //
            session.RunPolicy(tpm, policy, "leaf");

            //
            // Unseal the object
            //
            byte[] unsealedData = tpm[session].Unseal(primHandle);
            Console.WriteLine("Unsealed data: " + BitConverter.ToString(unsealedData));

            //
            // Change a PCR and make sure that the policy no longer works
            //
            var nullAuth = new AuthValue();

            tpm[nullAuth].PcrEvent(TpmHandle.Pcr(3), new byte[] { 1, 2, 3 });
            tpm.PolicyRestart(session.Handle);

            //
            // Run the policy again - an error will be returned
            //
            TpmRc policyError = session.RunPolicy(tpm, policy, null, true);

            //
            // And the session will be unusable
            //
            unsealedData = tpm[session]._ExpectError(TpmRc.PolicyFail).Unseal(primHandle);

            //
            // Clean up
            //
            tpm.FlushContext(session.Handle);
            tpm.FlushContext(primHandle);
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Create a 10 byte error response that matches TPM error responses.
 /// </summary>
 /// <param name="errorCode"></param>
 /// <returns></returns>
 private byte[] FormatError(TpmRc errorCode)
 {
     var m = new Marshaller();
     m.Put(TpmSt.NoSessions, "");
     m.Put((uint)10, "");
     m.Put(errorCode, "");
     return m.GetBytes();
 }
Ejemplo n.º 30
0
 public TpmException(TpmRc rawResponse, string errorDescription)
     : base(errorDescription)
 {
     ErrorString = TpmErrorHelpers.ErrorNumber(rawResponse).ToString();
     RawResponse = rawResponse;
 }
Ejemplo n.º 31
0
        public static TpmRc GetBaseErrorCode(TpmRc resultCode)
        {
            var resultCodeValue = (uint)resultCode;
            bool formatOneErrorType = ((resultCodeValue & 0x80) != 0);
            uint resultCodeMask = formatOneErrorType ? 0xBFU : 0x97FU;

            // Extract the actual error code
            uint maskedErrorVal = (uint)resultCode & resultCodeMask;
            var maskedError = (TpmRc)maskedErrorVal;
            return maskedError;
        }
Ejemplo n.º 32
0
 public TpmException(TpmRc rawResponse, string errorDescription)
     : base(errorDescription)
 {
     ErrorString = TpmErrorHelpers.ErrorNumber(rawResponse).ToString();
     RawResponse = rawResponse;
 }
Ejemplo n.º 33
0
        } // ProcessResponseSessions

        private void ValidateResponseSessions(
            TpmHandle[] outHandles,
            SessionOut[] outSessions,
            TpmCc commandCode,
            TpmRc responseCode,
            byte[] outParmsNoHandles)
        {
            int numSessions = Sessions.Length;
            if (numSessions == 0 || numSessions > outSessions.Length)
            {
                return;
            }

            int outSessionCount = 0;
            foreach (SessionBase s in Sessions)
            {
                SessionOut outSess = outSessions[outSessionCount++];
                if (s is Pwap)
                {
                    if (outSess.nonceTpm.Length != 0)
                    {
                        throw new TpmFailure("PWAP returned non-empty nonce");
                    }
                    if (outSess.auth.Length != 0)
                    {
                        throw new TpmFailure("PWAP returned non-empty auth value");
                    }
                }
                // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull
                else if (s is AuthSession)
                {
                    var sess = s as AuthSession;

                    byte[] parmsHash = GetExpectedResponseHash(sess.AuthHash, outParmsNoHandles, commandCode, responseCode);
                    byte[] expectedHmac = sess.GetAuthHmac(parmsHash, Direction.Response);

                    if (outSess.auth.Length != 0)
                    {
                        if (!Globs.ArraysAreEqual(outSess.auth, expectedHmac))
                        {
                            throw new TpmFailure("Bad response HMAC");
                        }
                    }
                }
                else
                {
                    throw new TpmFailure("Invalid response session type");
                }
            }
        } // ValidateResponseSessions
Ejemplo n.º 34
0
 public Tpm2GetTestResultResponse()
 {
     outData = new byte[0];
     testResult = new TpmRc();
 }
Ejemplo n.º 35
0
        /// <summary>
        /// This sample demonstrates the creation and use of a storage root key that
        /// behaves like the Storage Root Key (SRK) defined in TPM1.2.
        /// To do this we need to create a new primary, and then use EvictControl
        /// to make it NV-resident.
        /// </summary>
        /// <param name="tpm">Reference to TPM object</param>
        static void StorageRootKey(Tpm2 tpm)
        {
            //
            // This template asks the TPM to create an 2048 bit RSA storage key
            // with an associated AES key for symmetric data protection.  The term
            // "SRKs" is not used in TPM2.0, but we use it here to
            // not
            //
            var srkTemplate = new TpmPublic(TpmAlgId.Sha1,                                 // Name algorithm
                                            ObjectAttr.Restricted |                        // Storage keys must be restricted
                                            ObjectAttr.Decrypt |                           // Storage keys are Decrypt keys
                                            ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable (like 1.2)
                                            ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                            new byte[0],                                   // No policy
                                            new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                         new NullAsymScheme(),             // No signature
                                                         2048, 0),                         // 2048-bit RSA
                                            new Tpm2bPublicKeyRsa());
            //
            // Authorization for the key we are about to create
            //
            var srkAuth = new byte[0];

            AuthValue childAuthVal = AuthValue.FromRandom(8);
            TssObject swKey        = TssObject.CreateStorageParent(srkTemplate, childAuthVal);

            TpmPublic    srkPublic;
            CreationData srkCreationData;
            TkCreation   srkCreationTicket;

            byte[] srkCreationHash;

            //
            // Ask the TPM to create a new primary RSA/AES primary storage key
            //
            TpmHandle keyHandle = tpm[_ownerAuth].CreatePrimary(
                TpmHandle.RhOwner,                          // In the owner-hierarchy
                new SensitiveCreate(srkAuth, new byte[0]),  // With this auth-value
                srkTemplate,                                // Describes key
                new byte[0],                                // For creation ticket
                new PcrSelection[0],                        // For creation ticket
                out srkPublic,                              // Out pubKey and attrs
                out srkCreationData,                        // Not used here
                out srkCreationHash,                        //      Ibid
                out srkCreationTicket);                     //      Ibid

            //
            // print out text-versions of the public key just created
            //
            Console.WriteLine("New SRK public key\n" + srkPublic.ToString());

            //
            // The caller provides the handle for persistent keys
            //
            TpmHandle srkHandle = TpmHandle.Persistent(0x5000);

            //
            // Ae will make the "SRK" persistent in an NV-slot, so clean up anything
            // that is already there
            //
            tpm[_ownerAuth]._AllowErrors().EvictControl(TpmHandle.RhOwner, srkHandle, srkHandle);
            TpmRc lastError = tpm._GetLastResponseCode();

            //
            // Make the SRK NV-resident
            //
            tpm[_ownerAuth].EvictControl(TpmHandle.RhOwner, keyHandle, srkHandle);

            Console.WriteLine("SRK is persistent now.");
        }