mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-08-06 05:54:28 -04:00
cryptsetup: unify code (#2043)
* Add common backend for interacting with cryptsetup * Use common cryptsetup backend in bootstrapper * Use common cryptsetup backend in disk-mapper * Use common cryptsetup backend in csi lib --------- Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
f52c6752e2
commit
ac1128d07f
34 changed files with 1061 additions and 1307 deletions
76
disk-mapper/internal/diskencryption/BUILD.bazel
Normal file
76
disk-mapper/internal/diskencryption/BUILD.bazel
Normal file
|
@ -0,0 +1,76 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "mapper",
|
||||
srcs = [
|
||||
"cryptdevice.go",
|
||||
"mapper.go",
|
||||
"mapper_cgo.go",
|
||||
"mapper_cross.go",
|
||||
],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/disk-mapper/internal/mapper",
|
||||
visibility = ["//disk-mapper:__subpackages__"],
|
||||
deps = select({
|
||||
"@io_bazel_rules_go//go/platform:aix": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//internal/cryptsetup",
|
||||
"//internal/logger",
|
||||
"@com_github_martinjungblut_go_cryptsetup//:go-cryptsetup",
|
||||
"@org_uber_go_zap//:zap",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:illumos": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:ios": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:js": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//internal/cryptsetup",
|
||||
"//internal/logger",
|
||||
"@com_github_martinjungblut_go_cryptsetup//:go-cryptsetup",
|
||||
"@org_uber_go_zap//:zap",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//internal/logger",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "diskencryption",
|
||||
srcs = ["diskencryption.go"],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/disk-mapper/internal/diskencryption",
|
||||
visibility = ["//disk-mapper:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/cryptsetup",
|
||||
"//internal/logger",
|
||||
"@org_uber_go_zap//:zap",
|
||||
],
|
||||
)
|
108
disk-mapper/internal/diskencryption/diskencryption.go
Normal file
108
disk-mapper/internal/diskencryption/diskencryption.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/*
|
||||
Package diskencryption uses libcryptsetup to format and map crypt devices.
|
||||
|
||||
This is used by the disk-mapper to set up a node's state disk.
|
||||
|
||||
All interaction with libcryptsetup should be done here.
|
||||
*/
|
||||
package diskencryption
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/cryptsetup"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// DiskEncryption handles actions for formatting and mapping crypt devices.
|
||||
type DiskEncryption struct {
|
||||
device cryptDevice
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
// New creates a new crypt device for the device at path.
|
||||
func New(path string, log *logger.Logger) (*DiskEncryption, func(), error) {
|
||||
device := cryptsetup.New()
|
||||
free, err := device.Init(path)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("initializing crypt device for disk %q: %w", path, err)
|
||||
}
|
||||
return &DiskEncryption{device: device, log: log}, free, nil
|
||||
}
|
||||
|
||||
// IsLUKSDevice returns true if the device is formatted as a LUKS device.
|
||||
func (d *DiskEncryption) IsLUKSDevice() bool {
|
||||
return d.device.LoadLUKS2() == nil
|
||||
}
|
||||
|
||||
// DiskUUID gets the device's UUID.
|
||||
func (d *DiskEncryption) DiskUUID() (string, error) {
|
||||
return d.device.GetUUID()
|
||||
}
|
||||
|
||||
// FormatDisk formats the disk and adds passphrase in keyslot 0.
|
||||
func (d *DiskEncryption) FormatDisk(passphrase string) error {
|
||||
if err := d.device.Format(cryptsetup.FormatIntegrity); err != nil {
|
||||
return fmt.Errorf("formatting disk: %w", err)
|
||||
}
|
||||
|
||||
if err := d.device.KeyslotAddByVolumeKey(0, "", passphrase); err != nil {
|
||||
return fmt.Errorf("adding keyslot: %w", err)
|
||||
}
|
||||
|
||||
// wipe using 64MiB block size
|
||||
if err := d.Wipe(67108864); err != nil {
|
||||
return fmt.Errorf("wiping disk: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapDisk maps a crypt device to /dev/mapper/target using the provided passphrase.
|
||||
func (d *DiskEncryption) MapDisk(target, passphrase string) error {
|
||||
if err := d.device.ActivateByPassphrase(target, 0, passphrase, cryptsetup.ReadWriteQueueBypass); err != nil {
|
||||
return fmt.Errorf("mapping disk as %q: %w", target, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmapDisk removes the mapping of target.
|
||||
func (d *DiskEncryption) UnmapDisk(target string) error {
|
||||
return d.device.Deactivate(target)
|
||||
}
|
||||
|
||||
// Wipe overwrites the device with zeros to initialize integrity checksums.
|
||||
func (d *DiskEncryption) Wipe(blockWipeSize int) error {
|
||||
logProgress := func(size, offset uint64) {
|
||||
prog := (float64(offset) / float64(size)) * 100
|
||||
d.log.With(zap.String("progress", fmt.Sprintf("%.2f%%", prog))).Infof("Wiping disk")
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
// wipe the device
|
||||
if err := d.device.Wipe("integrity", blockWipeSize, 0, logProgress, 30*time.Second); err != nil {
|
||||
return fmt.Errorf("wiping disk: %w", err)
|
||||
}
|
||||
d.log.With(zap.Duration("duration", time.Since(start))).Infof("Wiping disk successful")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type cryptDevice interface {
|
||||
ActivateByPassphrase(deviceName string, keyslot int, passphrase string, flags int) error
|
||||
ActivateByVolumeKey(deviceName string, volumeKey string, volumeKeySize int, flags int) error
|
||||
Deactivate(deviceName string) error
|
||||
Format(integrity bool) error
|
||||
GetUUID() (string, error)
|
||||
LoadLUKS2() error
|
||||
KeyslotAddByVolumeKey(keyslot int, volumeKey string, passphrase string) error
|
||||
Wipe(name string, wipeBlockSize int, flags int, logCallback func(size, offset uint64), logFrequency time.Duration) error
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue