trezor: add skeleton for Trezor support
readpassword.Trezor() is not implemented yet and returns a hardcoded dummy key.
This commit is contained in:
parent
02ab358451
commit
c6f6e8ec4d
|
@ -22,7 +22,7 @@ type argContainer struct {
|
||||||
plaintextnames, quiet, nosyslog, wpanic,
|
plaintextnames, quiet, nosyslog, wpanic,
|
||||||
longnames, allow_other, reverse, aessiv, nonempty, raw64,
|
longnames, allow_other, reverse, aessiv, nonempty, raw64,
|
||||||
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
|
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
|
||||||
sharedstorage, devrandom, fsck bool
|
sharedstorage, devrandom, fsck, trezor bool
|
||||||
// Mount options with opposites
|
// Mount options with opposites
|
||||||
dev, nodev, suid, nosuid, exec, noexec, rw, ro bool
|
dev, nodev, suid, nosuid, exec, noexec, rw, ro bool
|
||||||
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
|
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
|
||||||
|
@ -138,6 +138,7 @@ func parseCliOpts() (args argContainer) {
|
||||||
flagSet.BoolVar(&args.sharedstorage, "sharedstorage", false, "Make concurrent access to a shared CIPHERDIR safer")
|
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.devrandom, "devrandom", false, "Use /dev/random for generating master key")
|
||||||
flagSet.BoolVar(&args.fsck, "fsck", false, "Run a filesystem check on CIPHERDIR")
|
flagSet.BoolVar(&args.fsck, "fsck", false, "Run a filesystem check on CIPHERDIR")
|
||||||
|
flagSet.BoolVar(&args.trezor, "trezor", false, "Protect the masterkey using a SatoshiLabs Trezor instead of a password")
|
||||||
|
|
||||||
// Mount options with opposites
|
// Mount options with opposites
|
||||||
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")
|
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")
|
||||||
|
|
21
init_dir.go
21
init_dir.go
|
@ -43,11 +43,12 @@ func isDir(dir string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initDir prepares a directory for use as a gocryptfs storage directory.
|
// initDir handles "gocryptfs -init". It prepares a directory for use as a
|
||||||
|
// gocryptfs storage directory.
|
||||||
// In forward mode, this means creating the gocryptfs.conf and gocryptfs.diriv
|
// In forward mode, this means creating the gocryptfs.conf and gocryptfs.diriv
|
||||||
// files in an empty directory.
|
// files in an empty directory.
|
||||||
// In reverse mode, we create .gocryptfs.reverse.conf and the directory does
|
// In reverse mode, we create .gocryptfs.reverse.conf and the directory does
|
||||||
// not to be empty.
|
// not need to be empty.
|
||||||
func initDir(args *argContainer) {
|
func initDir(args *argContainer) {
|
||||||
var err error
|
var err error
|
||||||
if args.reverse {
|
if args.reverse {
|
||||||
|
@ -68,10 +69,18 @@ func initDir(args *argContainer) {
|
||||||
tlog.Info.Printf("Choose a password for protecting your files.")
|
tlog.Info.Printf("Choose a password for protecting your files.")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
var password []byte
|
||||||
|
if args.trezor {
|
||||||
|
// Get binary data from from Trezor
|
||||||
|
password = readpassword.Trezor()
|
||||||
|
} else {
|
||||||
|
// Normal password entry
|
||||||
|
password = readpassword.Twice(args.extpass)
|
||||||
|
readpassword.CheckTrailingGarbage()
|
||||||
|
}
|
||||||
creator := tlog.ProgramName + " " + GitVersion
|
creator := tlog.ProgramName + " " + GitVersion
|
||||||
password := readpassword.Twice(args.extpass)
|
err = configfile.CreateConfFile(args.config, password, args.plaintextnames,
|
||||||
readpassword.CheckTrailingGarbage()
|
args.scryptn, creator, args.aessiv, args.devrandom, args.trezor)
|
||||||
err = configfile.CreateConfFile(args.config, password, args.plaintextnames, args.scryptn, creator, args.aessiv, args.devrandom)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tlog.Fatal.Println(err)
|
tlog.Fatal.Println(err)
|
||||||
os.Exit(exitcodes.WriteConf)
|
os.Exit(exitcodes.WriteConf)
|
||||||
|
@ -81,7 +90,7 @@ func initDir(args *argContainer) {
|
||||||
}
|
}
|
||||||
// password runs out of scope here
|
// password runs out of scope here
|
||||||
}
|
}
|
||||||
// Forward mode with filename encryption enabled needs a gocryptfs.diriv
|
// Forward mode with filename encryption enabled needs a gocryptfs.diriv file
|
||||||
// in the root dir
|
// in the root dir
|
||||||
if !args.plaintextnames && !args.reverse {
|
if !args.plaintextnames && !args.reverse {
|
||||||
err = nametransform.WriteDirIV(nil, args.cipherdir)
|
err = nametransform.WriteDirIV(nil, args.cipherdir)
|
||||||
|
|
|
@ -67,7 +67,8 @@ func randBytesDevRandom(n int) []byte {
|
||||||
// CreateConfFile - create a new config with a random key encrypted with
|
// CreateConfFile - create a new config with a random key encrypted with
|
||||||
// "password" and write it to "filename".
|
// "password" and write it to "filename".
|
||||||
// Uses scrypt with cost parameter logN.
|
// Uses scrypt with cost parameter logN.
|
||||||
func CreateConfFile(filename string, password []byte, plaintextNames bool, logN int, creator string, aessiv bool, devrandom bool) error {
|
func CreateConfFile(filename string, password []byte, plaintextNames bool,
|
||||||
|
logN int, creator string, aessiv bool, devrandom bool, trezor bool) error {
|
||||||
var cf ConfFile
|
var cf ConfFile
|
||||||
cf.filename = filename
|
cf.filename = filename
|
||||||
cf.Creator = creator
|
cf.Creator = creator
|
||||||
|
@ -87,6 +88,9 @@ func CreateConfFile(filename string, password []byte, plaintextNames bool, logN
|
||||||
if aessiv {
|
if aessiv {
|
||||||
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagAESSIV])
|
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagAESSIV])
|
||||||
}
|
}
|
||||||
|
if trezor {
|
||||||
|
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagTrezor])
|
||||||
|
}
|
||||||
{
|
{
|
||||||
// Generate new random master key
|
// Generate new random master key
|
||||||
var key []byte
|
var key []byte
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestLoadV2StrangeFeature(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateConfDefault(t *testing.T) {
|
func TestCreateConfDefault(t *testing.T) {
|
||||||
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, false)
|
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -83,14 +83,14 @@ func TestCreateConfDefault(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateConfDevRandom(t *testing.T) {
|
func TestCreateConfDevRandom(t *testing.T) {
|
||||||
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, true)
|
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", false, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateConfPlaintextnames(t *testing.T) {
|
func TestCreateConfPlaintextnames(t *testing.T) {
|
||||||
err := CreateConfFile("config_test/tmp.conf", testPw, true, 10, "test", false, false)
|
err := CreateConfFile("config_test/tmp.conf", testPw, true, 10, "test", false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ func TestCreateConfPlaintextnames(t *testing.T) {
|
||||||
|
|
||||||
// Reverse mode uses AESSIV
|
// Reverse mode uses AESSIV
|
||||||
func TestCreateConfFileAESSIV(t *testing.T) {
|
func TestCreateConfFileAESSIV(t *testing.T) {
|
||||||
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", true, false)
|
err := CreateConfFile("config_test/tmp.conf", testPw, false, 10, "test", true, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ const (
|
||||||
// Note that this flag does not change the password hashing algorithm
|
// Note that this flag does not change the password hashing algorithm
|
||||||
// which always is scrypt.
|
// which always is scrypt.
|
||||||
FlagHKDF
|
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
|
// knownFlags stores the known feature flags and their string representation
|
||||||
|
@ -37,6 +40,7 @@ var knownFlags = map[flagIota]string{
|
||||||
FlagAESSIV: "AESSIV",
|
FlagAESSIV: "AESSIV",
|
||||||
FlagRaw64: "Raw64",
|
FlagRaw64: "Raw64",
|
||||||
FlagHKDF: "HKDF",
|
FlagHKDF: "HKDF",
|
||||||
|
FlagTrezor: "Trezor",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filesystems that do not have these feature flags set are deprecated.
|
// Filesystems that do not have these feature flags set are deprecated.
|
||||||
|
|
|
@ -65,6 +65,9 @@ const (
|
||||||
FsckErrors = 26
|
FsckErrors = 26
|
||||||
// DeprecatedFS - this filesystem is deprecated
|
// DeprecatedFS - this filesystem is deprecated
|
||||||
DeprecatedFS = 27
|
DeprecatedFS = 27
|
||||||
|
// TrezorError - an error was encountered while interacting with a Trezor
|
||||||
|
// device
|
||||||
|
TrezorError = 28
|
||||||
)
|
)
|
||||||
|
|
||||||
// Err wraps an error with an associated numeric exit code
|
// Err wraps an error with an associated numeric exit code
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package readpassword
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Trezor reads 16 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 16 bytes or calls os.Exit to end
|
||||||
|
// the application.
|
||||||
|
func Trezor() []byte {
|
||||||
|
var err error
|
||||||
|
// TODO try to read bytes here....
|
||||||
|
// Handle errors
|
||||||
|
if err != nil {
|
||||||
|
tlog.Fatal.Printf("xxx some error was encountered...")
|
||||||
|
os.Exit(exitcodes.TrezorError)
|
||||||
|
}
|
||||||
|
|
||||||
|
tlog.Warn.Println("XXX readpassword.Trezor(): not implemented yet - returning hardcoded dummy bytes XXX")
|
||||||
|
return []byte("1234567890123456")
|
||||||
|
}
|
38
main.go
38
main.go
|
@ -33,26 +33,33 @@ var raceDetector bool
|
||||||
|
|
||||||
// loadConfig loads the config file "args.config", prompting the user for the password
|
// loadConfig loads the config file "args.config", prompting the user for the password
|
||||||
func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.ConfFile, err error) {
|
func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.ConfFile, err error) {
|
||||||
// Check if the file can be opened at all before prompting for a password
|
// First check if the file can be read at all, and find out if a Trezor should
|
||||||
fd, err := os.Open(args.config)
|
// be used instead of a password.
|
||||||
|
_, cf1, err := configfile.LoadConfFile(args.config, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tlog.Fatal.Printf("Cannot open config file: %v", err)
|
tlog.Fatal.Printf("Cannot open config file: %v", err)
|
||||||
return nil, nil, exitcodes.NewErr(err.Error(), exitcodes.OpenConf)
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
fd.Close()
|
// The user has passed the master key on the command line (probably because
|
||||||
// The user has passed the master key (probably because he forgot the
|
// he forgot the password).
|
||||||
// password).
|
|
||||||
if args.masterkey != "" {
|
if args.masterkey != "" {
|
||||||
masterkey = parseMasterKey(args.masterkey, false)
|
masterkey = parseMasterKey(args.masterkey, false)
|
||||||
_, confFile, err = configfile.LoadConfFile(args.config, nil)
|
return masterkey, cf1, nil
|
||||||
} else {
|
|
||||||
pw := readpassword.Once(args.extpass, "")
|
|
||||||
tlog.Info.Println("Decrypting master key")
|
|
||||||
masterkey, confFile, err = configfile.LoadConfFile(args.config, pw)
|
|
||||||
for i := range pw {
|
|
||||||
pw[i] = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
var pw []byte
|
||||||
|
if cf1.IsFeatureFlagSet(configfile.FlagTrezor) {
|
||||||
|
// Get binary data from from Trezor
|
||||||
|
pw = readpassword.Trezor()
|
||||||
|
} else {
|
||||||
|
// Normal password entry
|
||||||
|
pw = readpassword.Once(args.extpass, "")
|
||||||
|
}
|
||||||
|
tlog.Info.Println("Decrypting master key")
|
||||||
|
masterkey, confFile, err = configfile.LoadConfFile(args.config, pw)
|
||||||
|
for i := range pw {
|
||||||
|
pw[i] = 0
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tlog.Fatal.Println(err)
|
tlog.Fatal.Println(err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -71,6 +78,9 @@ func changePassword(args *argContainer) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exitcodes.Exit(err)
|
exitcodes.Exit(err)
|
||||||
}
|
}
|
||||||
|
if len(masterkey) == 0 {
|
||||||
|
panic("empty masterkey")
|
||||||
|
}
|
||||||
tlog.Info.Println("Please enter your new password.")
|
tlog.Info.Println("Please enter your new password.")
|
||||||
newPw := readpassword.Twice(args.extpass)
|
newPw := readpassword.Twice(args.extpass)
|
||||||
readpassword.CheckTrailingGarbage()
|
readpassword.CheckTrailingGarbage()
|
||||||
|
|
|
@ -103,7 +103,9 @@ func getMasterKey(args *argContainer) (masterkey []byte, confFile *configfile.Co
|
||||||
}
|
}
|
||||||
exitcodes.Exit(err)
|
exitcodes.Exit(err)
|
||||||
}
|
}
|
||||||
readpassword.CheckTrailingGarbage()
|
if !args.trezor {
|
||||||
|
readpassword.CheckTrailingGarbage()
|
||||||
|
}
|
||||||
if !args.fsck {
|
if !args.fsck {
|
||||||
// We only want to print the masterkey message on a normal mount.
|
// We only want to print the masterkey message on a normal mount.
|
||||||
printMasterKey(masterkey)
|
printMasterKey(masterkey)
|
||||||
|
|
|
@ -69,6 +69,7 @@ func TestExampleFses(t *testing.T) {
|
||||||
fsNames = append(fsNames, e.Name())
|
fsNames = append(fsNames, e.Name())
|
||||||
}
|
}
|
||||||
for _, n := range fsNames {
|
for _, n := range fsNames {
|
||||||
|
t.Logf("Checking %q", n)
|
||||||
path := "../example_filesystems/" + n
|
path := "../example_filesystems/" + n
|
||||||
cmd := exec.Command(test_helpers.GocryptfsBinary, "-fsck", "-extpass", "echo test", path)
|
cmd := exec.Command(test_helpers.GocryptfsBinary, "-fsck", "-extpass", "echo test", path)
|
||||||
outBin, err := cmd.CombinedOutput()
|
outBin, err := cmd.CombinedOutput()
|
||||||
|
|
Loading…
Reference in New Issue