go-tpm-tools
go-tpm-tools copied to clipboard
Support seal/unseal operation with a password
Current seal/unseal operations in tpm2tools only check PCRs. We should support the operation with a user specified password. So users can seal the secret to not only PCRs but also a password.
I'm contemplating hacking a bit on this as I need the signer interface. Is there any preferred ways to approach this?
Hi, the reason we didn't implement this in the first place is that, even though it is possible to add a password as an authorization, we think it is better to encrypt the data by yourself with a password (so no TPM needed, maybe using AEAD), and then seal the encrypted blob using the seal operation with the TPM. We fell like they can achieve the same result (though one advantage of TPM password auth is that it can provide certain dictionary attack protection, TPM will lock out for some time after few wrong password attempts). What's your use case?
I'm trying to seal private RSA key material in the TPM to create a x509 cert from it. Having PCR support and password support would make things better since the private key material never leaves the TPM.
A POC for this code is here without the PCR sealing and stuff.
https://github.com/Foxboron/go-uefi/blob/morten/tpm/cmd/gotpm/main.go
It's for having better key generation backends for sbctl
, https://github.com/Foxboron/sbctl
IIUC, you wan to create a Secure Boot key using TPM. In the POC, since you created a primary key using tpm2.HandleEndorsement
, you have already made sure that the private key won't leave the TPM.
Sealing the key with the PCR/password ensure that you can sign new EFI binaries iff the machine is in a good know state/you have the correct password. Is that what you want?
Sealing the key with the PCR/password ensure that you can sign new EFI binaries iff the machine is in a good know state/you have the correct password. Is that what you want?
Correct :)
func NewKey(rw io.ReadWriter, parent tpmutil.Handle, template tpm2.Public) (k *Key, err error) {
+ return NewKeyWithPcr(rw, parent, template, tpm2.PCRSelection{})
+}
+
+func NewKeyWithPcr(rw io.ReadWriter, parent tpmutil.Handle, template tpm2.Public, pcr tpm2.PCRSelection) (k *Key, err error) {
+ return NewKeyWithPassword(rw, parent, template, pcr, "", "")
+}
+
+func NewKeyWithPassword(rw io.ReadWriter, parent tpmutil.Handle, template tpm2.Public, pcr tpm2.PCRSelection, parentPassword, ownerPassword string) (k *Key, err error) {
if !isHierarchy(parent) {
// TODO add support for normal objects with Create() and Load()
return nil, fmt.Errorf("unsupported parent handle: %x", parent)
}
handle, pubArea, _, _, _, _, err :=
- tpm2.CreatePrimaryEx(rw, parent, tpm2.PCRSelection{}, "", "", template)
+ tpm2.CreatePrimaryEx(rw, parent, pcr, parentPassword, ownerPassword, template)
if err != nil {
return nil, err
}
I think something like this would solve the issue without introducing any new complexities in the codebase?
password
can be added as ownerPassword
here which is straightforward. However I think the PCR field in the CreatePrimaryEx
is for the creation data. In order to have the PCR auth for the key, we probably need to use the PCRSessionAuth we did for the Seal function. https://github.com/google/go-tpm-tools/blob/70c4d48316ea5e19a2e25930a2575eba3c808600/client/keys.go#L237