recovery: integrate TPM provisioning#7085
Conversation
Execute TPM provisioning on install using Chris Coulson's FDE utils code from https://github.com/chrisccoulson/ubuntu-core-fde-utils. This also requires google/go-tpm#109 which has been added to vendored packages. Try to provision the TPM as late as possible to prevent a situation where the installation fails after the TPM is provisioned. Provisioning happens just before sealing the LUKS device keyfile and the lockout authorization value is stored inside the encrypted partition. Signed-off-by: Claudio Matsuoka <claudio.matsuoka@canonical.com>
zyga
left a comment
There was a problem hiding this comment.
Quick pass of my uninformed eyes. I didn't review any of the TPM mechanics but I left a lot of little wording nitpicks for error messages and some misc comments.
recovery/fdeutils/provisioning.go
Outdated
| ) | ||
|
|
||
| const ( | ||
| srkHandle tpmutil.Handle = 0x81000000 |
There was a problem hiding this comment.
It would be great to reference this to some documentation.
recovery/fdeutils/provisioning.go
Outdated
| func ProvisionTPM(lockoutAuth []byte) error { | ||
| rw, err := tpm2.OpenTPM(tpmPath) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to open TPM device: %v", err) |
There was a problem hiding this comment.
Small wording tweak to the error message.
| return fmt.Errorf("failed to open TPM device: %v", err) | |
| return fmt.Errorf("cannot to open TPM device %q: %v", tpmPath, err) |
recovery/fdeutils/provisioning.go
Outdated
|
|
||
| c, _, err := tpm2.GetCapability(rw, tpm2.CapabilityTPMProperties, 1, permanentProps) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to request permanent properties: %v", err) |
There was a problem hiding this comment.
| return fmt.Errorf("failed to request permanent properties: %v", err) | |
| return fmt.Errorf("cannot request permanent TPM properties: %v", err) |
recovery/fdeutils/provisioning.go
Outdated
| } | ||
|
|
||
| if err := tpm2.Clear(rw, tpm2.HandleLockout, ""); err != nil { | ||
| return fmt.Errorf("failed to clear the TPM: %v", err) |
There was a problem hiding this comment.
| return fmt.Errorf("failed to clear the TPM: %v", err) | |
| return fmt.Errorf("cannot clear the TPM: %v", err) |
recovery/fdeutils/provisioning.go
Outdated
| func RequestTPMClearUsingPPI() error { | ||
| f, err := os.OpenFile(ppiPath, os.O_WRONLY, 0) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to open request handle: %v", err) |
There was a problem hiding this comment.
| return fmt.Errorf("failed to open request handle: %v", err) | |
| return fmt.Errorf("cannot open TPM request handle %q: %v", ppiPath, err) |
recovery/fdeutils/provisioning.go
Outdated
| defer f.Close() | ||
|
|
||
| if _, err := f.WriteString(clearPPIRequest); err != nil { | ||
| return fmt.Errorf("failed to submit request: %v", err) |
There was a problem hiding this comment.
| return fmt.Errorf("failed to submit request: %v", err) | |
| return fmt.Errorf("cannot submit TPM request: %v", err) |
recovery/recovery.go
Outdated
| func createWritable(keyfile string, keyfileSize int, cryptdev string) error { | ||
| logger.Noticef("Creating new writable") | ||
| func createWritable(keyBuffer []byte, cryptdev string) error { | ||
| logger.Noticef("Creating new ubuntu-data") |
There was a problem hiding this comment.
| logger.Noticef("Creating new ubuntu-data") | |
| logger.Noticef("Creating new ubuntu-data partition") |
It would be good to always refer to partitions as "foo" partition, because the bare name like ubuntu-data is not associated with partitions in any way.
recovery/recovery.go
Outdated
|
|
||
| // Don't remove this sync, it prevents file corruption on vfat | ||
| if err := exec.Command("sync").Run(); err != nil { | ||
| return fmt.Errorf("cannot sync: %s", err) |
There was a problem hiding this comment.
Please just use syscall.Sync instead. No need to fork for this.
There was a problem hiding this comment.
Ah, excellent, that's much better, thank you.
mvo5
left a comment
There was a problem hiding this comment.
Looks good, I pushed a small tweak to the vendor.json and a small suggestion in the code.
recovery/fdeutils/provisioning.go
Outdated
| const ( | ||
| srkHandle tpmutil.Handle = 0x81000000 | ||
|
|
||
| tpmPath string = "/dev/tpm0" |
There was a problem hiding this comment.
We don't need the "string" here (does not cause harm either though).
vendor/vendor.json
Outdated
| "origin": "github.com/chrisccoulson/go-tpm", | ||
| "path": "github.com/google/go-tpm", | ||
| "revision": "c6c7cb7465ae50e13263f2f8ff33f57d1f9859bc", | ||
| "revisionTime": "2019-07-08T13:36:22Z" |
There was a problem hiding this comment.
This will need the following extra line:
"tree": true
recovery/fdeutils/provisioning.go
Outdated
| return nil | ||
| } | ||
|
|
||
| func RequestTPMClearUsingPPI() error { |
There was a problem hiding this comment.
This is used only inside this package, it should probably be unexported - we can always export it if needed.
recovery/fdeutils/provisioning.go
Outdated
| @@ -0,0 +1,100 @@ | |||
| package fdeutils | |||
|
I talked to Chris and he preferes to have the code in his repo for now. I will rework this to import it from his repo. |
Don't store the unsealed key to the encrypted partition in the filesystem, write it to cryptsetup's stdin instead. Signed-off-by: Claudio Matsuoka <claudio.matsuoka@canonical.com>
Signed-off-by: Claudio Matsuoka <claudio.matsuoka@canonical.com>
Execute TPM provisioning on install using Chris Coulson's FDE utils code
from https://github.com/chrisccoulson/ubuntu-core-fde-utils. This also
requires google/go-tpm#109 which has been added
to vendored packages.
Try to provision the TPM as late as possible to prevent a situation
where the installation fails after the TPM is provisioned. Provisioning
happens just before sealing the LUKS device keyfile and the lockout
authorization value is stored inside the encrypted partition.
Signed-off-by: Claudio Matsuoka claudio.matsuoka@canonical.com