remove Trezor support
This commit is contained in:
parent
7dda2363e1
commit
1364b44ae3
@ -405,16 +405,6 @@ You need root permissions to use `-suid`.
|
||||
#### -trace string
|
||||
Write execution trace to file. View the trace using "go tool trace FILE".
|
||||
|
||||
#### -trezor
|
||||
With `-init`: Protect the masterkey using a SatoshiLabs Trezor instead of a password.
|
||||
|
||||
This feature is disabled by default and must be enabled at compile time using:
|
||||
|
||||
./build.bash -tags enable_trezor
|
||||
|
||||
You can determine if your gocryptfs binary has Trezor support enabled checking
|
||||
if the `gocryptfs -version` output contains the string `enable_trezor`.
|
||||
|
||||
#### -version
|
||||
Print version and exit. The output contains three fields separated by ";".
|
||||
Example: "gocryptfs v1.1.1-5-g75b776c; go-fuse 6b801d3; 2016-11-01 go1.7.3".
|
||||
|
10
cli_args.go
10
cli_args.go
@ -18,7 +18,6 @@ import (
|
||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
||||
"github.com/rfjakob/gocryptfs/internal/prefer_openssl"
|
||||
"github.com/rfjakob/gocryptfs/internal/readpassword"
|
||||
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
)
|
||||
@ -29,7 +28,7 @@ type argContainer struct {
|
||||
plaintextnames, quiet, nosyslog, wpanic,
|
||||
longnames, allow_other, reverse, aessiv, nonempty, raw64,
|
||||
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
|
||||
sharedstorage, devrandom, fsck, trezor bool
|
||||
sharedstorage, devrandom, fsck bool
|
||||
// Mount options with opposites
|
||||
dev, nodev, suid, nosuid, exec, noexec, rw, ro bool
|
||||
masterkey, mountpoint, cipherdir, cpuprofile,
|
||||
@ -170,9 +169,6 @@ func parseCliOpts() (args argContainer) {
|
||||
flagSet.BoolVar(&args.sharedstorage, "sharedstorage", false, "Make concurrent access to a shared CIPHERDIR safer")
|
||||
flagSet.BoolVar(&args.devrandom, "devrandom", false, "Use /dev/random for generating master key")
|
||||
flagSet.BoolVar(&args.fsck, "fsck", false, "Run a filesystem check on CIPHERDIR")
|
||||
if readpassword.TrezorSupport {
|
||||
flagSet.BoolVar(&args.trezor, "trezor", false, "Protect the masterkey using a SatoshiLabs Trezor instead of a password")
|
||||
}
|
||||
|
||||
// Mount options with opposites
|
||||
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")
|
||||
@ -282,10 +278,6 @@ func parseCliOpts() (args argContainer) {
|
||||
tlog.Fatal.Printf("The options -extpass and -masterkey cannot be used at the same time")
|
||||
os.Exit(exitcodes.Usage)
|
||||
}
|
||||
if !args.extpass.Empty() && args.trezor {
|
||||
tlog.Fatal.Printf("The options -extpass and -trezor cannot be used at the same time")
|
||||
os.Exit(exitcodes.Usage)
|
||||
}
|
||||
if args.idle < 0 {
|
||||
tlog.Fatal.Printf("Idle timeout cannot be less than 0")
|
||||
os.Exit(exitcodes.Usage)
|
||||
|
14
init_dir.go
14
init_dir.go
@ -9,7 +9,6 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||
"github.com/rfjakob/gocryptfs/internal/cryptocore"
|
||||
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
||||
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||
"github.com/rfjakob/gocryptfs/internal/readpassword"
|
||||
@ -72,19 +71,10 @@ func initDir(args *argContainer) {
|
||||
tlog.Info.Printf("Choose a password for protecting your files.")
|
||||
}
|
||||
{
|
||||
var password []byte
|
||||
var trezorPayload []byte
|
||||
if args.trezor {
|
||||
trezorPayload = cryptocore.RandBytes(readpassword.TrezorPayloadLen)
|
||||
// Get binary data from from Trezor
|
||||
password = readpassword.Trezor(trezorPayload)
|
||||
} else {
|
||||
// Normal password entry
|
||||
password = readpassword.Twice([]string(args.extpass), args.passfile)
|
||||
}
|
||||
password := readpassword.Twice([]string(args.extpass), args.passfile)
|
||||
creator := tlog.ProgramName + " " + GitVersion
|
||||
err = configfile.Create(args.config, password, args.plaintextnames,
|
||||
args.scryptn, creator, args.aessiv, args.devrandom, trezorPayload)
|
||||
args.scryptn, creator, args.aessiv, args.devrandom)
|
||||
if err != nil {
|
||||
tlog.Fatal.Println(err)
|
||||
os.Exit(exitcodes.WriteConf)
|
||||
|
@ -46,10 +46,6 @@ type ConfFile struct {
|
||||
// mounting. This mechanism is analogous to the ext4 feature flags that are
|
||||
// stored in the superblock.
|
||||
FeatureFlags []string
|
||||
// TrezorPayload stores 32 random bytes used for unlocking the master key using
|
||||
// a Trezor security module. The randomness makes sure that a unique unlock
|
||||
// value is used for each gocryptfs filesystem.
|
||||
TrezorPayload []byte `json:",omitempty"`
|
||||
// Filename is the name of the config file. Not exported to JSON.
|
||||
filename string
|
||||
}
|
||||
@ -73,7 +69,7 @@ func randBytesDevRandom(n int) []byte {
|
||||
// "password" and write it to "filename".
|
||||
// Uses scrypt with cost parameter logN.
|
||||
func Create(filename string, password []byte, plaintextNames bool,
|
||||
logN int, creator string, aessiv bool, devrandom bool, trezorPayload []byte) error {
|
||||
logN int, creator string, aessiv bool, devrandom bool) error {
|
||||
var cf ConfFile
|
||||
cf.filename = filename
|
||||
cf.Creator = creator
|
||||
@ -93,10 +89,6 @@ func Create(filename string, password []byte, plaintextNames bool,
|
||||
if aessiv {
|
||||
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagAESSIV])
|
||||
}
|
||||
if len(trezorPayload) > 0 {
|
||||
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagTrezor])
|
||||
cf.TrezorPayload = trezorPayload
|
||||
}
|
||||
{
|
||||
// Generate new random master key
|
||||
var key []byte
|
||||
|
@ -62,7 +62,7 @@ func TestLoadV2StrangeFeature(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateConfDefault(t *testing.T) {
|
||||
err := Create("config_test/tmp.conf", testPw, false, 10, "test", false, false, nil)
|
||||
err := Create("config_test/tmp.conf", testPw, false, 10, "test", false, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -83,14 +83,14 @@ func TestCreateConfDefault(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateConfDevRandom(t *testing.T) {
|
||||
err := Create("config_test/tmp.conf", testPw, false, 10, "test", false, true, nil)
|
||||
err := Create("config_test/tmp.conf", testPw, false, 10, "test", false, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateConfPlaintextnames(t *testing.T) {
|
||||
err := Create("config_test/tmp.conf", testPw, true, 10, "test", false, false, nil)
|
||||
err := Create("config_test/tmp.conf", testPw, true, 10, "test", false, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -111,7 +111,7 @@ func TestCreateConfPlaintextnames(t *testing.T) {
|
||||
|
||||
// Reverse mode uses AESSIV
|
||||
func TestCreateConfFileAESSIV(t *testing.T) {
|
||||
err := Create("config_test/tmp.conf", testPw, false, 10, "test", true, false, nil)
|
||||
err := Create("config_test/tmp.conf", testPw, false, 10, "test", true, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -25,9 +25,6 @@ const (
|
||||
// Note that this flag does not change the password hashing algorithm
|
||||
// which always is scrypt.
|
||||
FlagHKDF
|
||||
// FlagTrezor means that "-trezor" was used when creating the filesystem.
|
||||
// The masterkey is protected using a Trezor device instead of a password.
|
||||
FlagTrezor
|
||||
)
|
||||
|
||||
// knownFlags stores the known feature flags and their string representation
|
||||
@ -40,7 +37,6 @@ var knownFlags = map[flagIota]string{
|
||||
FlagAESSIV: "AESSIV",
|
||||
FlagRaw64: "Raw64",
|
||||
FlagHKDF: "HKDF",
|
||||
FlagTrezor: "Trezor",
|
||||
}
|
||||
|
||||
// Filesystems that do not have these feature flags set are deprecated.
|
||||
|
@ -65,9 +65,7 @@ const (
|
||||
FsckErrors = 26
|
||||
// DeprecatedFS - this filesystem is deprecated
|
||||
DeprecatedFS = 27
|
||||
// TrezorError - an error was encountered while interacting with a Trezor
|
||||
// device
|
||||
TrezorError = 28
|
||||
// skip 28
|
||||
// ExcludeError - an error occurred while processing "-exclude"
|
||||
ExcludeError = 29
|
||||
// DevNull means that /dev/null could not be opened
|
||||
|
@ -1,119 +0,0 @@
|
||||
// +build enable_trezor
|
||||
|
||||
package readpassword
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
|
||||
"github.com/xaionaro-go/cryptoWallet"
|
||||
"github.com/xaionaro-go/cryptoWallet/vendors"
|
||||
)
|
||||
|
||||
const (
|
||||
// TrezorPayloadLen is the length of the payload data passed to Trezor's
|
||||
// CipherKeyValue function.
|
||||
TrezorPayloadLen = 32
|
||||
trezorNonce = "" // the "nonce" is optional and has no use in here
|
||||
trezorKeyName = "gocryptfs"
|
||||
trezorKeyDerivationPath = `m/10019'/0'`
|
||||
// TrezorSupport is true when gocryptfs has been compile with -tags enable_trezor
|
||||
TrezorSupport = true
|
||||
)
|
||||
|
||||
func trezorGetPin(title, description, ok, cancel string) ([]byte, error) {
|
||||
return Once("", title), nil
|
||||
}
|
||||
func trezorGetConfirm(title, description, ok, cancel string) (bool, error) {
|
||||
return false, nil // do not retry on connection failure
|
||||
}
|
||||
|
||||
// Trezor reads 32 deterministically derived bytes from a
|
||||
// SatoshiLabs Trezor USB security module.
|
||||
// The bytes are pseudorandom binary data and may contain null bytes.
|
||||
// This function either succeeds and returns 32 bytes or calls os.Exit to end
|
||||
// the application.
|
||||
func Trezor(payload []byte) []byte {
|
||||
if len(payload) != TrezorPayloadLen {
|
||||
tlog.Fatal.Printf("Invalid TrezorPayload length: wanted %d, got %d bytes\n", TrezorPayloadLen, len(payload))
|
||||
os.Exit(exitcodes.LoadConf)
|
||||
}
|
||||
|
||||
// Find all trezor devices
|
||||
trezors := cryptoWallet.Find(cryptoWallet.Filter{
|
||||
VendorID: &[]uint16{vendors.GetVendorID("satoshilabs")}[0],
|
||||
ProductIDs: []uint16{1 /* Trezor One */},
|
||||
})
|
||||
|
||||
// ATM, we require to one and only one trezor device to be connected.
|
||||
// The support of multiple trezor devices is not implemented, yet.
|
||||
if len(trezors) == 0 {
|
||||
tlog.Fatal.Printf("Trezor device is not found. Check the connection.")
|
||||
os.Exit(exitcodes.TrezorError)
|
||||
}
|
||||
if len(trezors) > 1 {
|
||||
tlog.Fatal.Printf("It's more than one Trezor device connected. This case is not implemented, yet. The number of currently connected devices: %v.", len(trezors))
|
||||
os.Exit(exitcodes.TrezorError)
|
||||
}
|
||||
|
||||
// Using the first found device
|
||||
trezor := trezors[0]
|
||||
|
||||
// Trezor may ask for PIN or Passphrase. Setting the handler for this case.
|
||||
trezor.SetGetPinFunc(trezorGetPin)
|
||||
|
||||
// In some cases (like lost connection to the Trezor device and cannot
|
||||
// reconnect) it's required to get a confirmation from the user to
|
||||
// retry to reconnect. Setting the handler for this case.
|
||||
trezor.SetGetConfirmFunc(trezorGetConfirm)
|
||||
|
||||
// To reset the state of the device and check if it's initialized.
|
||||
// If device is not initialized then trezor.Reset() will return an
|
||||
// error.
|
||||
err := trezor.Reset()
|
||||
if err != nil {
|
||||
tlog.Fatal.Printf("Cannot reset the Trezor device. Error: %v", err.Error())
|
||||
os.Exit(exitcodes.TrezorError)
|
||||
}
|
||||
|
||||
// To generate a deterministic key we trying to decrypt our
|
||||
// predefined constant key using the Trezor device. The resulting key
|
||||
// will depend on next variables:
|
||||
// * the Trezor master key;
|
||||
// * the passphrase (passed to the Trezor).
|
||||
//
|
||||
// The right key will be received only if both values (mentioned
|
||||
// above) are correct.
|
||||
//
|
||||
// Note:
|
||||
// Also the resulting key depends on this values (that we defined as
|
||||
// constants above):
|
||||
// * the key derivation path;
|
||||
// * the "encrypted" payload;
|
||||
// * the nonce;
|
||||
// * the key name.
|
||||
key, err := trezor.DecryptKey(trezorKeyDerivationPath, payload, []byte(trezorNonce), trezorKeyName)
|
||||
if err != nil {
|
||||
tlog.Fatal.Printf("Cannot get the key from the Trezor device. Error description:\n\t%v", err.Error())
|
||||
os.Exit(exitcodes.TrezorError)
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
if len(key) != TrezorPayloadLen {
|
||||
log.Panicf("BUG: decrypted value has wrong length %d", len(key))
|
||||
}
|
||||
if bytes.Equal(key, payload) {
|
||||
log.Panicf("BUG: payload and decrypted value are identical")
|
||||
}
|
||||
zero := make([]byte, TrezorPayloadLen)
|
||||
if bytes.Equal(key, zero) {
|
||||
log.Panicf("BUG: decrypted value is all-zero")
|
||||
}
|
||||
|
||||
// Everything ok
|
||||
return key
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// +build !enable_trezor
|
||||
|
||||
package readpassword
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
)
|
||||
|
||||
const (
|
||||
// TrezorPayloadLen is the length of the payload data passed to Trezor's
|
||||
// CipherKeyValue function.
|
||||
TrezorPayloadLen = 32
|
||||
// TrezorSupport is true when gocryptfs has been compile with -tags enable_trezor
|
||||
TrezorSupport = false
|
||||
)
|
||||
|
||||
// Trezor determinitically derives 32 bytes from the payload and the connected
|
||||
// USB security module.
|
||||
func Trezor(payload []byte) []byte {
|
||||
tlog.Fatal.Printf("This binary has been compiled without Trezor support")
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
31
main.go
31
main.go
@ -34,8 +34,7 @@ var raceDetector bool
|
||||
|
||||
// loadConfig loads the config file "args.config", prompting the user for the password
|
||||
func loadConfig(args *argContainer) (masterkey []byte, cf *configfile.ConfFile, err error) {
|
||||
// First check if the file can be read at all, and find out if a Trezor should
|
||||
// be used instead of a password.
|
||||
// First check if the file can be read at all.
|
||||
cf, err = configfile.Load(args.config)
|
||||
if err != nil {
|
||||
tlog.Fatal.Printf("Cannot open config file: %v", err)
|
||||
@ -47,14 +46,7 @@ func loadConfig(args *argContainer) (masterkey []byte, cf *configfile.ConfFile,
|
||||
masterkey = parseMasterKey(args.masterkey, false)
|
||||
return masterkey, cf, nil
|
||||
}
|
||||
var pw []byte
|
||||
if cf.IsFeatureFlagSet(configfile.FlagTrezor) {
|
||||
// Get binary data from Trezor
|
||||
pw = readpassword.Trezor(cf.TrezorPayload)
|
||||
} else {
|
||||
// Normal password entry
|
||||
pw = readpassword.Once([]string(args.extpass), args.passfile, "")
|
||||
}
|
||||
pw := readpassword.Once([]string(args.extpass), args.passfile, "")
|
||||
tlog.Info.Println("Decrypting master key")
|
||||
masterkey, err = cf.DecryptMasterKey(pw)
|
||||
for i := range pw {
|
||||
@ -71,20 +63,10 @@ func loadConfig(args *argContainer) (masterkey []byte, cf *configfile.ConfFile,
|
||||
// changePassword - change the password of config file "filename"
|
||||
// Does not return (calls os.Exit both on success and on error).
|
||||
func changePassword(args *argContainer) {
|
||||
// Parse the config file, but do not unlock the master key. We only want to
|
||||
// know if the Trezor flag is set.
|
||||
cf1, err := configfile.Load(args.config)
|
||||
if err != nil {
|
||||
tlog.Fatal.Printf("Cannot open config file: %v", err)
|
||||
os.Exit(exitcodes.LoadConf)
|
||||
}
|
||||
if cf1.IsFeatureFlagSet(configfile.FlagTrezor) {
|
||||
tlog.Fatal.Printf("Password change is not supported on Trezor-enabled filesystems.")
|
||||
os.Exit(exitcodes.Usage)
|
||||
}
|
||||
var confFile *configfile.ConfFile
|
||||
{
|
||||
var masterkey []byte
|
||||
var err error
|
||||
masterkey, confFile, err = loadConfig(args)
|
||||
if err != nil {
|
||||
exitcodes.Exit(err)
|
||||
@ -111,7 +93,7 @@ func changePassword(args *argContainer) {
|
||||
// "-masterkey"?
|
||||
if args.masterkey != "" {
|
||||
bak := args.config + ".bak"
|
||||
err = os.Link(args.config, bak)
|
||||
err := os.Link(args.config, bak)
|
||||
if err != nil {
|
||||
tlog.Fatal.Printf("Could not create backup file: %v", err)
|
||||
os.Exit(exitcodes.Init)
|
||||
@ -121,7 +103,7 @@ func changePassword(args *argContainer) {
|
||||
"Delete it after you have verified that you can access your files with the new password."+
|
||||
tlog.ColorReset, bak)
|
||||
}
|
||||
err = confFile.WriteFile()
|
||||
err := confFile.WriteFile()
|
||||
if err != nil {
|
||||
tlog.Fatal.Println(err)
|
||||
os.Exit(exitcodes.WriteConf)
|
||||
@ -136,9 +118,6 @@ func printVersion() {
|
||||
if stupidgcm.BuiltWithoutOpenssl {
|
||||
tagsSlice = append(tagsSlice, "without_openssl")
|
||||
}
|
||||
if readpassword.TrezorSupport {
|
||||
tagsSlice = append(tagsSlice, "enable_trezor")
|
||||
}
|
||||
tags := ""
|
||||
if tagsSlice != nil {
|
||||
tags = " " + strings.Join(tagsSlice, " ")
|
||||
|
@ -1,58 +0,0 @@
|
||||
package trezor
|
||||
|
||||
// Test operations with "-trezor".
|
||||
// See also the "cli" package - the tests there are very similar.
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/tests/test_helpers"
|
||||
)
|
||||
|
||||
func isTrezorConnected() bool {
|
||||
if runtime.GOOS != "linux" {
|
||||
return false
|
||||
}
|
||||
c := exec.Command("lsusb", "-d", "534c:0001")
|
||||
err := c.Run()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Test -init with -trezor
|
||||
func TestInitTrezor(t *testing.T) {
|
||||
if !isTrezorConnected() {
|
||||
t.Skip("No Trezor device connected")
|
||||
}
|
||||
t.Log("Trying gocryptfs -init -trezor ...")
|
||||
// vvvvvvvvvvvvv disable -extpass
|
||||
dir := test_helpers.InitFS(t, "-trezor", "-extpass", "")
|
||||
// The freshly created config file should have the Trezor feature flag set.
|
||||
c, err := configfile.Load(dir + "/" + configfile.ConfDefaultName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !c.IsFeatureFlagSet(configfile.FlagTrezor) {
|
||||
t.Error("Trezor flag should be set but is not")
|
||||
}
|
||||
if len(c.TrezorPayload) != 32 {
|
||||
t.Errorf("TrezorPayload has wrong length: %d", len(c.TrezorPayload))
|
||||
}
|
||||
}
|
||||
|
||||
// Test using -trezor together with -extpass. Should fail with code 1 (usage error).
|
||||
func TestTrezorExtpass(t *testing.T) {
|
||||
cmd := exec.Command(test_helpers.GocryptfsBinary, "-init", "-trezor", "-extpass", "foo", "/tmp")
|
||||
err := cmd.Run()
|
||||
exitCode := test_helpers.ExtractCmdExitCode(err)
|
||||
if exitCode != exitcodes.Usage {
|
||||
t.Errorf("wrong exit code: want %d, have %d", exitcodes.Usage, exitCode)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user