A key to the protocol I plan to use is to verify a TLS transcript is to do ECDH on TPM2 to get a key that is flagged as not being able to leave the TPM2 (so that only the remove peer server + the TPM has direct access to the key, not the user). The key is used via the TPM2 for TLS, and then deleted off the TPM. The TPM2 then produces a signed attestation that ECDH happened on the TPM, never left it, was only used for the data included in the hash being signed, and was deleted at the end.
There are a few potential paths I considered, all leveraging the audit functionality of the TPM2 (which allows it to certify an audit log).
The biggest challenge is that since every command needs to specify the audit session to use (if any), making sure there is no usage of the key between the records in the audit log is essential.
Use the nonceTPM and verify it through the attested audit log?
It is possible to create a session (that can’t leave the TPM2). When the session is created, you get a random nonce value back. Every time the authorisation is used, the nonce changes. So if it was possible to check that the nonce in matched the nonce out from the previous command, it would be possible to guarantee there were no extra commands.
Unfortunately, the nonce doesn’t seem to appear in the audit hash attested to in the audit logs since it isn’t a command parameter.
Force the nonceTPM to be used against a policy session?
TPM2 allows an object (such as a key) to have a policy hash, so that it can be only accessed by a policy session that satisfies the policy. And a policy can require authorising with a particular session nonceTPM. This would force that nonceTPM into the log. This is effective for making sure a session is only used for authorisation once. However, the above problem with the response nonceTPMs not being in the logs makes this hard to rely on.
Use NV Indexes to limit how many times a policy session is used?
An NV Index references non-volatile memory on the TPM.
There is an NV Index type called ‘PIN PASS’ which increments every time it is used for authorisation, with a limit after which it stops working. It is possible to get the TPM2 to attest to the state of the NV Index. It can be locked down by policy to stop writes to it. So if it wasn’t for loopholes in it, it could be used to attest that a key was only used the expected number of times to encrypt / decrypt / sign.
However, NV Indexes can be deleted and recreated, and their name used to reference them from policy doesn’t include any random data - so it is possible for the user to recreate a PIN PASS with reset counts, and the attestation for this new object will be indistinguishable from the original, and will still work from the policy. This means effectively NV Index based solutions would allow people to forge TLS transcripts, and so it is not suitable for this application.
Use an exclusive audit session
The TPM2 specification allows for an audit session to be marked as ‘exclusive’. It remains exclusive as long as there are no intervening commands to the TPM2 that don’t use the same audit session.
I was hoping to avoid using an exclusive audit session, because generally a system only has one TPM, and an exclusive audit session means that for the duration of the TLS connection we are generating a proof over, the application would need exclusive use of the TPM (or be disrupted and need to start again).
However, I haven’t found a better option despite trying out quite a few leads, and so I’m continuing research on the basis that exclusive audit sessions are the (only) way to go for now. This is disappointing given a few simple improvements to the TPM2 standard could have provided much better options for this application.