SealedStorage
About
SealedStorage library allows to seal data so that it can only be unsealed on a local machine (bound to a specific secure module) in a specific state (typically, verified boot mode). Unlike unsealing, sealing can be done in any state.
SealedStorage only supports Cr50 and uses trunks and tpm_manager to work with the secure module.
The library interface is defined in sealed_storage.h. An example of using the interface is provided in sealed_storage_tool.cc.
Underlying implementation
The data is sealed using a multi-staged process:
- A TPM-bound sealing ECC key is generated. The key is generated as a primary key in endorsement hierarchy, so using the same key template always results in the same key. The key has an attached policy that allows performing authorized operations only when PCRs are in the desired state. The policy is part of the key template, so anyone who wants to generate the same key would have to generate it with that auth policy.
- The sealing key is used in ECDH protocol to generate an ephemeral keypair (ECDH_KeyGen command). ECDH_KeyGen doesn't require authorization and can be performed in any state, regardless of the policy set for the sealing key. The resulting private part of the generated keypair (Z point) is used as a seed for creating an AES-256 key. The public part (pub point) becomes a part of the sealed blob.
- A random IV is generated.
- The data to seal is encrypted using AES-256-CBC with the key and IV obtained on the two previous steps.
- The resulting blob contains {pub point, IV, policy digest, plaintext size, encrypted data}. This blob can be stored by the caller in any non-volatile storage.
To unseal, the steps are reversed:
- The blob, containing {plaintext size, policy digest, pub point, IV, encrypted data}, is parsed.
- The same primary key in endorsement hierarchy is generated. The policy for the key is passed by the caller and must match the policy used when sealing data to get the same sealing key. If the policy passed by the caller doesn't match the policy digest from the blob, an immediate error is returned.
- The sealing key is used in ECDH protocol to restore the private part of the ephemeral key (Z point) given its public part (pub point, retreieved from the blob). ECDH_ZGen command used for that required authorization and would only succeed if the policy attached to the sealing key is satisfied. And, as it was constructed when sealing, the policy is satisifed only if PCRs are in the right state. Thus, for a wrong state, and attempt to unseal would fail at this step.
- After restoring Z point, it is used as a seed for generating AES-256 key, exactly as it was done when sealing.
- The encrypted data is decrypted using the resulting AES key and IV obtained from the data blob. The size of the resulting plaintext is compared with the plaintext size from the blob, and error is returned in case of mismatch to protect from cases when a wrong sealing key (e.g. right policy, but on a different device) leads to a wrong Z point, which by chance leads to a valid padding. And the decryption operation results in a success with some garbage data.