Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions crypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ var (
// required features.
ErrMissingCryptsetupFeature = luks2.ErrMissingCryptsetupFeature

ErrKeyslotNameNotExist = errors.New("no key with the specified name exists")

luks2Activate = luks2.Activate
luks2AddKey = luks2.AddKey
luks2Deactivate = luks2.Deactivate
Expand Down Expand Up @@ -870,7 +872,7 @@ func DeleteLUKS2ContainerKey(devicePath, keyslotName string) error {

token, id, exists := view.TokenByName(keyslotName)
if !exists {
return errors.New("no key with the specified name exists")
return ErrKeyslotNameNotExist
}

if len(view.TokenNames()) == 1 {
Expand Down Expand Up @@ -920,7 +922,7 @@ func renameLUKS2ContainerKey(nonAtomic *nonAtomicOperationAllowedFlag, devicePat

token, id, exists := view.TokenByName(oldName)
if !exists {
return errors.New("no key with the specified name exists")
return ErrKeyslotNameNotExist
}

if _, _, exists := view.TokenByName(newName); exists {
Expand Down Expand Up @@ -1044,3 +1046,20 @@ func NameLegacyLUKS2ContainerKey(devicePath string, keyslot int, newName string)
func TestLUKS2ContainerKey(devicePath string, key []byte) bool {
return luks2.TestContainerKey(devicePath, key)
}

// Check if key is valid key for LUKS2 container at devicePath for a specific keyslot.
func TestLUKS2ContainerKeyForKeyslot(devicePath string, name string, key []byte) (bool, error) {
view, err := newLUKSView(context.TODO(), devicePath)
if err != nil {
return false, xerrors.Errorf("cannot obtain LUKS header view: %w", err)
}

token, _, exists := view.TokenByName(name)
if !exists {
return false, ErrKeyslotNameNotExist
}

keyslotId := token.Keyslots()[0]

return luks2.TestContainerKeyForKeyslot(devicePath, keyslotId, key), nil
}
38 changes: 38 additions & 0 deletions crypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4137,3 +4137,41 @@ func (s *cryptSuite) TestNameLegacyLUKS2ContainerKeyNameAlreadyUsed(c *C) {
err := NameLegacyLUKS2ContainerKey("/dev/foo1", 0, "already-used")
c.Check(err, ErrorMatches, `the new name is already in use`)
}

func (s *cryptSuiteUnmockedBase) TestTestLUKS2ContainerKeyForKeyslot(c *C) {
key := s.newPrimaryKey()
path := luks2test.CreateEmptyDiskImage(c, 20)

initOptions := &InitializeLUKS2ContainerOptions{
InitialKeyslotName: "initial",
}
c.Assert(InitializeLUKS2Container(path, "disk", key, initOptions), IsNil)

otherKey := s.newPrimaryKey()
c.Assert(AddLUKS2ContainerUnlockKey(path, "other", key, otherKey), IsNil)

recoveryKey := s.newRecoveryKey()
c.Assert(AddLUKS2ContainerRecoveryKey(path, "recovery", key, recoveryKey), IsNil)

check := func(name string, testKey []byte, expected bool) {
res, err := TestLUKS2ContainerKeyForKeyslot(path, name, testKey)
c.Assert(err, IsNil)
c.Check(res, Equals, expected)
}

check("initial", key, true)
check("initial", otherKey, false)
check("initial", recoveryKey[:], false)

check("other", key, false)
check("other", otherKey, true)
check("other", recoveryKey[:], false)

check("recovery", key, false)
check("recovery", otherKey, false)
check("recovery", recoveryKey[:], true)

_, err := TestLUKS2ContainerKeyForKeyslot(path, "non-existent", key)
c.Check(err, ErrorMatches, `no key with the specified name exists`)
c.Check(errors.Is(err, ErrKeyslotNameNotExist), Equals, true)
}
5 changes: 5 additions & 0 deletions internal/luks2/cryptsetup.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,3 +506,8 @@ func SetSlotPriority(devicePath string, slot int, priority SlotPriority) error {
func TestContainerKey(devicePath string, key []byte) bool {
return cryptsetupCmd(bytes.NewReader(key), "open", "--test-passphrase", "--key-file", "-", devicePath) == nil
}

// Check if key is valid key for LUKS2 container at devicePath for a specific keyslot.
func TestContainerKeyForKeyslot(devicePath string, slot int, key []byte) bool {
return cryptsetupCmd(bytes.NewReader(key), "open", "--test-passphrase", "--key-slot", strconv.Itoa(slot), "--key-file", "-", devicePath) == nil
}
17 changes: 17 additions & 0 deletions internal/luks2/cryptsetup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1339,3 +1339,20 @@ func (s *cipherSuite) TestSelectCipherAndKeysize(c *C) {
c.Check(keysize, Equals, tc.expectedKeysize)
}
}

func (s *cryptsetupSuite) TestTestContainerKeyForKeyslot(c *C) {
key := make([]byte, 32)
rand.Read(key)

otherKey := make([]byte, 32)
rand.Read(otherKey)

devicePath := luks2test.CreateEmptyDiskImage(c, 20)
c.Assert(Format(devicePath, "test", key, &FormatOptions{}), IsNil)
c.Assert(AddKey(devicePath, key, otherKey, &AddKeyOptions{Slot: 1}), IsNil)

c.Check(TestContainerKeyForKeyslot(devicePath, 0, key), Equals, true)
c.Check(TestContainerKeyForKeyslot(devicePath, 0, otherKey), Equals, false)
c.Check(TestContainerKeyForKeyslot(devicePath, 1, key), Equals, false)
c.Check(TestContainerKeyForKeyslot(devicePath, 1, otherKey), Equals, true)
}
Loading