diff --git a/cmd/luks2crypt/main.go b/cmd/luks2crypt/main.go index eeed13e..3fb5613 100644 --- a/cmd/luks2crypt/main.go +++ b/cmd/luks2crypt/main.go @@ -45,6 +45,9 @@ func run(args []string) error { Usage: "Luks Device to rotate password on. Ex. /dev/sda3"}, cli.StringFlag{Name: "currentpassword, p", Usage: "Password to unlock and update device"}, + cli.IntFlag{Name: "luksVersion, v", + Usage: "Luks version", + Value: 2}, cli.StringFlag{Name: "cryptserver, s", Usage: "Crypt Server to escrow recovery key to. Ex. cryptserver.example.com"}, cli.StringFlag{Name: "cryptendpoint, e", @@ -71,13 +74,19 @@ func optVersion(c *cli.Context) error { func optPostImaging(c *cli.Context) error { cryptURL := "https://" + c.String("cryptserver") opts := postimaging.Opts{ - LuksDev: c.String("luksdevice"), - CurPass: c.String("currentpassword"), - Server: cryptURL, - URI: c.String("cryptendpoint"), - AuthUser: c.String("authuser"), - AuthPass: c.String("authpass"), + LuksDev: c.String("luksdevice"), + CurPass: c.String("currentpassword"), + Server: cryptURL, + URI: c.String("cryptendpoint"), + AuthUser: c.String("authuser"), + AuthPass: c.String("authpass"), + LuksVersion: c.Int("luksVersion"), } + + if opts.LuksVersion != 1 { + opts.LuksVersion = 2 + } + if (opts.AuthUser != "") && (opts.AuthPass == "") { fmt.Printf("Password: ") password, err := terminal.ReadPassword(0) diff --git a/go.mod b/go.mod index 8260835..4bca34a 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,13 @@ go 1.14 require ( github.com/diskfs/go-diskfs v0.0.0-20190517155712-1190dcf1ff31 github.com/dselans/dmidecode v0.0.0-20180814053009-65c3f9d81910 - github.com/gorilla/schema v1.1.0 + github.com/gorilla/schema v1.2.0 github.com/kr/pretty v0.1.0 // indirect github.com/satori/go.uuid v1.2.0 // indirect github.com/sethvargo/go-diceware v0.2.0 - golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 - golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect + golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c + golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/urfave/cli.v1 v1.20.0 ) diff --git a/go.sum b/go.sum index 8ecf602..a257eb6 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/diskfs/go-diskfs v0.0.0-20190517155712-1190dcf1ff31 h1:k5UxaYj85BdnZn github.com/diskfs/go-diskfs v0.0.0-20190517155712-1190dcf1ff31/go.mod h1:/Law/HCWU7AOPxin1Tg4L9eUwlLjVUsuztx/s4X683E= github.com/dselans/dmidecode v0.0.0-20180814053009-65c3f9d81910 h1:w9T/rS5VP0SPXqYr7BpUeqf6ukp/GEWm6nXhziWzBY4= github.com/dselans/dmidecode v0.0.0-20180814053009-65c3f9d81910/go.mod h1:yGxJ4za56u74+F00gmg9RJoyXLzvrOrIat4b/Dgw9Lo= -github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= -github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= +github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -14,13 +14,18 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/sethvargo/go-diceware v0.2.0 h1:3QzXGqUe0UR9y1XYSz1dxGS+fKtXOxRqqKjy+cG1yTI= github.com/sethvargo/go-diceware v0.2.0/go.mod h1:II+37A5sTGAtg3zd/JqyVQ8qqAjSm/2r2X6qkVZDjyg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/luks/luks.go b/internal/luks/luks.go index 1350f47..e6866fb 100644 --- a/internal/luks/luks.go +++ b/internal/luks/luks.go @@ -22,6 +22,7 @@ type Settings struct { OldPass, NewPass, LuksDevice string LuksSlot int cDevice *C.struct_crypt_device + LuksVersion int } // Error holds error messages from this package @@ -52,7 +53,11 @@ func (luksDevice *Settings) cryptInit() (*C.struct_crypt_device, error) { // load populates the libcryptsetup struct with device info from disk func (luksDevice *Settings) load() error { - cCryptType := C.CString(C.CRYPT_LUKS1) + cCryptType := C.CString(C.CRYPT_LUKS2) + if luksDevice.LuksVersion == 1 { + cCryptType = C.CString(C.CRYPT_LUKS1) + } + defer C.free(unsafe.Pointer(cCryptType)) err := C.crypt_load(luksDevice.cDevice, cCryptType, nil) @@ -141,7 +146,11 @@ func (luksDevice *Settings) format() (int, error) { data_device: nil, } - cLuksType := C.CString(C.CRYPT_LUKS1) + cLuksType := C.CString(C.CRYPT_LUKS2) + if luksDevice.LuksVersion == 1 { + cLuksType = C.CString(C.CRYPT_LUKS1) + } + defer C.free(unsafe.Pointer(cLuksType)) cLuksCipher := C.CString("aes") @@ -207,10 +216,11 @@ func (luksDevice *Settings) freeCryptDev() { // formatSetPassword formats a device with luks and adds a passphrase to device // This is used by tests to create a virtual disk -func formatSetPassword(pass string, luksDevice string) (bool, error) { +func formatSetPassword(pass string, luksDevice string, luksVersion int) (bool, error) { cryptInfo := &Settings{ - NewPass: pass, - LuksDevice: luksDevice, + NewPass: pass, + LuksDevice: luksDevice, + LuksVersion: luksVersion, } cCryptDev, err := cryptInfo.cryptInit() @@ -233,9 +243,10 @@ func formatSetPassword(pass string, luksDevice string) (bool, error) { } // PassWorks tests if a luks password is correct -func PassWorks(pass string, luksDevice string) (bool, error) { +func PassWorks(pass string, luksDevice string, luksVersion int) (bool, error) { cryptInfo := &Settings{ - LuksDevice: luksDevice, + LuksDevice: luksDevice, + LuksVersion: luksVersion, } cCryptDev, err := cryptInfo.cryptInit() @@ -261,15 +272,12 @@ func PassWorks(pass string, luksDevice string) (bool, error) { } // SetRecoveryPassword changes the luks passphrase on the device -func SetRecoveryPassword( - oldPass string, - newPass string, - luksDevice string, -) error { +func SetRecoveryPassword(oldPass string, newPass string, luksDevice string, luksVersion int) error { cryptInfo := &Settings{ - OldPass: oldPass, - NewPass: newPass, - LuksDevice: luksDevice, + OldPass: oldPass, + NewPass: newPass, + LuksDevice: luksDevice, + LuksVersion: luksVersion, } cCryptDev, err := cryptInfo.cryptInit() diff --git a/internal/luks/luks_test.go b/internal/luks/luks_test.go index 3fb2860..4889001 100644 --- a/internal/luks/luks_test.go +++ b/internal/luks/luks_test.go @@ -19,6 +19,7 @@ import ( type testDisk struct { path, pass, newPass string size int64 + luksVersion int } // createTempDir allocates a temporary directory in the system $TMPDIR @@ -36,8 +37,9 @@ func createTempDir(t *testing.T, dir string, prefix string) string { // create allocates and formats a disk to run tests against func (d testDisk) create(t *testing.T) { luksDev := &Settings{ - NewPass: d.pass, - LuksDevice: d.path, + NewPass: d.pass, + LuksDevice: d.path, + LuksVersion: d.luksVersion, } disk, err := diskfs.Create(d.path, d.size, diskfs.Raw) @@ -55,7 +57,7 @@ func (d testDisk) create(t *testing.T) { t.Errorf("error partitioning test filesystem %v", err) } - _, err = formatSetPassword(luksDev.NewPass, luksDev.LuksDevice) + _, err = formatSetPassword(luksDev.NewPass, luksDev.LuksDevice, luksDev.LuksVersion) if err != nil { t.Errorf("error creating test luks device: %v", err) } @@ -66,13 +68,14 @@ func TestPassWorks(t *testing.T) { defer os.RemoveAll(dir) expected := testDisk{ - path: path.Clean(dir + "/luksdisk.img"), - size: int64(10 * 1024 * 1024), // 10MB - pass: "testPassw0rd!", + path: path.Clean(dir + "/luksdisk.img"), + size: int64(10 * 1024 * 1024), // 10MB + pass: "testPassw0rd!", + luksVersion: 1, } expected.create(t) - _, err := PassWorks(expected.pass, expected.path) + _, err := PassWorks(expected.pass, expected.path, expected.luksVersion) if err != nil { t.Errorf("error checking if '%v' is the password for '%v'. Got %v", expected.pass, @@ -87,14 +90,15 @@ func TestSetRecoveryPassword(t *testing.T) { defer os.RemoveAll(dir) expected := testDisk{ - path: path.Clean(dir + "/luksdisk.img"), - size: int64(10 * 1024 * 1024), // 10MB - pass: "testPassw0rd!", - newPass: "Th!sIsTh3NewPassw0d*", + path: path.Clean(dir + "/luksdisk.img"), + size: int64(10 * 1024 * 1024), // 10MB + pass: "testPassw0rd!", + newPass: "Th!sIsTh3NewPassw0d*", + luksVersion: 1, } expected.create(t) - err := SetRecoveryPassword(expected.pass, expected.newPass, expected.path) + err := SetRecoveryPassword(expected.pass, expected.newPass, expected.path, expected.luksVersion) if err != nil { t.Errorf("error changing password from '%v' to '%v' on '%v'. Got %v", expected.pass, diff --git a/pkg/postimaging/postimaging.go b/pkg/postimaging/postimaging.go index 275043b..f1a07f2 100644 --- a/pkg/postimaging/postimaging.go +++ b/pkg/postimaging/postimaging.go @@ -20,6 +20,7 @@ import ( // Opts is used to store the options needed for postimaging functions type Opts struct { + LuksVersion int LuksDev, CurPass, Server, URI, AuthUser, AuthPass string } @@ -52,7 +53,7 @@ func Run(opts Opts) error { log.Println("generated new random password") // test if the current password works before performing destructive actions - passWorks, err := luks.PassWorks(opts.CurPass, opts.LuksDev) + passWorks, err := luks.PassWorks(opts.CurPass, opts.LuksDev, opts.LuksVersion) if err != nil || passWorks == false { return err } @@ -84,7 +85,7 @@ func Run(opts Opts) error { // change luks admin password to new password err = luks.SetRecoveryPassword(opts.CurPass, cryptServerData.Pass, - opts.LuksDev) + opts.LuksDev, opts.LuksVersion) if err != nil { return err }