public PolicyAce AddNextAce(PolicyAce nextAce) { if (this is TpmPolicyOr) { Globs.Throw<ArgumentException>("AddNextAce: Do not call AddNextAce for an OR node: Use AddPolicyBranch instead."); } if (NextAce != null) { Globs.Throw<ArgumentException>("AddNextAce: Policy ACE already has a child"); } if (!String.IsNullOrEmpty(BranchIdentifier)) { if (String.IsNullOrEmpty(nextAce.BranchIdentifier)) { nextAce.BranchIdentifier = BranchIdentifier; } else if (nextAce.BranchIdentifier != BranchIdentifier) { Globs.Throw<ArgumentException>("AddNextAce: Policy ACE with non-empty BranchName can only have a child with the same or no branch name"); } BranchIdentifier = ""; } NextAce = nextAce; NextAce.PreviousAce = this; return nextAce; }
private PolicyAce GetNodeIdInternal(PolicyAce n, string nodeId) { if (n.NodeId == nodeId) { return(n); } // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (n is TpmPolicyOr) { foreach (PolicyAce a in ((TpmPolicyOr)n).PolicyBranches) { PolicyAce ace = GetNodeIdInternal(a, nodeId); if (ace != null) { return(ace); } } } if (n.NextAce != null) { return(GetNodeIdInternal(n.NextAce, nodeId)); } return(null); }
/// <summary> /// Create a simple policy chain (no ORs). /// </summary> public void Create(PolicyAce[] singlePolicyChain) { // ReSharper disable once RedundantExplicitArraySize var arr = new PolicyAce[1][] { singlePolicyChain }; CreateNormalizedPolicy(arr); }
// Returns the linked list as an array internal static PolicyAce[] GetArrayRepresentation(PolicyAce head) { int numElems = 0; PolicyAce next = head; do { if (next == null) { break; } next = next.NextAce; numElems++; } while (true); var arr = new PolicyAce[numElems]; int count = 0; next = head; do { if (next == null) { break; } arr[count] = next; next = next.NextAce; count++; } while (true); return(arr); }
/// <summary> /// Load a policy from a stream (MemoryStream, FileStream) in the specified format /// </summary> /// <param name="format"></param> /// <param name="sourceStream"></param> public void Deserialize(PolicySerializationFormat format, Stream sourceStream) { TpmPolicy pol = null; switch (format) { case PolicySerializationFormat.Xml: { var ser = new DataContractSerializer(typeof(TpmPolicy)); pol = (TpmPolicy)ser.ReadObject(sourceStream); break; } case PolicySerializationFormat.Json: { var ser = new DataContractJsonSerializer(typeof(TpmPolicy)); pol = (TpmPolicy)ser.ReadObject(sourceStream); break; } default: Globs.Throw <ArgumentException>("PolicyTree.Deserialize: Unknown format " + format); return; } pol.AssociatedPolicy = this; PolicyRoot = pol.PolicyRoot; }
internal static PolicyAce FromArrayRepresentation(PolicyAce[] arr, PolicyTree policy) { PolicyAce root = null; PolicyAce current = null; PolicyAce previous = null; // Makes a doubly linked list from an array foreach (PolicyAce a in arr) { // All ACEs have an associated policy tree a.AssociatedPolicy = policy; // we need a link to previous if (previous != null) { a.PreviousAce = previous; } // previous needs a link to us if (current != null) { current.NextAce = a; } current = a; if (root == null) { root = current; } previous = a; } return(root); }
public PolicyAce AddNextAce(PolicyAce nextAce) { if (this is TpmPolicyOr) { Globs.Throw <ArgumentException>("AddNextAce: Do not call AddNextAce for " + "an OR node. Use AddPolicyBranch instead."); } if (NextAce != null) { Globs.Throw <ArgumentException>("AddNextAce: Policy ACE already has a child"); } if (!String.IsNullOrEmpty(BranchID)) { if (String.IsNullOrEmpty(nextAce.BranchID)) { nextAce.BranchID = BranchID; } else if (nextAce.BranchID != BranchID) { Globs.Throw <ArgumentException>( "AddNextAce: Policy ACE with non-empty BranchName " + "can only have a child with the same or no branch name"); } BranchID = ""; } NextAce = nextAce; NextAce.PreviousAce = this; return(nextAce); }
public PolicyTree InsertPolicyRoot(PolicyAce newRoot) { if (PolicyRoot != null) newRoot.AddNextAce(PolicyRoot); PolicyRoot = newRoot; return this; }
public PolicyTree InsertPolicyRoot(PolicyAce newRoot) { if (PolicyRoot != null) { newRoot.AddNextAce(PolicyRoot); } SetPolicyRoot(newRoot); return(this); }
public TpmHash GetPolicyDigest() { PolicyAce dummyAce = null; if (null == PolicyRoot) { return(new TpmHash(PolicyHash.HashAlg)); } // First, check that the tree is OK. An exception is thrown if checks fail. CheckPolicy("", ref dummyAce); return(PolicyRoot.GetPolicyDigest(PolicyHash.HashAlg)); }
/// <summary> /// Returns the ticket associated with a prior policy execution (or null). /// </summary> /// <param name="nodeIdentifier"></param> /// <returns></returns> public TkAuth GetTicket(string nodeIdentifier) { MatchingNode = null; PolicyAce matchingAce = GetNodeIdInternal(PolicyRoot, nodeIdentifier); if (matchingAce == null) { return(null); } TkAuth tic = ((TpmPolicySigned)matchingAce).GetPolicyTicket(); return(tic); }
/// <summary> /// Run a path on the policy tree. The path is identified by the leaf identifier string. A session is /// created and returned. If allowErrors is true then errors returned do not cause an exception (but /// are returned in the response code). /// </summary> /// <param name="tpm"></param> /// <param name="policySession"></param> /// <param name="branchToEvaluate"></param> /// <param name="allowErrors"></param> /// <returns></returns> public TpmRc RunPolicy(Tpm2 tpm, PolicyTree policyTree, string branchToEvaluate = null, bool allowErrors = false) { policyTree.AllowErrorsInPolicyEval = allowErrors; PolicyAce leafAce = null; // First, check that the policy is OK. policyTree.CheckPolicy(branchToEvaluate, ref leafAce); if (leafAce == null) { Globs.Throw("RunPolicy: Branch identifier " + branchToEvaluate + " does not exist"); } var responseCode = TpmRc.Success; try { if (allowErrors) { tpm._DisableExceptions(); } tpm._InitializeSession(this); // Walk up the tree from the leaf.. PolicyAce nextAce = leafAce; while (nextAce != null) { responseCode = nextAce.Execute(tpm, this, policyTree); if (responseCode != TpmRc.Success) { break; } // ..and continue along the path to the root nextAce = nextAce.PreviousAce; } } finally { if (allowErrors) { tpm._EnableExceptions(); } } return(responseCode); }
/// <summary> /// Sets the current policy tree to a policy branch represented by its leaf ACE. /// A policy branch can be constructed by means of the following expressions: /// new TpmAce1().And(new TpmAce2()).And(new TpmAce3()); /// or /// new TpmAce1().AddNextAce(new TpmAce2()).AddNextAce(new TpmAce3()); /// </summary> public void Set(PolicyAce leaf) { if (leaf == null) { PolicyRoot = null; return; } // The construction policyTree.Set() // evaluates to ace4. We have to go back to the root. if (String.IsNullOrEmpty(leaf.BranchID)) { leaf.BranchID = "leaf"; } do { PolicyRoot = leaf; leaf = leaf.PreviousAce; } while (leaf != null); }
protected PolicyAce[] ChainToArray(PolicyAce ace) { int count = 0; PolicyAce curr = ace; while (curr.NextAce != null) { count++; curr = curr.NextAce; } PolicyAce[] arr = new PolicyAce[count]; curr = ace; for (int i = 0; i < count; i++) { arr[i] = curr; curr = curr.NextAce; arr[i].PreviousAce = null; arr[i].NextAce = null; } return(arr); }
private PolicyAce FindNodeId(PolicyAce ace, string nodeId) { if (ace.NodeId == nodeId) { return(ace); } if (ace is TpmPolicyOr) { foreach (PolicyAce branchRoot in ((TpmPolicyOr)ace).PolicyBranches) { PolicyAce a = FindNodeId(branchRoot, nodeId); if (a != null) { return(a); } } } return(ace.NextAce == null ? null : FindNodeId(ace.NextAce, nodeId)); }
public void AddPolicyBranches(PolicyAce[] arr) { PolicyBranches.Clear(); foreach (PolicyAce a in arr) { PolicyBranches.Add(a); } }
internal void CheckBranchIDs(PolicyAce ace, string branchIdToFind, ref PolicyAce matchingAce) { if (ace == null) { return; } ace.AssociatedPolicy = this; // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (ace is TpmPolicyOr) { // Go down each branch of the OR PolicyContainsOrs = true; var orAce = (TpmPolicyOr)ace; foreach (PolicyAce nextAce in orAce.PolicyBranches) { CheckBranchIDs(nextAce, branchIdToFind, ref matchingAce); } } else { PolicyAce nextAce = ace.NextAce; if (nextAce != null) { CheckBranchIDs(nextAce, branchIdToFind, ref matchingAce); return; } // We are at the leaf. If there are no ORs in this chain then we are // done. If there are ORs then check two things (1) that the leaf // has a non-empty BranchIdentifier, and (2) that the branchIdentifiers // are unique. if (!PolicyContainsOrs) { matchingAce = ace; if (String.IsNullOrEmpty(ace.BranchID)) { ace.BranchID = "leaf"; } return; } if (String.IsNullOrEmpty(ace.BranchID)) { Globs.Throw("CheckPolicyIdInternal: Branch leaf does not have a BranchID"); } if (BranchIdCollection.Contains(ace.BranchID)) { Globs.Throw("CheckPolicyIdInternal: Replicated BranchID " + ace.BranchID); } BranchIdCollection.Add(ace.BranchID); if (ace.BranchID == branchIdToFind) { matchingAce = ace; } } }
internal void CheckPolicyIdInternal(PolicyAce ace, string branchIdToFind, ref PolicyAce matchingAce, string nodeIdToFind = "") { // we allow null sessions if (ace == null) { return; } ace.AssociatedPolicy = this; // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (ace is TpmPolicyOr) { // Go down each branch of the OR PolicyContainsOrs = true; var orAce = (TpmPolicyOr)ace; foreach (PolicyAce nextAce in orAce.PolicyBranches) { CheckPolicyIdInternal(nextAce, branchIdToFind, ref matchingAce, nodeIdToFind); } } else { PolicyAce nextAce = ace.NextAce; if (nextAce != null) { CheckPolicyIdInternal(nextAce, branchIdToFind, ref matchingAce, nodeIdToFind); return; } // We are at the leaf. If there are no ORs in this chain then we are done. If there // are ORs then check two things (1) that the leaf has a non-empty BranchIdentifier, // and (2) that the branchIdentifiers are unique. if (!PolicyContainsOrs) { matchingAce = ace; if (String.IsNullOrEmpty(ace.BranchIdentifier)) { ace.BranchIdentifier = "leaf"; } return; } if (String.IsNullOrEmpty(ace.BranchIdentifier)) { throw new Exception("Branch leaf does not have a BranchIdentifier"); } if (BranchIdCollection.Contains(ace.BranchIdentifier)) { throw new Exception("Replicated branch leaf" + ace.BranchIdentifier); } BranchIdCollection.Add(ace.BranchIdentifier); if (ace.BranchIdentifier == branchIdToFind) { matchingAce = ace; } if (!String.IsNullOrEmpty(nodeIdToFind)) { if (nodeIdToFind == ace.NodeId) { MatchingNode = ace; matchingAce = ace; } } } }
/// <summary> /// Load a policy from a stream (MemoryStream, FileStream) in the specified format /// </summary> /// <param name="policyIdentifier"></param> /// <param name="fileName"></param> public void Deserialize(PolicySerializationFormat format, Stream sourceStream) { TpmPolicy pol = null; switch (format) { case PolicySerializationFormat.Xml: { var ser = new DataContractSerializer(typeof(TpmPolicy)); pol = (TpmPolicy)ser.ReadObject(sourceStream); break; } case PolicySerializationFormat.Json: { var ser = new DataContractJsonSerializer(typeof(TpmPolicy)); pol = (TpmPolicy)ser.ReadObject(sourceStream); break; } default: Globs.Throw<ArgumentException>("PolicyTree.Deserialize: Unknown format " + format); return; } pol.AssociatedPolicy = this; PolicyRoot = pol.PolicyRoot; }
protected PolicyAce ArrayToChain(PolicyAce[] arr) { for (int j = 0; j < arr.Length - 1; j++) { arr[j].NextAce = arr[j + 1]; arr[j + 1].PreviousAce = arr[j]; } return arr[0]; }
/// <summary> /// A "normalized" policy is one transformed into disjunctive normal form, /// in which a collection of policy "AND chains" is combined with PolicyOR /// before submission to the TPM. /// Callers must provide an-array-of-arrays of TpmPolicyACEs. The arrays may NOT /// contain PolicyOr (these will be added automatically), but each array MUST be /// terminated with a unique string identifier encoded in a TpmPolicyChainId. /// </summary> /// <param name="policy"></param> public void CreateNormalizedPolicy(PolicyAce[][] policy) { // To validate that the input does not have any repeated branchIds or ACEs var branchIdDict = new Dictionary <string, string>(); var aces = new HashSet <object>(); int numBranches = 0; bool unnamedBranches = false; // The following code validates and transforms the array-of-arrays into a linked // list + OR nodes tree. First collect lists of chains in the chains collection. var chains = new List <PolicyAce>(); foreach (PolicyAce[] chain in policy) { numBranches++; PolicyAce leaf = null; PolicyAce previousAce = null; PolicyAce root = null; // Turn the array into a doubly-linked list foreach (PolicyAce ace in chain) { // Repeats are illegal if (aces.Contains(ace)) { Globs.Throw <ArgumentException>("CreateNormalizedPolicy: " + "Repeated ACE in policy"); } // Already associated with a session is illegal if (ace.AssociatedPolicy != null) { Globs.Throw <ArgumentException>("CreateNormalizedPolicy: " + "ACE is already associated with a policy"); } ace.AssociatedPolicy = this; aces.Add(ace); // OR is illegal in normal form (these are added automatically // at the root to union the arrays that are input to this function). if (ace is TpmPolicyOr) { Globs.Throw <ArgumentException>("CreateNormalizedPolicy: " + "Normalized form cannot contain TpmPolicyOr"); } if (previousAce != null) { previousAce.NextAce = ace; } ace.PreviousAce = previousAce; previousAce = ace; // Is the branchId valid? string branchId = ace.BranchID; if (!String.IsNullOrEmpty(branchId)) { if (branchIdDict.ContainsKey(branchId)) { Globs.Throw <ArgumentException>("CreateNormalizedPolicy: " + "Repeated branch-identifier " + branchId); } branchIdDict.Add(branchId, ""); } if (root == null) { root = ace; } leaf = ace; } // Does the leaf have a branch ID? if (leaf != null && String.IsNullOrEmpty(leaf.BranchID)) { unnamedBranches = true; } // Else we have a good chain starting at root chains.Add(root); } if (unnamedBranches && numBranches != 1) { throw new ArgumentException("Policy-chain leaf does not have a branch identifier"); } // We now have a list of chains in chains. int numChains = chains.Count; // A single chain (no ORs) if (numChains == 1) { PolicyRoot = chains[0]; return; } // Each TPM_or can take up to 8 inputs. We will add OR-aces to the root // to capture all chains. The algorithm is that we create an OR and keep // adding chains in the input order until full (if it is the last chain) // or one-less than full. Then create a new OR, attach it to the last OR // and keep filling as before. var theRoot = new TpmPolicyOr(); TpmPolicyOr currentOrAce = theRoot; for (int j = 0; j < numChains; j++) { bool lastChain = (j == numChains - 1); if ((currentOrAce.PolicyBranches.Count < 7) || lastChain) { currentOrAce.AddPolicyBranch(chains[j]); } else { // We have overflowed the TpmPolicyOr so add a new child-OR // attached to the previous as the final (8th) branch. var nextOr = new TpmPolicyOr(); currentOrAce.AddPolicyBranch(nextOr); currentOrAce = nextOr; currentOrAce.AddPolicyBranch(chains[j]); } } // All input chains are connected up to one or more ORs at the root so we are done. PolicyRoot = theRoot; }
/// <summary> /// Check to see if all branches have an ID and that the IDs are unique. /// </summary> /// <param name="branchIdToFind"></param> /// <param name="matchingAce"></param> internal void CheckPolicy(string branchIdToFind, ref PolicyAce matchingAce) { PolicyContainsOrs = false; BranchIdCollection = new HashSet<string>(); CheckPolicyIdInternal(PolicyRoot, branchIdToFind, ref matchingAce); }
// [Obsolete] public PolicyAce SetPolicyRoot(PolicyAce root) { PolicyRoot = root; return(PolicyRoot); }
internal void CheckPolicyIdInternal(PolicyAce ace, string branchIdToFind, ref PolicyAce matchingAce, string nodeIdToFind = "") { // we allow null sessions if (ace == null) return; ace.AssociatedPolicy = this; // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (ace is TpmPolicyOr) { // Go down each branch of the OR PolicyContainsOrs = true; var orAce = (TpmPolicyOr)ace; foreach (PolicyAce nextAce in orAce.PolicyBranches) { CheckPolicyIdInternal(nextAce, branchIdToFind, ref matchingAce, nodeIdToFind); } } else { PolicyAce nextAce = ace.NextAce; if (nextAce != null) { CheckPolicyIdInternal(nextAce, branchIdToFind, ref matchingAce, nodeIdToFind); return; } // We are at the leaf. If there are no ORs in this chain then we are done. If there // are ORs then check two things (1) that the leaf has a non-empty BranchIdentifier, // and (2) that the branchIdentifiers are unique. if (!PolicyContainsOrs) { matchingAce = ace; if (String.IsNullOrEmpty(ace.BranchIdentifier)) { ace.BranchIdentifier = "leaf"; } return; } if (String.IsNullOrEmpty(ace.BranchIdentifier)) { Globs.Throw("CheckPolicyIdInternal: Branch leaf does not have a BranchIdentifier"); } if (BranchIdCollection.Contains(ace.BranchIdentifier)) { Globs.Throw("CheckPolicyIdInternal: Replicated branch leaf" + ace.BranchIdentifier); } BranchIdCollection.Add(ace.BranchIdentifier); if (ace.BranchIdentifier == branchIdToFind) { matchingAce = ace; } if (!String.IsNullOrEmpty(nodeIdToFind)) { if (nodeIdToFind == ace.NodeId) { MatchingNode = ace; matchingAce = ace; } } } }
/// <summary> /// This sample illustrates the use of a TpmPolicyOr. /// </summary> static void PolicyOr(Tpm2 tpm) { Console.WriteLine("PolicyOr 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.PolicyLocality, TpmCc.PolicyPCR, TpmCc.PolicyAuthValue }; foreach (var commandCode in usedCommands) { if (!tpm.Helpers.IsImplemented(commandCode)) { Console.WriteLine("Cancel Policy OR sample, because command {0} is not implemented by TPM.", commandCode); return; } } var pcrs = new uint[] { 1, 2, 3 }; var sel = new PcrSelection(TpmAlgId.Sha, pcrs); PcrSelection[] selOut; Tpm2bDigest[] pcrValues; // // First read the PCR values // tpm.PcrRead(new[] { sel }, out selOut, out pcrValues); // // 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 policyTree = new PolicyTree(TpmAlgId.Sha256); // // First branch of PolicyOr // var branch1 = new PolicyAce[] { new TpmPolicyLocality(LocalityAttr.TpmLocZero), new TpmPolicyPcr(expectedPcrVals), "branch_1" }; // // Second branch of PolicyOr // var branch2 = new PolicyAce[] { new TpmPolicyAuthValue(), "branch_2" }; // // Create the policy. CreateNormalizedPolicy takes an array-of-arrays // of PolicyACEs that are to be OR'ed together (the branches themselves cannot // contain TpmPOlicyOrs). The library code constructs a policy tree with // minimum number of TpmPolicyOrs at the root. // policyTree.CreateNormalizedPolicy(new[] {branch1, branch2}); // // Ask Tpm2Lib for the expected policy-hash for this policy // TpmHash expectedPolicyHash = policyTree.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 }; var authVal = new byte[] { 1, 2 }; TpmHandle primHandle = CreateSealedPrimaryObject(tpm, dataToSeal, authVal, 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, policyTree, "branch_1"); // // And unseal the object // byte[] unsealedData = tpm[session].Unseal(primHandle); Console.WriteLine("Unsealed data for branch_1: " + BitConverter.ToString(unsealedData)); // // Now run the other branch // tpm.PolicyRestart(session.Handle); session.RunPolicy(tpm, policyTree, "branch_2"); // // And the session will be unusable // unsealedData = tpm[session].Unseal(primHandle); Console.WriteLine("Unsealed data for branch_2: " + BitConverter.ToString(unsealedData)); // // Clean up // tpm.FlushContext(session.Handle); tpm.FlushContext(primHandle); }
/// <summary> /// A "normalized" policy is one transformed into disjunctive normal form in which a collection /// of policy "AND chains" is combined with PolicyOR before submission to the TPM. /// Callers must provide an-array-of-arrays of TpmPolicyACEs. The arrays may NOT /// contain PolicyOr (these will be added automatically), but each array MUST be terminated /// with a unique string identifier encoded in a TpmPolicyChainId. /// </summary> /// <param name="policy"></param> public void CreateNormalizedPolicy(PolicyAce[][] policy) { // To validate that the input does not have any repeated branchIds or ACEs var branchIdDict = new Dictionary<string, string>(); var aces = new HashSet<object>(); int numBranches = 0; bool unnamedBranches = false; // The following code validates and transforms the array-of-arrays into a linked // list + OR nodes tree. First collect lists of chains in the chains collection. var chains = new List<PolicyAce>(); foreach (PolicyAce[] chain in policy) { numBranches++; PolicyAce leaf = null; PolicyAce previousAce = null; PolicyAce root = null; // Turn the array into a doubly-linked list foreach (PolicyAce ace in chain) { // Repeats are illegal if (aces.Contains(ace)) { Globs.Throw<ArgumentException>("CreateNormalizedPolicy: Repeated ACE in policy"); } // Already associated with a session is illegal if (ace.AssociatedPolicy != null) { Globs.Throw<ArgumentException>("CreateNormalizedPolicy: ACE is already associated with a policy"); } ace.AssociatedPolicy = this; aces.Add(ace); // OR is illegal in normal form (these are added automatically // at the root to union the arrays that are input to this function). if (ace is TpmPolicyOr) { Globs.Throw<ArgumentException>("CreateNormalizedPolicy: Normalized form cannot contain TpmPolicyOr"); } if (previousAce != null) { previousAce.NextAce = ace; } ace.PreviousAce = previousAce; previousAce = ace; // Is the branchId valid? string branchId = ace.BranchIdentifier; if (!String.IsNullOrEmpty(branchId)) { if (branchIdDict.ContainsKey(branchId)) { Globs.Throw<ArgumentException>("CreateNormalizedPolicy: Repeated branch-identifier " + branchId); } branchIdDict.Add(branchId, ""); } if (root == null) { root = ace; } leaf = ace; } // Does the leaf have a branch ID? if (leaf != null && String.IsNullOrEmpty(leaf.BranchIdentifier)) { unnamedBranches = true; } // Else we have a good chain starting at root chains.Add(root); } if (unnamedBranches && numBranches != 1) { throw new ArgumentException("Policy-chain leaf does not have a branch identifier"); } // We now have a list of chains in chains. int numChains = chains.Count; // A single chain (no ORs) if (numChains == 1) { PolicyRoot = chains[0]; return; } // Each TPM_or can take up to 8 inputs. We will add OR-aces to the root to capture all // chains. The algorithm is that we create an OR and keep adding chains in the input order // until full (if it is the last chain) or one-less than full. Then create a new OR, attach it // to the last OR and keep filling as before. var theRoot = new TpmPolicyOr(); TpmPolicyOr currentOrAce = theRoot; for (int j = 0; j < numChains; j++) { bool lastChain = (j == numChains - 1); if ((currentOrAce.PolicyBranches.Count < 7) || lastChain) { currentOrAce.AddPolicyBranch(chains[j]); } else { // We have overflowed the TpmPolicyOr so add a new child-OR // attached to the previous as the final (8th) branch. var nextOr = new TpmPolicyOr(); currentOrAce.AddPolicyBranch(nextOr); currentOrAce = nextOr; currentOrAce.AddPolicyBranch(chains[j]); } } // All input chains are connected up to one or more ORs at the root so we are done. PolicyRoot = theRoot; }
internal static PolicyAce FromArrayRepresentation(PolicyAce[] arr, PolicyTree policy) { PolicyAce root = null; PolicyAce current = null; PolicyAce previous = null; // Makes a doubly linked list from an array foreach (PolicyAce a in arr) { // All ACEs have an associated policy tree a.AssociatedPolicy = policy; // we need a link to previous if (previous != null) { a.PreviousAce = previous; } // previous needs a link to us if (current != null) { current.NextAce = a; } current = a; if (root == null) { root = current; } previous = a; } return root; }
// Returns the linked list as an array internal static PolicyAce[] GetArrayRepresentation(PolicyAce head) { int numElems = 0; PolicyAce next = head; do { if (next == null) { break; } next = next.NextAce; numElems++; } while (true); var arr = new PolicyAce[numElems]; int count = 0; next = head; do { if (next == null) { break; } arr[count] = next; next = next.NextAce; count++; } while (true); return arr; }
// [Obsolete] public PolicyAce SetPolicyRoot(PolicyAce root) { PolicyRoot = root; _Digest = null; return(PolicyRoot); }
/// <summary> /// Sets the current policy tree to a policy branch represented by its leaf ACE. /// A policy branch can be constructed by means of the following expressions: /// new TpmAce1().And(new TpmAce2()).And(new TpmAce3()); /// or /// new TpmAce1().AddNextAce(new TpmAce2()).AddNextAce(new TpmAce3()); /// </summary> public void Set (PolicyAce leaf) { if (leaf == null) { PolicyRoot = null; return; } // The construction policyTree.Set() // evaluates to ace4. We have to go back to the root. if (String.IsNullOrEmpty(leaf.BranchIdentifier)) { leaf.BranchIdentifier = "leaf"; } do { PolicyRoot = leaf; leaf = leaf.PreviousAce; } while (leaf != null); }
/// <summary> /// Add an "OR-branch" /// </summary> /// <param name="newAce"></param> /// <returns></returns> public PolicyAce AddPolicyBranch(PolicyAce newAce) { PolicyBranches.Add(newAce); newAce.PreviousAce = this; return newAce; }
/// <summary> /// Create a simple policy chain (no ORs). /// </summary> public void Create(PolicyAce[] singlePolicyChain) { // ReSharper disable once RedundantExplicitArraySize var arr = new PolicyAce[1][] {singlePolicyChain}; CreateNormalizedPolicy(arr); }
public PolicyAce SetPolicyRoot(PolicyAce newRoot) { PolicyRoot = newRoot; return(PolicyRoot); }
public PolicyAce And(PolicyAce nextAce) { return AddNextAce(nextAce); }
/// <summary> /// Add an "OR-branch" /// </summary> /// <param name="newAce"></param> /// <returns></returns> public PolicyAce AddPolicyBranch(PolicyAce newAce) { PolicyBranches.Add(newAce); newAce.PreviousAce = this; return(newAce); }
/// <summary> /// Check to see if all branches have an ID and that the IDs are unique. /// </summary> /// <param name="branchIdToFind"></param> /// <param name="matchingAce"></param> internal void CheckPolicy(string branchIdToFind, ref PolicyAce matchingAce) { PolicyContainsOrs = false; BranchIdCollection = new HashSet <string>(); CheckBranchIDs(PolicyRoot, branchIdToFind, ref matchingAce); }
public PolicyAce And(PolicyAce nextAce) { return(AddNextAce(nextAce)); }
// [Obsolete] public PolicyAce SetPolicyRoot(PolicyAce root) { PolicyRoot = root; return PolicyRoot; }