Exemplo n.º 1
0
        public void Apply(Stack <Operand> operands)
        {
            if (Op == OpCode.Sizeof)
            {
                operands.Push((int)TpmTypes.Lookup(operands.Pop().Value).GetSize());
                return;
            }
            Operand rhs = operands.Pop();
            Operand lhs = operands.Pop();

            operands.Push(Apply(lhs.NumericValue, rhs.NumericValue));
        }
Exemplo n.º 2
0
        static void FixEnumTypeCollisions()
        {
            List <TpmStruct> toAdd = new List <TpmStruct>();

            for (int j = 0; j < TpmTypes.TheTypes.Count; j++)
            {
                TpmType tp = TpmTypes.TheTypes[j];
                if (!(tp is TpmUnion &&
                      tp.SpecName.IsOneOf(new string[] { "TPMU_PUBLIC_ID", "TPMU_SIGNATURE" })))
                {
                    continue;
                }

                // See if we have collisions.
                // Collided member types are converted into derived types by adding selector name to the base
                // type name. Struct that became a base one inherits from all the union interfaces, while
                // a derived struct only inherits from the base one and implements interfaces of the unions,
                // of which it is a member.
                // Base class B provides a union interface implementation only if this union contains a member
                // of type B. If a union U contains members of types derived from B, then B's implementation
                // of U's interface methods just throws NotImplementedException exception.
                TpmUnion u    = (TpmUnion)tp;
                var      dict = new Dictionary <string, UnionMember>();
                foreach (UnionMember m in u.Members)
                {
                    string typeName     = m.Type.SpecName;
                    string selectorName = m.SelectorValue.Name;
                    if (dict.ContainsKey(typeName))
                    {
                        // Collision detected.
                        Debug.WriteLine("Collision in {0} [{1}] -- {2}", u.Name, selectorName, typeName);

                        TpmStruct baseStruct = (TpmStruct)TpmTypes.Lookup(typeName);
                        AddDerivedStruct(baseStruct, m, u,
                                         "Auto-derived from " + baseStruct.SpecName +
                                         " to provide unique GetUnionSelector() implementation");
                        if (dict[typeName] != null)
                        {
                            // Create the derived structure for the first occurrence.
                            AddDerivedStruct(baseStruct, dict[typeName], u);
                            // But do it only once...
                            dict[typeName] = null;
                        }
                    }
                    else
                    {
                        dict.Add(typeName, m);
                    }
                }
            }
        } // FixEnumTypeCollisions()
Exemplo n.º 3
0
 static void FixStructsWithEncryptedBuffer()
 {
     foreach (var typeName in StructsWithEncryptedBuffer)
     {
         var s = (TpmStruct)TpmTypes.Lookup(typeName);
         var f = s.Fields[3];
         Debug.Assert(f.Name.StartsWith("enc"));
         Debug.Assert(f.MarshalType == MarshalType.VariableLengthArray);
         f.MarshalType = MarshalType.EncryptedVariableLengthArray;
         Debug.Assert(f.SizeTagField != null);
         s.Fields[2] = f;
         s.Fields.RemoveAt(3);
     }
 }
Exemplo n.º 4
0
        public static List <TpmNamedConstant> GetBifieldElements(TpmBitfield bf)
        {
            var elements = new List <TpmNamedConstant>();

            foreach (var b in bf.Elements)
            {
                if (b.StartBit == b.EndBit)
                {
                    AddBitfieldElt(elements, b.TranslatedName, 1 << b.StartBit, b.Comment, b.OldStyleName);
                }
                else // multibit members of a bitfield
                {
                    string typeName = b.Name;
                    if (TpmTypes.Contains(typeName))
                    {
                        // Type typeName defines allowed values for this multi-bit field
                        var e = TpmTypes.Lookup(typeName) as TpmEnum;
                        if (e != null)
                        {
                            foreach (var v in e.Members)
                            {
                                AddBitfieldElt(elements, v.Name, v.NumericValue << b.EndBit, v.Comment);
                            }
                        }
                    }

                    // Multi-bit bitfield 'name' is additionally represented by several enumerators:
                    //   name_BIT_MASK - bit mask selecting all bits of the field
                    //   name_BIT_OFFSET - offset of the field's low order bit
                    //   name_BIT_LENGTH - number of bits in the field
                    string nameBase = b.Name.Contains("_") ? TargetLang.NameToDotNet(b.Name) : b.Name;
                    int    len      = b.StartBit - b.EndBit + 1;
                    var    suff     = TargetLang.DotNet ? new string[] { "BitMask", "BitOffset", "BitLength" }
                                                 : new string[] { "_BIT_MASK", "_BIT_OFFSET", "_BIT_LENGTH" };
                    AddBitfieldElt(elements, nameBase + suff[0], ((1 << len) - 1) << b.EndBit, b.Comment, null, true);
                    AddBitfieldElt(elements, nameBase + suff[1], b.EndBit, null, null, true);
                    AddBitfieldElt(elements, nameBase + suff[2], len, null, null, true);
                    if (TargetLang.DotNet && bf.Name == "LocalityAttr")
                    {
                        // For backward compatibility
                        for (int i = 0; i < len; ++i)
                        {
                            AddBitfieldElt(elements, $"{nameBase}Bit{i}", 1 << (b.EndBit + i), "", null, true);
                        }
                    }
                } // multibit members of a bitfield
            }
            return(elements);
        }
Exemplo n.º 5
0
        public static void DoFixups()
        {
            // Many TPM structs represent a length-prefixed array or structure.
            // When such struct is a fields of another (enclosing) structure, get rid of the struct
            // wrapper and place the payload array/struct directly as the member of the enclosing struct.
            FixTpm2bStructs();
            FlattenTaggedStructures();
            FixStructsWithEncryptedBuffer();
            FlattenLists();

            // This command allows session based encryption.
            foreach (var s in TpmTypes.Get <TpmStruct>().Where(s => s.IsCmdStruct()))
            {
                if (s.Fields.Count > s.NumHandles &&
                    s.Fields[s.NumHandles].MarshalType.IsOneOf(MarshalType.ArrayCount, MarshalType.LengthOfStruct))
                {
                    // This command allows session based encryption.
                    Debug.Assert(s.Fields.Count > s.NumHandles + 1);
                    var sizeField  = s.Fields[s.NumHandles];
                    var sizedField = s.Fields[s.NumHandles + 1];
                    var cmdInfo    = s.Info as CmdStructInfo;
                    cmdInfo.SessEncSizeLen = sizeField.Type.GetSize();
                    cmdInfo.SessEncValLen  = sizeField.MarshalType == MarshalType.LengthOfStruct
                                          ? 1 : sizedField.Type.GetSize();
                }
            }

            TpmStruct[] symDefs = { (TpmStruct)TpmTypes.Lookup("TPMT_SYM_DEF"),
                                    (TpmStruct)TpmTypes.Lookup("TPMT_SYM_DEF_OBJECT") };
            var         fieldTypes = new string[] { "TPM_ALG_ID", "UINT16", "TPM_ALG_ID" };

            Debug.Assert(symDefs[0].Fields.Count == symDefs[1].Fields.Count &&
                         symDefs[0].Fields.Count == fieldTypes.Length);

            for (int i = 0; i < fieldTypes.Length; ++i)
            {
                foreach (var sd in symDefs)
                {
                    sd.Fields[i].MarshalType = MarshalType.Normal;
                    sd.Fields[i].Type        = TpmTypes.Lookup(fieldTypes[i]);
                }
            }
            symDefs[0].Fields[0].Attrs = symDefs[1].Fields[0].Attrs |= StructFieldAttr.TermOnNull;

            FixEnumTypeCollisions();
        }
Exemplo n.º 6
0
        static void TweakSymDefStructFieldNames(bool dotNet)
        {
            var sd  = (TpmStruct)TpmTypes.Lookup("TPMT_SYM_DEF");
            var sdo = (TpmStruct)TpmTypes.Lookup("TPMT_SYM_DEF_OBJECT");

            for (int i = 0; i < sd.Fields.Count; ++i)
            {
                Debug.Assert(sd.Fields[i].Name == sdo.Fields[i].Name);
                if (dotNet)
                {
                    sd.Fields[i].Name = sdo.Fields[i].Name = Helpers.Capitalize(sd.Fields[i].Name);
                }
                else
                {
                    sd.Fields[i].Name = sdo.Fields[i].Name = sd.Fields[i].Name.ToLower();
                }
            }
        }
Exemplo n.º 7
0
        public static void AddDerivedStruct(TpmStruct baseStruct, UnionMember curMember,
                                            TpmUnion curUnion, string comment = null)
        {
            string baseTypeName = baseStruct.SpecName;
            string newTypeName  = baseTypeName + "_" + RemoveEnumPrefix(curMember.SelectorValue.SpecName,
                                                                        curMember.SelectorValue.EnclosingEnum.SpecName);

            if (!TpmTypes.Contains(newTypeName))
            {
                var newStruct = new TpmStruct(newTypeName,
                                              comment ?? "Auto-derived from " + baseTypeName,
                                              baseStruct);
                TpmTypes.Add(newStruct);
            }

            var s = (TpmStruct)TpmTypes.Lookup(newTypeName);

            s.RegisterContainingUnion(curUnion);
            // Fix up the union field
            curMember.Type = s;
        }
Exemplo n.º 8
0
        /// <summary> Makes constant values specified as arithmetic expressions comply with the current
        /// langauge syntax (adds enum type name qualifiers and type casts when necessary, eliminates
        /// sizeof() operators when unsupported, etc.) </summary>
        public static string TranslateConstExpr(TpmConstExpr ce, TpmEnum enclosingEnum = null)
        {
            var nameDelimiters = new char[] { ' ', ',', '{', '}',
                                              '(', ')', '+', '-', '<', '*', '/', '`' };
            string suffix = TargetLang.Java ? ".toInt()" : "";
            string expr   = ce.Expr;

            string[] tokens         = expr.Split(nameDelimiters);
            bool     sizeofOccurred = false,
                     commentNeeded  = false;

            foreach (string token in tokens)
            {
                if (token.Length == 0)
                {
                    continue;
                }
                if (token == "sizeof")
                {
                    Debug.Assert(!sizeofOccurred);
                    sizeofOccurred = true;
                    continue;
                }
                if (Expression.IsNumber(token))
                {
                    if (token == "00")
                    {
                        Debug.Assert(expr == token);
                        expr = "0";
                    }
                    Debug.Assert(!sizeofOccurred);
                    continue;
                }

                TpmNamedConstant nc = TpmTypes.LookupConstant(token);
                if (enclosingEnum != null && nc?.EnclosingEnum == enclosingEnum)
                {
                    // Members of the enum being processed do not need to be qualified
                    Debug.Assert(token == nc.SpecName);
                    expr = expr.Replace(token, nc.Name + suffix);
                    continue;
                }
                if (!TpmTypes.ContainsConstant(token))
                {
                    // This must be a type name operand of sizeof()
                    Debug.Assert(sizeofOccurred);
                    sizeofOccurred = false;
                    TpmType t = TpmTypes.Lookup(token);
                    if (t is TpmStruct || TargetLang.IsOneOf(Lang.Java, Lang.JS, Lang.Py))
                    {
                        string sizeofExpr = "sizeof(" + token + ")";
                        Debug.Assert(expr.Contains(sizeofExpr));
                        commentNeeded = TargetLang.Py;
                        string origExpr = TargetLang.Py ? "" : $"/*{sizeofExpr}*/";
                        expr = expr.Replace(sizeofExpr, $"0x{t.GetSize():X}{origExpr}");
                    }
                    else if (TargetLang.DotNet)
                    {
                        expr = expr.Replace(token, t.StripTypedefs().Name);
                    }
                }
                else
                {
                    nc = TpmTypes.LookupConstant(token);
                    var translated = nc.QualifiedName + suffix;
                    if (!TargetLang.IsGenerated(nc.EnclosingEnum))
                    {
                        translated = nc.NumericValue.ToString();
                        if (!TargetLang.Py)
                        {
                            translated += "/*" + token + "*/";
                        }
                        else
                        {
                            commentNeeded = true;
                        }
                    }
                    expr = expr.Replace(token, translated);
                }
            } // foreach token

            if (TargetLang.DotNet && expr.Contains("<<"))
            {
                // Shift operator in .Net requires right operand of type 'int' and unsigned left one.
                int curPos = 0;
                expr = expr.Replace(" << ", "<<");
                do
                {
                    int pos = expr.IndexOf("<<", curPos);
                    if (pos == -1)
                    {
                        break;
                    }
                    curPos = pos + 2 + 6; // Add sizes of "<<" and "(uint)"
                    while (char.IsLetterOrDigit(expr[--pos]) || expr[pos] == '.')
                    {
                        continue;
                    }
                    expr = expr.Insert(pos + 1, "(uint)");
                } while (true);
                expr = expr.Replace("<<", " << (int)");
            }

            if (commentNeeded)
            {
                expr += $"  # {ce.Expr}";
            }
            return(expr);
        } // TranslateConstExpr()
Exemplo n.º 9
0
        /// <remarks> If this method goes into an infinite loop, this usually means that
        /// the Part 2, or  Vendor Specicfic part of the TPM 2.0 spec added a new constant
        /// value defined not in a table, but rather in a NOTE. In this case this definition
        /// needs to be manually added into the ImplementationConstants array. </remarks>
        public static int Eval(string val)
        {
            if (IsNumber(val))
            {
                return(Convert.ToInt32(val, val.ToLower().StartsWith("0x") ? 16 : 10));
            }
            if (TpmTypes.ContainsConstant(val))
            {
                return(TpmTypes.LookupConstant(val).NumericValue);
            }

            var tokens = Tokenize(val);
            var ops    = new Stack <Operator>();
            var values = new Stack <Operand>();

            for (int i = 0; i < tokens.Length; ++i)
            {
                var tok = tokens[i];

                if (tok is Operand)
                {
                    values.Push((Operand)tok);
                    continue;
                }
                var op = (Operator)tok;
                if (op.Is(OpCode.Sizeof))
                {
                    Debug.Assert(tokens.Length > i + 2);
                    string typeName = (tokens[i + 2] as Operand).Value;
                    Debug.Assert(TpmTypes.Contains(typeName));
                    var e = TpmTypes.Lookup(typeName);
                    // Workaround for _PRIVATE max size
                    values.Push(new Operand(typeName == "_PRIVATE" ? 1024 : e.GetSize()));
                    i += 3;
                    continue;
                }
                if (ops.Count == 0 || op.Is(OpCode.LeftParen) || ops.Peek() < op)
                {
                    Debug.Assert(!op.Is(OpCode.RightParen));
                    ops.Push(op);
                    continue;
                }
                else
                {
                    do
                    {
                        Operator prevOp = ops.Pop();
                        if (prevOp.Is(OpCode.LeftParen))
                        {
                            Debug.Assert(op.Is(OpCode.RightParen));
                            break;
                        }
                        prevOp.Apply(values);
                    }while (ops.Count > 0 && ops.Peek() >= op);

                    if (!op.Is(OpCode.RightParen))
                    {
                        ops.Push(op);
                    }
                }
            }
            while (ops.Count > 0)
            {
                ops.Pop().Apply(values);
            }
            Debug.Assert(values.Count == 1);
            int res = values.Pop().NumericValue;

            return(res);
        }
Exemplo n.º 10
0
 public TpmField(string fieldTypeName, string fieldName, string comment)
 {
     Type    = TpmTypes.Lookup(fieldTypeName);
     Name    = fieldName;
     Comment = comment;
 }
Exemplo n.º 11
0
 public TpmType(string specName, string comment = "", string underlyingType = null, int size = 0)
 {
     Init(specName, comment, size,
          underlyingType == null ? null : TpmTypes.Lookup(underlyingType));
 }
Exemplo n.º 12
0
 internal static TpmStruct GetRespStruct(TpmStruct req)
 {
     return((TpmStruct)TpmTypes.Lookup(req.SpecName.Replace("_REQUEST", "Response").Substring(5)));
 }
Exemplo n.º 13
0
        void GenHandleTable()
        {
            Write("//-----------------------------------------------------------------------------");
            Write("//------------------------- COMMAND INFO -----------------------------------");
            Write("//-----------------------------------------------------------------------------");
            Write("public static class CommandInformation");
            TabIn("{");
            Write("public static CommandInfo[] Info = new CommandInfo[]");
            TabIn("{");
            bool printComma = false;

            foreach (var req in TpmTypes.Get <TpmStruct>().Where(s => s.Info.IsRequest()))
            {
                TpmStruct resp          = GetRespStruct(req);
                string    cmdName       = GetCommandName(req);
                string    transCmdName  = TargetLang.TypeToDotNet(cmdName);
                string    reqStructName = "Tpm2" + transCmdName + "Request";

                // encryptable parms?
                ParmCryptInfo cryptInfo = 0;

                if (req.Fields.Count > req.NumHandles)
                {
                    // find the first field that is not a handle
                    StructField parm0 = req.Fields[req.NumHandles];
                    if (parm0.MarshalType.IsOneOf(MarshalType.LengthOfStruct, MarshalType.ArrayCount))
                    {
                        string typeName = parm0.Type.StripTypedefs().Name;
                        if (typeName == "uint")
                        {
                            cryptInfo |= ParmCryptInfo.EncIn4;
                        }
                        else if (typeName == "ushort")
                        {
                            cryptInfo |= ParmCryptInfo.Enc2In2;
                        }
                    }
                }
                if (resp.Fields.Count > resp.NumHandles)
                {
                    // find the first field that is not a handle
                    StructField parm0 = resp.Fields[resp.NumHandles];
                    if (parm0.MarshalType.IsOneOf(MarshalType.LengthOfStruct, MarshalType.ArrayCount))
                    {
                        string typeName = parm0.Type.StripTypedefs().Name;
                        if (typeName == "uint")
                        {
                            cryptInfo |= ParmCryptInfo.DecOut4;
                        }
                        else if (typeName == "ushort")
                        {
                            cryptInfo |= ParmCryptInfo.DecOut2;
                        }
                    }
                }

                string handleTypeNames = "";
                // types of input handles
                if (req.NumHandles > 0)
                {
                    for (int j = 0; j < req.NumHandles; j++)
                    {
                        StructField hField         = req.Fields[j];
                        string      origHandleType = hField.Type.SpecName;
                        handleTypeNames += origHandleType + " ";
                        TpmType tpx = TpmTypes.Lookup(origHandleType);
                    }
                }
                handleTypeNames = handleTypeNames.TrimEnd(new char[] { ' ' });
                handleTypeNames = "\"" + handleTypeNames + "\"";

                string respTypeId = !resp.Implement ? "EmptyResponse"
                                  : resp.Name;

                WriteComma(ref printComma);
                Write($"new CommandInfo(TpmCc.{transCmdName}, {req.NumHandles}, {resp.NumHandles}, {req.NumAuthHandles}, " +
                      $"typeof({reqStructName}), typeof({respTypeId}), {(uint)cryptInfo}, {handleTypeNames})", false);
            }
            TabOut("};");
            TabOut("}");
        }