-
Notifications
You must be signed in to change notification settings - Fork 642
recovery: integrate TPM provisioning #7085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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 <[email protected]>
zyga
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please just use syscall.Sync instead. No need to fork for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, excellent, that's much better, thank you.
mvo5
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright header missing.
|
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 <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
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 [email protected]