public static bool CrackCommand()

in TPM Parser/Tpm2Lib/Tpm2.cs [736:845]


        public static bool CrackCommand(
            byte[] command,
            out CommandHeader header,
            out TpmHandle[] handles,
            out SessionIn[] sessions,
            out byte[] commandParms)
        {
            var m = new Marshaller(command);
            header = m.Get<CommandHeader>();
            CommandInfo commandInfo = Tpm2.CommandInfoFromCommandCode(header.CommandCode);
            if (header.Tag == TpmSt.Null)
            {
                // A diagnostics command. Pass through unmodified
                handles = null;
                sessions = null;
                commandParms = null;
                return false;
            }
            handles = new TpmHandle[commandInfo.HandleCountIn];
            for (int j = 0; j < handles.Length; j++)
            {
                handles[j] = m.Get<TpmHandle>();
            }
            // Note sessions are only present if the command tag indicates sessions
            if (header.Tag == TpmSt.Sessions)
            {
                uint sessionLength = m.Get<uint>();
                uint sessionStart = m.GetGetPos();
                uint sessionEnd = sessionStart + sessionLength;
                // if bytes between m.GetGetPos() and sessionEnd are all 0xAA this is
                // a censored session.
                byte[] sessionArray = m.GetNBytes((int)sessionLength);
                if (Array.TrueForAll<byte>(sessionArray, element => { return element == 0xAA; }))
                {
                    // yes, censored buffer, try to replace with intelligent guess
                    // authorization field consist of:
                    //  TPM20_HANDLE Handle;  // authHandle: TPM_RH_PW
                    //  UINT16 Nonce2B;       // TPM2B_NONCE
                    //  UINT8 Session;        // TPMA_SESSION
                    //  UINT16 Auth2B;        // TPM2B_AUTH
                    // to make intelligent guess about size of nonce and auth,
                    // subtract constant sized field (9 bytes). Nonce is usually
                    // a hash, so it should be either 20, 32, 48, or 64 bytes.
                    // the auth value would make up the rest, but also usually
                    // be the result of a hash operation.
                    sessionLength = sessionLength - sizeof(uint) - sizeof(ushort) - sizeof(byte) - sizeof(ushort);
                    ushort nonceSize;
                    if (sessionLength/2 == TpmHash.DigestSize(TpmAlgId.Sha1) ||
                        sessionLength/2 == TpmHash.DigestSize(TpmAlgId.Sha256) ||
                        sessionLength/2 == TpmHash.DigestSize(TpmAlgId.Sha384) ||
                        sessionLength/2 == TpmHash.DigestSize(TpmAlgId.Sha512))
                    {
                        nonceSize = (ushort)(sessionLength / 2);
                    }
                    else if (sessionLength >= TpmHash.DigestSize(TpmAlgId.Sha512))
                    {
                        nonceSize = TpmHash.DigestSize(TpmAlgId.Sha512);
                    }
                    else if (sessionLength >= TpmHash.DigestSize(TpmAlgId.Sha384))
                    {
                        nonceSize = TpmHash.DigestSize(TpmAlgId.Sha384);
                    }
                    else if (sessionLength >= TpmHash.DigestSize(TpmAlgId.Sha256))
                    {
                        nonceSize = TpmHash.DigestSize(TpmAlgId.Sha256);
                    }
                    else if (sessionLength >= TpmHash.DigestSize(TpmAlgId.Sha1))
                    {
                        nonceSize = TpmHash.DigestSize(TpmAlgId.Sha1);
                    }
                    else
                    {
                        // 0 <= sessionLength < size of SHA1 digest
                        nonceSize = (ushort)sessionLength;
                    }
                    // marshal nonceSize
                    sessionArray[4] = (byte)(nonceSize >> 8);
                    sessionArray[5] = (byte)nonceSize;
                    // marshall session
                    int sessionOffset = sizeof(uint) + sizeof(ushort) + nonceSize;
                    sessionArray[sessionOffset] = 0;
                    // marshall authSize
                    ushort authSize = (ushort)(sessionLength - nonceSize);
                    sessionArray[sessionOffset + 1] = (byte)(authSize >> 8);
                    sessionArray[sessionOffset + 2] = (byte)authSize;

                    m.SetBytes(sessionArray, sessionStart);
                }
                m.SetGetPos(sessionStart);
                var inSessions = new List<SessionIn>();
                while (m.GetGetPos() < sessionEnd)
                {
                    var s = m.Get<SessionIn>();
                    inSessions.Add(s);
                }
                sessions = inSessions.ToArray();
            }
            else
            {
                sessions = new SessionIn[0];
            }
            // And finally parameters
            commandParms = m.GetArray<byte>((int)(m.GetValidLength() - m.GetGetPos()));
            if (m.GetValidLength() != header.CommandSize)
            {
                Globs.Throw("Command length in header does not match input byte-stream");
                return false;
            }
            return true;
        }