wolfTPM icon indicating copy to clipboard operation
wolfTPM copied to clipboard

Add TPM 2.0 example for seal and unseal (using PCR)

Open dgarske opened this issue 5 years ago • 1 comments
trafficstars

TODO: Add example for sealing / unsealing data with TPM based on PCR value.

dgarske avatar Jul 24 '20 16:07 dgarske

Investigate supporting TPM2_PolicyAuthorize and TPM2_PolicyPCR

dgarske avatar Jul 06 '22 15:07 dgarske

The implementation in #244 uses TPM2_PolicyAuthorize with TPM2_PolicyPCR, however for my use case I needed a direct PCR policy for Unseal.

It would be good to get the PolicyAuthorize technique merged though as iirc that's what BitLocker uses, and WolfTPM seemed to be the sanest and easiest to embed library (for EFI) vs the N-levels of indirection in tpm2-tss with lots of dependencies and the scary spaghetti that is the IBM libraries.

Couldn't figure out how to get your branch of WolfTPM to do the unseal the way I needed, but hopefully this information will be useful to you if you choose to implement it.

I ended up just pushing the bytes to/from the TPM by hand as I didn't need flexibility or integration headaches (also don't need parameter encryption as I'm not using a discrete TPM), although I got stuck on how to calculate the HMAC for Unseal with a Policy session. Reading the TCG specs sent me down a week-long rabbit hole, and eventually found it easier to enable TSS2_LOG=all+TRACE rather than relying on the spec or the TSS code.

Attached is a sample TPM conversation performing an Unseal of a PCR policy locked key, the calls to PCR_Read and GetCapability are unnecessary, iirc it should also be unnecessary to pass pcrDigest via PolicyPCR. log.unseal2.txt

Snippet to calculate the HMAC (see the log.unseal2.txt file for where the hashes come from):

from hashlib import sha256
import hmac

# Constant
CC_Unseal = bytes.fromhex('0000015e')

# Returned from TPM_CC.ReadPublic
obj_name = bytes.fromhex('000bafb549e7ce3f1c929e4446f529f6999104eaceb66adedddd0ac8528bd815621d')

context = sha256(CC_Unseal + obj_name).digest()

# Submitted with Unseal request as authorizationArea[0].nonce.buffer
unseal_nonce = bytes.fromhex('0f38a8ce6b7397b81db627a8616c89521d2feb2d1b65f8f546338307d1309b6e')

# Returned from StartAuthSession as .parameters.nonceTPM.buffer
nonceTPM = bytes.fromhex('9ba1856fa01a2559b55ff813a9063f2e56d934a3131af768f869940406bfab73')

# Constant
session_attributes = bytes([1])

msg = context + unseal_nonce + nonceTPM + session_attributes
hmac.new(b'', msg, sha256).hexdigest()

HarryR avatar Mar 09 '23 14:03 HarryR

Hey @HarryR

I've made a separate PR for implementing sealing and unsealing with policyPCR and policyAuthorize https://github.com/wolfSSL/wolfTPM/pull/261. If I'm understanding you correctly you are looking to create a policy with only policyPCR and to seal a secret protected by that policy? If so then my PR supports that, I've made the function wolfTPM2_PolicyPCR so you can create a policy from the PCR values only without using policyAuthorize. If you seal an object after calling wolfTPM2_PolicyPCR using wolfTPM2_CreateKeySeal_ex, or by setting up the TPM2_Create manually, you will only be able to unseal by recreating the policy. Let me know if you have more questions or suggestions.

Best Wishes, John Bland

jpbland1 avatar Mar 21 '23 18:03 jpbland1