-
Notifications
You must be signed in to change notification settings - Fork 574
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
gadget/install,secboot: use snapcore/secboot luks2 api #8972
gadget/install,secboot: use snapcore/secboot luks2 api #8972
Conversation
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
Blocked, must update TPM connection error handling first. |
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 looks okay to me. I added a comment about one part in encrypt_tpm.go
where I wasn't sure why key copy is done.
|
||
// FormatEncryptedDevice | ||
func FormatEncryptedDevice(key EncryptionKey, label, node string) error { | ||
return sbInitializeLUKS2Container(node, label, key[:]) |
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.
Nitpick, it is not obvious why a copy of the key needs to be made here and below. Could you add a comment to the code please.
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.
The reason is not that we need a copy, it's because key
is an array and the function expects a slice. However, the called function may be changed to require a [64]byte array instead because the first thing it does is to check the size of the slice and fail if it's not exactly 64. See canonical/secboot#45
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.
Thanks for this PR! Looks good, some ideas/suggestions inline. But no blockers AFAICT
}, | ||
}) | ||
c.Assert(capturedFifo, testutil.FileEquals, rkey[:]) | ||
} { |
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.
For completness we may want to have a test with both "openErr" and "formatErr" to have the full matrix
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.
newEncryptedDevice
has a separate test which should ensure it's working properly, it shouldn't be necessary to test it again when testing the recovery key (mockedOpenErr
and mockedFormatErr
are relevant only when creating the device and not when adding a recovery key).
gadget/install/encrypt_test.go
Outdated
c.Assert(s.mockCryptsetup.Calls(), DeepEquals, [][]string{ | ||
func (s *encryptSuite) TestNewEncryptedDevice(c *C) { | ||
for _, tc := range []struct { | ||
formatErr 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.
Some small comments would be nice here, i.e. we have three times "err" - either some small comment or soemthing like:
mockedFormatErr
mockedOpenErr
expectedErr
(or similar)
gadget/install/encrypt_test.go
Outdated
{addErr: nil, err: ""}, | ||
{addErr: errors.New("add key error"), err: "add key 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.
Extra whitespace
gadget/install/encrypt_test.go
Outdated
c.Assert(err, IsNil) | ||
func (s *encryptSuite) TestAddRecoveryKey(c *C) { | ||
for _, tc := range []struct { | ||
addErr 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.
Same comment as above, i.e. maybe slightly more verbose what the relation of addErr and err is? Somehting like "mockedAddErr, expectedErr" maybe ?
} | ||
|
||
calls := 0 | ||
restore := install.MockSecbootFormatEncryptedDevice(func(key secboot.EncryptionKey, label, node string) 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.
We are not checking node here, why is that?
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.
Oops, this was really missing, thanks Michael.
c.Assert(err, IsNil) | ||
} else { | ||
c.Assert(err, ErrorMatches, tc.err) | ||
continue |
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 probably want to check here that c.Assert(cryptsetup.Calls(), HasLen, 0)
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.
Depending on the test case cryptsetup may have been called at this point (e.g. the open error is the result of a cryptsetup open
operation).
myKey[i] = byte(i) | ||
} | ||
|
||
myRecoveryKey := secboot.RecoveryKey{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} |
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.
Same suggestion as above to move the recovery key creation into the encryptionSuite setup
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.
I wonder if we should also create the keys in encrypSuite here (like we did in the gadget code). Somehting like:
diff --git a/secboot/encrypt_test.go b/secboot/encrypt_test.go
index 14860c4e78..4d149187be 100644
--- a/secboot/encrypt_test.go
+++ b/secboot/encrypt_test.go
@@ -28,12 +28,24 @@ import (
"github.com/snapcore/snapd/secboot"
)
-type encryptSuite struct{}
+type encryptSuite struct {
+ mockedEncryptionKey secboot.EncryptionKey
+ mockedRecoveryKey secboot.RecoveryKey
+}
var _ = Suite(&encryptSuite{})
+func (s *encryptSuite) TestSetUp(c *C) {
+ // create empty key to prevent blocking on lack of system entropy
+ s.mockedEncryptionKey = secboot.EncryptionKey{}
+ for i := range s.mockedEncryptionKey {
+ s.mockedEncryptionKey[i] = byte(i)
+ }
+ s.mockedRecoveryKey = secboot.RecoveryKey{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
+}
+
func (s *encryptSuite) TestRecoveryKeySave(c *C) {
- rkey := secboot.RecoveryKey{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255}
+ rkey := s.mockedRecoveryKey
err := rkey.Save("test-key")
c.Assert(err, IsNil)
fileInfo, err := os.Stat("test-key")
diff --git a/secboot/encrypt_tpm_test.go b/secboot/encrypt_tpm_test.go
index 12b984c34d..a0b692b622 100644
--- a/secboot/encrypt_tpm_test.go
+++ b/secboot/encrypt_tpm_test.go
@@ -36,23 +36,17 @@ func (s *encryptSuite) TestFormatEncryptedDevice(c *C) {
{initErr: nil, err: ""},
{initErr: errors.New("some error"), err: "some error"},
} {
- // create empty key to prevent blocking on lack of system entropy
- myKey := secboot.EncryptionKey{}
- for i := range myKey {
- myKey[i] = byte(i)
- }
-
calls := 0
restore := secboot.MockSbInitializeLUKS2Container(func(devicePath, label string, key []byte) error {
calls++
c.Assert(devicePath, Equals, "/dev/node")
c.Assert(label, Equals, "my label")
- c.Assert(key, DeepEquals, myKey[:])
+ c.Assert(key, DeepEquals, s.mockedEncryptionKey[:])
return tc.initErr
})
defer restore()
- err := secboot.FormatEncryptedDevice(myKey, "my label", "/dev/node")
+ err := secboot.FormatEncryptedDevice(s.mockedEncryptionKey, "my label", "/dev/node")
c.Assert(calls, Equals, 1)
if tc.err == "" {
c.Assert(err, IsNil)
@@ -70,25 +64,17 @@ func (s *encryptSuite) TestAddRecoveryKey(c *C) {
{addErr: nil, err: ""},
{addErr: errors.New("some error"), err: "some error"},
} {
- // create empty key to prevent blocking on lack of system entropy
- myKey := secboot.EncryptionKey{}
- for i := range myKey {
- myKey[i] = byte(i)
- }
-
- myRecoveryKey := secboot.RecoveryKey{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
-
calls := 0
restore := secboot.MockSbAddRecoveryKeyToLUKS2Container(func(devicePath string, key []byte, recoveryKey [16]byte) error {
calls++
c.Assert(devicePath, Equals, "/dev/node")
- c.Assert(recoveryKey[:], DeepEquals, myRecoveryKey[:])
- c.Assert(key, DeepEquals, myKey[:])
+ c.Assert(recoveryKey[:], DeepEquals, s.mockedRecoveryKey[:])
+ c.Assert(key, DeepEquals, s.mockedEncryptionKey[:])
return tc.addErr
})
defer restore()
- err := secboot.AddRecoveryKey(myKey, myRecoveryKey, "/dev/node")
+ err := secboot.AddRecoveryKey(s.mockedEncryptionKey, s.mockedRecoveryKey, "/dev/node")
c.Assert(calls, Equals, 1)
if tc.err == "" {
c.Assert(err, IsNil)
but it seems less important here as we only use myKey twice and the recovery key once
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
Signed-off-by: Claudio Matsuoka <[email protected]>
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.
Thanks, looks good
Previously when installing a uc20 system we called
cryptsetup luksFormat
directly to create an encrypted device, and
cryptsetup luksAddKey
to add therecovery key. These two operations are now provided by snapcore/secboot.
(Note that we don't call snapcore/secboot directly, we use our own secboot
package to wrap those calls instead so we can build without snapcore/secboot
depending on the build tags we use.)