Skip to content

Commit

Permalink
feat: expose more encryption options in the LUKS module
Browse files Browse the repository at this point in the history
Add `xchacha12,aes-adiantum-plain64` and `xchacha20,aes-adiantum-plain64` ciphers.
Expose handles for tweaking `--sector-size` and `--key-size`.
Provide a way to set some of the `--perf` flags.

Signed-off-by: Artem Chernyshev <artem.0xD2@gmail.com>
  • Loading branch information
Unix4ever authored and talos-bot committed Jul 26, 2021
1 parent 30c2bc3 commit c34b59f
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 5 deletions.
82 changes: 80 additions & 2 deletions blockdevice/encryption/luks/luks.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,21 @@ import (
// Cipher LUKS2 cipher type.
type Cipher int

var keySizeDefaults = map[Cipher]uint{
AESXTSPlain64Cipher: 512,
XChaCha12Cipher: 256,
XChaCha20Cipher: 256,
}

// String converts to command line string parameter value.
func (c Cipher) String() (string, error) {
switch c {
case AESXTSPlain64Cipher:
return AESXTSPlain64CipherString, nil
case XChaCha12Cipher:
return XChaCha12String, nil
case XChaCha20Cipher:
return XChaCha20String, nil
default:
return "", fmt.Errorf("unknown cipher kind %d", c)
}
Expand All @@ -44,6 +54,10 @@ func ParseCipherKind(s string) (Cipher, error) {
fallthrough
case AESXTSPlain64CipherString:
return AESXTSPlain64Cipher, nil
case XChaCha12String:
return XChaCha12Cipher, nil
case XChaCha20String:
return XChaCha20Cipher, nil
default:
return 0, fmt.Errorf("unknown cipher kind %s", s)
}
Expand All @@ -52,16 +66,50 @@ func ParseCipherKind(s string) (Cipher, error) {
const (
// AESXTSPlain64CipherString string representation of aes-xts-plain64 cipher.
AESXTSPlain64CipherString = "aes-xts-plain64"
// XChaCha12String string representation of xchacha12 cipher.
XChaCha12String = "xchacha12,aes-adiantum-plain64"
// XChaCha20String string representation of xchacha20 cipher.
XChaCha20String = "xchacha20,aes-adiantum-plain64"
// AESXTSPlain64Cipher represents aes-xts-plain64 encryption cipher.
AESXTSPlain64Cipher Cipher = iota
// XChaCha12Cipher represents xchacha12 encryption cipher.
XChaCha12Cipher
// XChaCha20Cipher represents xchacha20 encryption cipher.
XChaCha20Cipher
)

const (
// PerfNoReadWorkqueue sets --perf-no_read_workqueue.
PerfNoReadWorkqueue = "no_read_workqueue"
// PerfNoWriteWorkqueue sets --perf-no_write_workqueue.
PerfNoWriteWorkqueue = "no_write_workqueue"
// PerfSameCPUCrypt sets --perf-same_cpu_crypt.
PerfSameCPUCrypt = "same_cpu_crypt"
)

// ValidatePerfOption checks that specified string is a valid perf option.
func ValidatePerfOption(value string) error {
switch value {
case PerfNoReadWorkqueue:
fallthrough
case PerfNoWriteWorkqueue:
fallthrough
case PerfSameCPUCrypt:
return nil
}

return fmt.Errorf("invalid perf option %v", value)
}

// LUKS implements LUKS2 encryption provider.
type LUKS struct {
perfOptions []string
cipher Cipher
iterTime time.Duration
pbkdfForceIterations uint
pbkdfMemory uint64
blockSize uint64
keySize uint
}

// New creates new LUKS2 encryption provider.
Expand All @@ -74,6 +122,10 @@ func New(cipher Cipher, options ...Option) *LUKS {
option(l)
}

if l.keySize == 0 {
l.keySize = keySizeDefaults[cipher]
}

return l
}

Expand All @@ -86,6 +138,7 @@ func (l *LUKS) Open(deviceName string, key *encryption.Key) (string, error) {

args := []string{"luksOpen", deviceName, mappedName, "--key-file=-"}
args = append(args, keyslotArgs(key)...)
args = append(args, l.perfArgs()...)

err := l.runCommand(args, key.Value)
if err != nil {
Expand All @@ -105,6 +158,11 @@ func (l *LUKS) Encrypt(deviceName string, key *encryption.Key) error {
args := []string{"luksFormat", "--type", "luks2", "--key-file=-", "-c", cipher, deviceName}
args = append(args, l.argonArgs()...)
args = append(args, keyslotArgs(key)...)
args = append(args, l.encryptionArgs()...)

if l.blockSize != 0 {
args = append(args, fmt.Sprintf("--sector-size=%d", l.blockSize))
}

err = l.runCommand(args, key.Value)
if err != nil {
Expand Down Expand Up @@ -134,6 +192,7 @@ func (l *LUKS) AddKey(devname string, key, newKey *encryption.Key) error {
}

args = append(args, l.argonArgs()...)
args = append(args, l.encryptionArgs()...)
args = append(args, keyslotArgs(newKey)...)

return l.runCommand(args, buffer.Bytes())
Expand All @@ -159,6 +218,7 @@ func (l *LUKS) SetKey(devname string, oldKey, newKey *encryption.Key) error {
}

args = append(args, l.argonArgs()...)
args = append(args, l.perfArgs()...)

return l.runCommand(args, buffer.Bytes())
}
Expand Down Expand Up @@ -223,8 +283,6 @@ func (l *LUKS) ReadKeyslots(deviceName string) (*encryption.Keyslots, error) {
return keyslots, nil
}

// CheckKey try using the key

// runCommand executes cryptsetup with arguments.
func (l *LUKS) runCommand(args []string, stdin []byte) error {
_, err := cmd.RunContext(cmd.WithStdin(
Expand Down Expand Up @@ -270,6 +328,26 @@ func (l *LUKS) argonArgs() []string {
return args
}

func (l *LUKS) perfArgs() []string {
res := []string{}

for _, o := range l.perfOptions {
res = append(res, fmt.Sprintf("--perf-%s", o))
}

return res
}

func (l *LUKS) encryptionArgs() []string {
res := []string{}

if l.keySize != 0 {
res = append(res, fmt.Sprintf("--key-size=%d", l.keySize))
}

return append(res, l.perfArgs()...)
}

func keyslotArgs(key *encryption.Key) []string {
if key.Slot != encryption.AnyKeyslot {
return []string{fmt.Sprintf("--key-slot=%d", key.Slot)}
Expand Down
5 changes: 2 additions & 3 deletions blockdevice/encryption/luks/luks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func (suite *LUKSSuite) TestEncrypt() {
provider := luks.New(
luks.AESXTSPlain64Cipher,
luks.WithIterTime(time.Millisecond*100),
luks.WithPerfOptions(luks.PerfSameCPUCrypt),
)

_, err = g.Add(bootSize, gpt.WithPartitionName("boot"))
Expand Down Expand Up @@ -153,9 +154,7 @@ func TestLUKSSuite(t *testing.T) {
t.Skip("can't run the test as non-root")
}

hostname, _ := os.Hostname() //nolint: errcheck

if hostname == "buildkitsandbox" {
if hostname, _ := os.Hostname(); hostname == "buildkitsandbox" { //nolint:errcheck
t.Skip("test not supported under buildkit as partition devices are not propagated from /dev")
}

Expand Down
21 changes: 21 additions & 0 deletions blockdevice/encryption/luks/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,24 @@ func WithPBKDFMemory(value uint64) Option {
l.pbkdfMemory = value
}
}

// WithKeySize sets generated key size.
func WithKeySize(value uint) Option {
return func(l *LUKS) {
l.keySize = value
}
}

// WithBlockSize sets block size.
func WithBlockSize(value uint64) Option {
return func(l *LUKS) {
l.blockSize = value
}
}

// WithPerfOptions enables encryption perf options.
func WithPerfOptions(options ...string) Option {
return func(l *LUKS) {
l.perfOptions = options
}
}

0 comments on commit c34b59f

Please sign in to comment.