/// <summary>
/// Some policies can be evaluated solely from public parts of the policy.
/// Others needs a private keyholder to sign some data. Tpm2Lib provides
/// a callback facility for these cases.
///
/// This second sample illustrates the use of callbacks to provide authData.
/// </summary>
/// <param name="tpm">Reference to the TPM object to use.</param>
static void PolicyEvaluationWithCallback2(Tpm2 tpm)
{
Console.WriteLine("Policy evaluation with callback sample 2.");
//
// 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.PolicySecret,
TpmCc.PolicyGetDigest,
TpmCc.PolicyRestart
};
foreach (var commandCode in usedCommands)
{
if (!tpm.Helpers.IsImplemented(commandCode))
{
Console.WriteLine("Cancel Policy evaluation callback 2 sample, because command {0} is not implemented by TPM.", commandCode);
return;
}
}
//
// Create an object with an AuthValue. The type of object is immaterial
// (it can even be the owner). In order to construct the policy we will
// need the name and to prove that we know the AuthVal.
//
_publicAuthorizationValue = AuthValue.FromRandom(10);
var dataToSeal = new byte[] { 1, 2, 3, 4 };
_publicSealedObjectHandle = CreateSealedPrimaryObject(tpm,
dataToSeal,
_publicAuthorizationValue,
null);
byte[] objectName = _publicSealedObjectHandle.Name;
var policy = new PolicyTree(TpmAlgId.Sha256);
policy.Create(
new PolicyAce[]
{
new TpmPolicySecret(objectName, // Name of the obj that we will prove authData
true, // Include nonceTpm
new byte[0], // Not bound to a cpHash
new byte[0], // Null policyRef
0), // Never expires (in this session)
"leaf" // Name for this ACE
});
TpmHash expectedHash = policy.GetPolicyDigest();
//
// We are about to ask for the session to be evaluated, but in order
// to process TpmPolicySecret the caller will have to prove knowledge of
// the authValue associated with objectName. In this first version we
// do this with PWAP.
//
policy.SetPolicySecretCallback(PolicySecretCallback);
AuthSession authSession = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
authSession.RunPolicy(tpm, policy, "leaf");
//
// The policy evaluated. But is the digest what we expect?
//
byte[] digestIs = tpm.PolicyGetDigest(authSession.Handle);
if (expectedHash != digestIs)
{
throw new Exception("Incorrect PolicyDigest");
}
//
// And now do the same thing but with an HMAC session.
//
_sharedTpm = tpm;
tpm.PolicyRestart(authSession.Handle);
policy.SetPolicySecretCallback(PolicySecretCallback2);
authSession.RunPolicy(tpm, policy, "leaf");
_sharedTpm = null;
//
// The policy evaluated. But is the digest what we expect?
//
digestIs = tpm.PolicyGetDigest(authSession.Handle);
if (expectedHash != digestIs)
{
throw new Exception("Incorrect PolicyDigest");
}
Console.WriteLine("TpmPolicySignature evaluated.");
tpm.FlushContext(authSession.Handle);
}