Satisfying a Policy
The considerations for satisfying the different kinds of policies—simple assertions, multifactor assertions, compound assertions, and flexible assertions—are slightly different, so let's consider them separately. It's important to remember that the order in which a policy is satisfied is important. A policy constructed with a TPM2_PolicyPCR followed by TPM2_PolicyPassword is different from a policy constructed with TPM2_PolicyPassword followed by TPM2_PolicyPCR. In general, policy commands aren't commutative.
Simple Assertions and Multifactor Assertions
Most simple assertions are easy to apply to a policy. Password, PCR, locality, TPM internal state, internal state of an NV RAM location, and command-based assertions are asserted in the same way as when the policy was created, except instead of using a trial policy, you use the policy handle myPolicySessionHandle. Other commands that require signature verification (the TPM2_PolicySigned command with or without a policyRef) require more work.
For example, if you're asserting that a password must be used to satisfy the policy, you execute the command TPM2_PolicyPassword. The password isn't actually passed at this time. This is just telling the session that when the command is finally executed with the object, the user must prove at that time that they know the password by passing it in either as a plaintext password or as an HMAC in the session.
To satisfy TPM2_PolicySigned, a signature is needed, and the signature is over a hash that is formed in part from the nonceTPM returned by the last use of the session. Additionally, the TPM must have the public key loaded so that it can verify the signature.
Loading the public key is done exactly the same way you did it to create the session, using the TPM2_LoadExternal command. This returns a handle to the loaded public key, here called aPublicHandle. You use this when calling the PolicySigned command, but first you have to pass in a signature. To do this, you first need to form a hash and sign it.
The hash is formed by
aHash = HASH(nonceTPM || expiration =0 || cpHashA = NULL || policyRef = 0x0000)
where nonceTPM was returned by the TPM when the session was created, expiration is all zeroes (no expiration), cpHashA = Empty Auth, and policyRef is emptyBuffer. (If you're using this for verification of a biometric reader, then policyRef is equal to the name of the person whose biometric was verified). The private key is used to sign this hash; and when signed, the result is called mySignature.
Next you execute the TPM2_PolicySigned command, passing in the handle of the session, APublicHandle, and mySignature. At this point, the TPM checks the signature internally using the public key, and if it's verified, extends its internal session policy buffer as desired. Now any command with an object whose policy that matches that policy buffer can be executed.