From e43da08f2de6f64865aa2373b952a3aa2d49fffa Mon Sep 17 00:00:00 2001 From: Itxaka Date: Thu, 30 Nov 2023 11:01:39 +0100 Subject: [PATCH] Allow passing flags to luksify flags for luks version and use tpm Signed-off-by: Itxaka --- go.mod | 1 + go.sum | 2 ++ main.go | 38 +++++++++++++++++++++++--------------- pkg/lib/lock.go | 48 ++++++++++++++++++++++++++++++++++++------------ 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 408f771..3ecbfda 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/urfave/cli v1.22.12 gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 + k8s.io/apimachinery v0.26.2 ) require ( diff --git a/go.sum b/go.sum index 0c16a74..4ac9a1f 100644 --- a/go.sum +++ b/go.sum @@ -442,3 +442,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= +k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= diff --git a/main.go b/main.go index 40a2ee3..99d40c1 100644 --- a/main.go +++ b/main.go @@ -24,11 +24,24 @@ func main() { Name: "encrypt", Description: "Encrypts a partition", + Usage: "Encrypts a partition", + ArgsUsage: "kcrypt [--version VERSION] [--tpm] LABEL", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "version", + Value: "luks1", + Usage: "luks version to use", + }, + &cli.BoolFlag{ + Name: "tpm", + Usage: "Use TPM to lock the partition", + }, + }, Action: func(c *cli.Context) error { if c.NArg() != 1 { return fmt.Errorf("requires 1 arg, the partition label") } - out, err := lib.Luksify(c.Args().First()) + out, err := lib.Luksify(c.Args().First(), c.String("version"), c.Bool("tpm")) if err != nil { return err } @@ -38,24 +51,19 @@ func main() { }, { - Name: "unlock-all", - UsageText: "unlock-all", - Usage: "Try to unlock all LUKS partitions", - Description: ` -Typically run during initrd to unlock all the LUKS partitions found - `, - ArgsUsage: "kcrypt unlock-all", - Flags: []cli.Flag{ - - &cli.StringFlag{}, - }, + Name: "unlock-all", + UsageText: "unlock-all", + Usage: "Try to unlock all LUKS partitions", + Description: "Typically run during initrd to unlock all the LUKS partitions found", + ArgsUsage: "kcrypt unlock-all", Action: func(c *cli.Context) error { return lib.UnlockAll() }, }, { - Name: "extract-initrd", + Name: "extract-initrd", + Hidden: true, Action: func(c *cli.Context) error { if c.NArg() != 2 { return fmt.Errorf("requires 3 args. initrd,, dst") @@ -64,8 +72,8 @@ Typically run during initrd to unlock all the LUKS partitions found }, }, { - - Name: "inject-initrd", + Name: "inject-initrd", + Hidden: true, Action: func(c *cli.Context) error { if c.NArg() != 3 { return fmt.Errorf("requires 3 args. initrd, srcfile, dst") diff --git a/pkg/lib/lock.go b/pkg/lib/lock.go index 76eadfc..916b72d 100644 --- a/pkg/lib/lock.go +++ b/pkg/lib/lock.go @@ -2,10 +2,12 @@ package lib import ( "fmt" + "github.com/anatol/luks.go" "github.com/gofrs/uuid" "github.com/jaypipes/ghw" "github.com/jaypipes/ghw/pkg/block" configpkg "github.com/kairos-io/kcrypt/pkg/config" + "k8s.io/apimachinery/pkg/util/rand" "os" "os/exec" "strings" @@ -29,33 +31,55 @@ func CreateLuks(dev, password, version string, cryptsetupArgs ...string) error { return nil } -// Take a part label, and recreates it with LUKS. IT OVERWRITES DATA! +// Luksify Take a part label, and recreates it with LUKS. IT OVERWRITES DATA! // On success, it returns a machine parseable string with the partition information // (label:name:uuid) so that it can be stored by the caller for later use. // This is because the label of the encrypted partition is not accessible unless // the partition is decrypted first and the uuid changed after encryption so // any stored information needs to be updated (by the caller). -func Luksify(label string) (string, error) { - // blkid - persistent, b, err := FindPartition(label) +func Luksify(label, version string, tpm bool) (string, error) { + var pass string + if version == "" { + version = "luks1" + } + if version != "luks1" && version != "luks2" { + return "", fmt.Errorf("version must be luks1 or luks2") + } + + part, b, err := FindPartition(label) if err != nil { return "", err } - pass, err := GetPassword(b) - if err != nil { - return "", err + if tpm { + // On TPM locking we generate a random password that will only be used here then discarded. + // only unlocking method will be PCR values + pass = rand.String(32) + } else { + pass, err = GetPassword(b) + if err != nil { + return "", err + } } - persistent = fmt.Sprintf("/dev/%s", persistent) + part = fmt.Sprintf("/dev/%s", part) devMapper := fmt.Sprintf("/dev/mapper/%s", b.Name) partUUID := uuid.NewV5(uuid.NamespaceURL, label) - if err := CreateLuks(persistent, pass, "luks1", []string{"--uuid", partUUID.String()}...); err != nil { + extraArgs := []string{"--uuid", partUUID.String()} + + if err := CreateLuks(part, pass, version, extraArgs...); err != nil { return "", err } + if tpm { + // Enroll PCR values as an unlock method + out, err := SH(fmt.Sprintf("systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7+8+9 %s", part)) + if err != nil { + return "", fmt.Errorf("err: %w, out: %s", err, out) + } + } - if err := LuksUnlock(persistent, b.Name, pass); err != nil { + if err := LuksUnlock(part, b.Name, pass); err != nil { return "", err } @@ -69,9 +93,9 @@ func Luksify(label string) (string, error) { return "", fmt.Errorf("err: %w, out: %s", err, out) } - out2, err := SH(fmt.Sprintf("cryptsetup close %s", b.Name)) + err = luks.Lock(b.Name) if err != nil { - return "", fmt.Errorf("err: %w, out: %s", err, out2) + return "", fmt.Errorf("err: %w", err) } return configpkg.PartitionToString(b), nil