constellation/bootstrapper/internal/diskencryption/diskencryption.go
Daniel Weiße 6a40c73ff7
disk-mapper: set LUKS2 token to allow reusing unintialized state disks (#2083)
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
2023-07-18 16:20:03 +02:00

78 lines
2.1 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
// Package diskencryption handles interaction with a node's state disk.
package diskencryption
import (
"fmt"
"github.com/edgelesssys/constellation/v2/internal/cryptsetup"
"github.com/spf13/afero"
)
const (
stateMapperDevice = "state"
initialKeyPath = "/run/cryptsetup-keys.d/state.key"
keyslot = 0
)
// DiskEncryption manages the encrypted state mapper device.
type DiskEncryption struct {
fs afero.Fs
device cryptdevice
}
// New creates a new Cryptsetup.
func New() *DiskEncryption {
return &DiskEncryption{
fs: afero.NewOsFs(),
device: cryptsetup.New(),
}
}
// Open opens the cryptdevice.
func (c *DiskEncryption) Open() (free func(), err error) {
return c.device.InitByName(stateMapperDevice)
}
// UUID gets the device's UUID.
// Only works after calling Open().
func (c *DiskEncryption) UUID() (string, error) {
return c.device.GetUUID()
}
// UpdatePassphrase switches the initial random passphrase of the mapped crypt device to a permanent passphrase.
// Only works after calling Open().
func (c *DiskEncryption) UpdatePassphrase(passphrase string) error {
initialPassphrase, err := c.getInitialPassphrase()
if err != nil {
return err
}
if err := c.device.KeyslotChangeByPassphrase(keyslot, keyslot, initialPassphrase, passphrase); err != nil {
return err
}
// Set token as initialized.
return c.device.SetConstellationStateDiskToken(cryptsetup.SetDiskInitialized)
}
// getInitialPassphrase retrieves the initial passphrase used on first boot.
func (c *DiskEncryption) getInitialPassphrase() (string, error) {
passphrase, err := afero.ReadFile(c.fs, initialKeyPath)
if err != nil {
return "", fmt.Errorf("reading first boot encryption passphrase from disk: %w", err)
}
return string(passphrase), nil
}
type cryptdevice interface {
InitByName(name string) (func(), error)
GetUUID() (string, error)
KeyslotChangeByPassphrase(currentKeyslot int, newKeyslot int, currentPassphrase string, newPassphrase string) error
SetConstellationStateDiskToken(bool) error
}