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)); }
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()
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); } }
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); }
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(); }
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(); } } }
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; }
/// <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()
/// <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); }
public TpmField(string fieldTypeName, string fieldName, string comment) { Type = TpmTypes.Lookup(fieldTypeName); Name = fieldName; Comment = comment; }
public TpmType(string specName, string comment = "", string underlyingType = null, int size = 0) { Init(specName, comment, size, underlyingType == null ? null : TpmTypes.Lookup(underlyingType)); }
internal static TpmStruct GetRespStruct(TpmStruct req) { return((TpmStruct)TpmTypes.Lookup(req.SpecName.Replace("_REQUEST", "Response").Substring(5))); }
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("}"); }