Skip to content

Commit f02fa5c

Browse files
committed
trezor: add skeleton for Trezor support
readpassword.Trezor() is not implemented yet and returns a hardcoded dummy key.
1 parent 009cc0a commit f02fa5c

File tree

10 files changed

+86
-26
lines changed

10 files changed

+86
-26
lines changed

cli_args.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type argContainer struct {
2222
plaintextnames, quiet, nosyslog, wpanic,
2323
longnames, allow_other, reverse, aessiv, nonempty, raw64,
2424
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
25-
sharedstorage, devrandom, fsck bool
25+
sharedstorage, devrandom, fsck, trezorkey bool
2626
// Mount options with opposites
2727
dev, nodev, suid, nosuid, exec, noexec, rw, ro bool
2828
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
@@ -138,6 +138,7 @@ func parseCliOpts() (args argContainer) {
138138
flagSet.BoolVar(&args.sharedstorage, "sharedstorage", false, "Make concurrent access to a shared CIPHERDIR safer")
139139
flagSet.BoolVar(&args.devrandom, "devrandom", false, "Use /dev/random for generating master key")
140140
flagSet.BoolVar(&args.fsck, "fsck", false, "Run a filesystem check on CIPHERDIR")
141+
flagSet.BoolVar(&args.trezorkey, "trezorkey", false, "Protect the masterkey using a SatoshiLabs Trezor")
141142

142143
// Mount options with opposites
143144
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")

init_dir.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ func isDir(dir string) error {
4343
return nil
4444
}
4545

46-
// initDir prepares a directory for use as a gocryptfs storage directory.
46+
// initDir handles "gocryptfs -init". It prepares a directory for use as a
47+
// gocryptfs storage directory.
4748
// In forward mode, this means creating the gocryptfs.conf and gocryptfs.diriv
4849
// files in an empty directory.
4950
// In reverse mode, we create .gocryptfs.reverse.conf and the directory does
50-
// not to be empty.
51+
// not need to be empty.
5152
func initDir(args *argContainer) {
5253
var err error
5354
if args.reverse {
@@ -68,10 +69,18 @@ func initDir(args *argContainer) {
6869
tlog.Info.Printf("Choose a password for protecting your files.")
6970
}
7071
{
72+
var password []byte
73+
if args.trezorkey {
74+
// Get binary data from from Trezor
75+
password = readpassword.Trezor()
76+
} else {
77+
// Normal password entry
78+
password = readpassword.Twice(args.extpass)
79+
readpassword.CheckTrailingGarbage()
80+
}
7181
creator := tlog.ProgramName + " " + GitVersion
72-
password := readpassword.Twice(args.extpass)
73-
readpassword.CheckTrailingGarbage()
74-
err = configfile.CreateConfFile(args.config, password, args.plaintextnames, args.scryptn, creator, args.aessiv, args.devrandom)
82+
err = configfile.CreateConfFile(args.config, password, args.plaintextnames,
83+
args.scryptn, creator, args.aessiv, args.devrandom, args.trezorkey)
7584
if err != nil {
7685
tlog.Fatal.Println(err)
7786
os.Exit(exitcodes.WriteConf)
@@ -81,7 +90,7 @@ func initDir(args *argContainer) {
8190
}
8291
// password runs out of scope here
8392
}
84-
// Forward mode with filename encryption enabled needs a gocryptfs.diriv
93+
// Forward mode with filename encryption enabled needs a gocryptfs.diriv file
8594
// in the root dir
8695
if !args.plaintextnames && !args.reverse {
8796
err = nametransform.WriteDirIV(nil, args.cipherdir)

internal/configfile/config_file.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ func randBytesDevRandom(n int) []byte {
6767
// CreateConfFile - create a new config with a random key encrypted with
6868
// "password" and write it to "filename".
6969
// Uses scrypt with cost parameter logN.
70-
func CreateConfFile(filename string, password []byte, plaintextNames bool, logN int, creator string, aessiv bool, devrandom bool) error {
70+
func CreateConfFile(filename string, password []byte, plaintextNames bool,
71+
logN int, creator string, aessiv bool, devrandom bool, trezorkey bool) error {
7172
var cf ConfFile
7273
cf.filename = filename
7374
cf.Creator = creator
@@ -87,6 +88,9 @@ func CreateConfFile(filename string, password []byte, plaintextNames bool, logN
8788
if aessiv {
8889
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagAESSIV])
8990
}
91+
if trezorkey {
92+
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagTrezorKey])
93+
}
9094
{
9195
// Generate new random master key
9296
var key []byte

internal/configfile/config_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestLoadV2StrangeFeature(t *testing.T) {
6262
}
6363

6464
func TestCreateConfDefault(t *testing.T) {
65-
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, false)
65+
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, false, false)
6666
if err != nil {
6767
t.Fatal(err)
6868
}
@@ -83,14 +83,14 @@ func TestCreateConfDefault(t *testing.T) {
8383
}
8484

8585
func TestCreateConfDevRandom(t *testing.T) {
86-
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, true)
86+
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, true, false)
8787
if err != nil {
8888
t.Fatal(err)
8989
}
9090
}
9191

9292
func TestCreateConfPlaintextnames(t *testing.T) {
93-
err := CreateConfFile("config_test/tmp.conf", testPw, true, 10, "test", false, false)
93+
err := CreateConfFile("config_test/tmp.conf", testPw, true, 10, "test", false, false, false)
9494
if err != nil {
9595
t.Fatal(err)
9696
}
@@ -111,7 +111,7 @@ func TestCreateConfPlaintextnames(t *testing.T) {
111111

112112
// Reverse mode uses AESSIV
113113
func TestCreateConfFileAESSIV(t *testing.T) {
114-
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", true, false)
114+
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", true, false, false)
115115
if err != nil {
116116
t.Fatal(err)
117117
}

internal/configfile/feature_flags.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ const (
2525
// Note that this flag does not change the password hashing algorithm
2626
// which always is scrypt.
2727
FlagHKDF
28+
// FlagTrezorKey means that "-trezorkey" was used when creating the filesystem.
29+
// The masterkey is protected using a Trezor device instead of a password.
30+
FlagTrezorKey
2831
)
2932

3033
// knownFlags stores the known feature flags and their string representation
@@ -37,6 +40,7 @@ var knownFlags = map[flagIota]string{
3740
FlagAESSIV: "AESSIV",
3841
FlagRaw64: "Raw64",
3942
FlagHKDF: "HKDF",
43+
FlagTrezorKey: "TrezorKey",
4044
}
4145

4246
// Filesystems that do not have these feature flags set are deprecated.

internal/exitcodes/exitcodes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ const (
6565
FsckErrors = 26
6666
// DeprecatedFS - this filesystem is deprecated
6767
DeprecatedFS = 27
68+
// TrezorError - an error was encountered while interacting with a Trezor
69+
// device
70+
TrezorError = 28
6871
)
6972

7073
// Err wraps an error with an associated numeric exit code

internal/readpassword/trezor.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package readpassword
2+
3+
import (
4+
"os"
5+
6+
"github.com/rfjakob/gocryptfs/internal/exitcodes"
7+
"github.com/rfjakob/gocryptfs/internal/tlog"
8+
)
9+
10+
// Trezor reads 16 deterministically derived bytes from a
11+
// SatoshiLabs Trezor USB security module.
12+
// The bytes are pseudorandom binary data and may contain null bytes.
13+
// This function either succeeds and returns 16 bytes or calls os.Exit to end
14+
// the application.
15+
func Trezor() []byte {
16+
var err error
17+
// TODO try to read bytes here....
18+
// Handle errors
19+
if err != nil {
20+
tlog.Fatal.Printf("xxx some error was encountered...")
21+
os.Exit(exitcodes.TrezorError)
22+
}
23+
24+
tlog.Warn.Println("XXX readpassword.Trezor(): not implemented yet - returning hardcoded dummy bytes XXX")
25+
return []byte("1234567890123456")
26+
}

main.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,33 @@ var raceDetector bool
3333

3434
// loadConfig loads the config file "args.config", prompting the user for the password
3535
func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.ConfFile, err error) {
36-
// Check if the file can be opened at all before prompting for a password
37-
fd, err := os.Open(args.config)
36+
// First check if the file can be read at all, and find out if a Trezor should
37+
// be used instead of a password.
38+
_, cf1, err := configfile.LoadConfFile(args.config, nil)
3839
if err != nil {
3940
tlog.Fatal.Printf("Cannot open config file: %v", err)
40-
return nil, nil, exitcodes.NewErr(err.Error(), exitcodes.OpenConf)
41+
return nil, nil, err
4142
}
42-
fd.Close()
43-
// The user has passed the master key (probably because he forgot the
44-
// password).
43+
// The user has passed the master key on the command line (probably because
44+
// he forgot the password).
4545
if args.masterkey != "" {
4646
masterkey = parseMasterKey(args.masterkey, false)
47-
_, confFile, err = configfile.LoadConfFile(args.config, nil)
47+
return masterkey, cf1, nil
48+
}
49+
var pw []byte
50+
if cf1.IsFeatureFlagSet(configfile.FlagTrezorKey) {
51+
// Get binary data from from Trezor
52+
pw = readpassword.Trezor()
4853
} else {
49-
pw := readpassword.Once(args.extpass, "")
50-
tlog.Info.Println("Decrypting master key")
51-
masterkey, confFile, err = configfile.LoadConfFile(args.config, pw)
52-
for i := range pw {
53-
pw[i] = 0
54-
}
54+
// Normal password entry
55+
pw = readpassword.Once(args.extpass, "")
5556
}
57+
tlog.Info.Println("Decrypting master key")
58+
masterkey, confFile, err = configfile.LoadConfFile(args.config, pw)
59+
for i := range pw {
60+
pw[i] = 0
61+
}
62+
5663
if err != nil {
5764
tlog.Fatal.Println(err)
5865
return nil, nil, err
@@ -71,6 +78,9 @@ func changePassword(args *argContainer) {
7178
if err != nil {
7279
exitcodes.Exit(err)
7380
}
81+
if len(masterkey) == 0 {
82+
panic("empty masterkey")
83+
}
7484
tlog.Info.Println("Please enter your new password.")
7585
newPw := readpassword.Twice(args.extpass)
7686
readpassword.CheckTrailingGarbage()

masterkey.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ func getMasterKey(args *argContainer) (masterkey []byte, confFile *configfile.Co
103103
}
104104
exitcodes.Exit(err)
105105
}
106-
readpassword.CheckTrailingGarbage()
106+
if !args.trezorkey {
107+
readpassword.CheckTrailingGarbage()
108+
}
107109
if !args.fsck {
108110
// We only want to print the masterkey message on a normal mount.
109111
printMasterKey(masterkey)

tests/fsck/fsck_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func TestExampleFses(t *testing.T) {
6969
fsNames = append(fsNames, e.Name())
7070
}
7171
for _, n := range fsNames {
72+
t.Logf("Checking %q", n)
7273
path := "../example_filesystems/" + n
7374
cmd := exec.Command(test_helpers.GocryptfsBinary, "-fsck", "-extpass", "echo test", path)
7475
outBin, err := cmd.CombinedOutput()

0 commit comments

Comments
 (0)