/// <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);
}