aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-09-25 15:05:09 +0200
committerJakob Unterwurzacher2016-09-25 16:43:17 +0200
commit2050c7f3b3822a4a3329d4ba5b146d269ef05b4d (patch)
tree69e5639a02498e37fa4f1aa3af6f605f756f42cc
parentf8da264222f7348c6b9e6dd9d372200f850d2878 (diff)
reverse: add gcmsiv flag and associated tests
-rw-r--r--Documentation/MANPAGE.md9
-rw-r--r--cli_args.go3
-rw-r--r--init_dir.go16
-rw-r--r--internal/configfile/config_file.go8
-rw-r--r--internal/configfile/config_test.go4
-rw-r--r--main.go20
-rwxr-xr-xtest.bash4
-rw-r--r--tests/normal/cli_test.go59
-rw-r--r--tests/reverse/correctness_test.go17
-rw-r--r--tests/reverse/longname_perf_test.go45
-rw-r--r--tests/reverse/main_test.go32
11 files changed, 153 insertions, 64 deletions
diff --git a/Documentation/MANPAGE.md b/Documentation/MANPAGE.md
index bf696f1..5c31a92 100644
--- a/Documentation/MANPAGE.md
+++ b/Documentation/MANPAGE.md
@@ -58,6 +58,9 @@ to mount the gocryptfs filesytem without user interaction.
**-fusedebug**
: Enable fuse library debug output
+**-gcmsiv**
+: Use the GCM-SIV encryption mode (implied by -reverse)
+
**-init**
: Initialize encrypted directory
@@ -94,7 +97,7 @@ runs as root, you can enable device files by passing the opposite mount option,
interesting. For a complete liste see the section
`FILESYSTEM-INDEPENDENT MOUNT OPTIONS` in mount(8).
-**-openssl bool**
+**-openssl bool/"auto"**
: Use OpenSSL instead of built-in Go crypto (default "auto"). Using
built-in crypto is 4x slower unless your CPU has AES instructions and
you are using Go 1.6+. In mode "auto", gocrypts chooses the faster
@@ -109,6 +112,10 @@ option.
**-q, -quiet**
: Quiet - silence informational messages
+**-reverse**
+: Reverse mode shows a read-only encrypted view of a plaintext
+directory
+
**-ro**
: Mount the filesystem read-only
diff --git a/cli_args.go b/cli_args.go
index 4c91f44..b50c350 100644
--- a/cli_args.go
+++ b/cli_args.go
@@ -14,7 +14,7 @@ import (
type argContainer struct {
debug, init, zerokey, fusedebug, openssl, passwd, foreground, version,
plaintextnames, quiet, nosyslog, wpanic,
- longnames, allow_other, ro, reverse bool
+ longnames, allow_other, ro, reverse, gcmsiv bool
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
memprofile, o string
// Configuration file name override
@@ -51,6 +51,7 @@ func parseCliOpts() (args argContainer) {
"Only works if user_allow_other is set in /etc/fuse.conf.")
flagSet.BoolVar(&args.ro, "ro", false, "Mount the filesystem read-only")
flagSet.BoolVar(&args.reverse, "reverse", false, "Reverse mode")
+ flagSet.BoolVar(&args.gcmsiv, "gcmsiv", false, "GCM-SIV encryption")
flagSet.StringVar(&args.masterkey, "masterkey", "", "Mount with explicit master key")
flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
diff --git a/init_dir.go b/init_dir.go
index fac4053..c9c7be6 100644
--- a/init_dir.go
+++ b/init_dir.go
@@ -39,7 +39,7 @@ func initDir(args *argContainer) {
}
password := readpassword.Twice(args.extpass)
creator := tlog.ProgramName + " " + GitVersion
- err = configfile.CreateConfFile(args.config, password, args.plaintextnames, args.scryptn, creator, args.reverse)
+ err = configfile.CreateConfFile(args.config, password, args.plaintextnames, args.scryptn, creator, args.gcmsiv)
if err != nil {
tlog.Fatal.Println(err)
os.Exit(ERREXIT_INIT)
@@ -53,8 +53,14 @@ func initDir(args *argContainer) {
os.Exit(ERREXIT_INIT)
}
}
-
- tlog.Info.Printf(tlog.ColorGreen + "The filesystem has been created successfully." + tlog.ColorReset)
+ mountArgs := ""
+ fsName := "gocryptfs"
+ if args.reverse {
+ mountArgs = " -reverse"
+ fsName = "gocryptfs-reverse"
+ }
+ tlog.Info.Printf(tlog.ColorGreen+"The %s filesystem has been created successfully."+tlog.ColorReset,
+ fsName)
wd, _ := os.Getwd()
friendlyPath, _ := filepath.Rel(wd, args.cipherdir)
if strings.HasPrefix(friendlyPath, "../") {
@@ -62,7 +68,7 @@ func initDir(args *argContainer) {
// keep the absolute path.
friendlyPath = args.cipherdir
}
- tlog.Info.Printf(tlog.ColorGrey+"You can now mount it using: %s %s MOUNTPOINT"+tlog.ColorReset,
- tlog.ProgramName, friendlyPath)
+ tlog.Info.Printf(tlog.ColorGrey+"You can now mount it using: %s%s %s MOUNTPOINT"+tlog.ColorReset,
+ tlog.ProgramName, mountArgs, friendlyPath)
os.Exit(0)
}
diff --git a/internal/configfile/config_file.go b/internal/configfile/config_file.go
index b1504b4..32e7e66 100644
--- a/internal/configfile/config_file.go
+++ b/internal/configfile/config_file.go
@@ -45,7 +45,7 @@ type ConfFile struct {
// CreateConfFile - create a new config with a random key encrypted with
// "password" and write it to "filename".
// Uses scrypt with cost parameter logN.
-func CreateConfFile(filename string, password string, plaintextNames bool, logN int, creator string, reverse bool) error {
+func CreateConfFile(filename string, password string, plaintextNames bool, logN int, creator string, gcmsiv bool) error {
var cf ConfFile
cf.filename = filename
cf.Creator = creator
@@ -59,7 +59,7 @@ func CreateConfFile(filename string, password string, plaintextNames bool, logN
cf.EncryptKey(key, password, logN)
// Set feature flags
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagGCMIV128])
+ cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagGCMIV128]) // 128-bit IVs
if plaintextNames {
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagPlaintextNames])
} else {
@@ -67,8 +67,8 @@ func CreateConfFile(filename string, password string, plaintextNames bool, logN
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagEMENames])
cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagLongNames])
}
- if reverse {
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagGCMSIV])
+ if gcmsiv {
+ cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagGCMSIV]) // GCM-SIV encryption mode
}
// Write file to disk
diff --git a/internal/configfile/config_test.go b/internal/configfile/config_test.go
index 72c25f6..ac85c8d 100644
--- a/internal/configfile/config_test.go
+++ b/internal/configfile/config_test.go
@@ -71,7 +71,7 @@ func TestCreateConfFile(t *testing.T) {
}
-func TestCreateConfFileReverse(t *testing.T) {
+func TestCreateConfFileGCMSIV(t *testing.T) {
err := CreateConfFile("config_test/tmp.conf", "test", false, 10, "test", true)
if err != nil {
t.Fatal(err)
@@ -87,7 +87,7 @@ func TestCreateConfFileReverse(t *testing.T) {
func TestIsFeatureFlagKnown(t *testing.T) {
// Test a few hardcoded values
- testKnownFlags := []string{"DirIV", "PlaintextNames", "EMENames", "GCMIV128", "LongNames"}
+ testKnownFlags := []string{"DirIV", "PlaintextNames", "EMENames", "GCMIV128", "LongNames", "GCMSIV"}
// And also everything in knownFlags (yes, it is likely that we end up with
// some duplicates. Does not matter.)
for _, f := range knownFlags {
diff --git a/main.go b/main.go
index ea9efad..e2777b0 100644
--- a/main.go
+++ b/main.go
@@ -111,11 +111,9 @@ func printVersion() {
func main() {
runtime.GOMAXPROCS(4)
var err error
-
// Parse all command-line options (i.e. arguments starting with "-")
// into "args". Path arguments are parsed below.
args := parseCliOpts()
-
// Fork a child into the background if "-f" is not set AND we are mounting
// a filesystem. The child will do all the work.
if !args.foreground && flagSet.NArg() == 2 {
@@ -152,6 +150,10 @@ func main() {
if args.quiet {
tlog.Info.Enabled = false
}
+ // "-reverse" implies "-gcmsiv"
+ if args.reverse {
+ args.gcmsiv = true
+ }
// "-config"
if args.config != "" {
args.config, err = filepath.Abs(args.config)
@@ -201,7 +203,7 @@ func main() {
} else {
tlog.Debug.Printf("OpenSSL enabled")
}
- // Operation flags: init, passwd or mount
+ // Operation flags: -init or -passwd; otherwise: mount
// "-init"
if args.init {
if flagSet.NArg() > 1 {
@@ -288,8 +290,7 @@ func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFi
if args.openssl {
cryptoBackend = cryptocore.BackendOpenSSL
}
- if args.reverse {
- // reverse implies GCMSIV
+ if args.gcmsiv {
cryptoBackend = cryptocore.BackendGCMSIV
}
frontendArgs := fusefrontend.Args{
@@ -306,7 +307,7 @@ func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFi
if confFile.IsFeatureFlagSet(configfile.FlagGCMSIV) {
frontendArgs.CryptoBackend = cryptocore.BackendGCMSIV
} else if args.reverse {
- tlog.Fatal.Printf("GCMSIV is required by reverse mode, but not enabled in the config file")
+ tlog.Fatal.Printf("GCM-SIV is required by reverse mode, but not enabled in the config file")
os.Exit(ERREXIT_USAGE)
}
}
@@ -317,11 +318,14 @@ func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFi
}
jsonBytes, _ := json.MarshalIndent(frontendArgs, "", "\t")
tlog.Debug.Printf("frontendArgs: %s", string(jsonBytes))
-
+ if frontendArgs.CryptoBackend == cryptocore.BackendGCMSIV {
+ tlog.Info.Printf(tlog.ColorYellow +
+ "Warning: The GCM-SIV format used by reverse mode is not yet finalized.\n" +
+ "The on-disk format will change in the future." + tlog.ColorReset)
+ }
var finalFs pathfs.FileSystem
if args.reverse {
finalFs = fusefrontend_reverse.NewFS(frontendArgs)
- tlog.Info.Printf(tlog.ColorYellow + "REVERSE MODE IS EXPERIMENTAL!" + tlog.ColorReset)
} else {
finalFs = fusefrontend.NewFS(frontendArgs)
}
diff --git a/test.bash b/test.bash
index 2a565b7..8711d8f 100755
--- a/test.bash
+++ b/test.bash
@@ -8,8 +8,8 @@ source build.bash
go test ./... $*
-# Clean up after ourself, but don't descend into maybe still mounted
-# example filesystems
+# Clean up after ourself, but don't descend into possibly still mounted
+# example filesystems.
# The tests cannot to this themselves as they are run in parallel
rm -Rf --one-file-system /tmp/gocryptfs-test-parent
diff --git a/tests/normal/cli_test.go b/tests/normal/cli_test.go
index ed3111b..62ad217 100644
--- a/tests/normal/cli_test.go
+++ b/tests/normal/cli_test.go
@@ -5,7 +5,6 @@ package normal
import (
"os"
"os/exec"
- "path/filepath"
"testing"
"github.com/rfjakob/gocryptfs/internal/configfile"
@@ -24,18 +23,45 @@ func TestMain(m *testing.M) {
// Test -init flag
func TestInit(t *testing.T) {
dir := test_helpers.InitFS(t)
- _, err := os.Stat(filepath.Join(dir, configfile.ConfDefaultName))
+ _, c, err := configfile.LoadConfFile(dir+"/"+configfile.ConfDefaultName, "test")
if err != nil {
t.Fatal(err)
}
+ if c.IsFeatureFlagSet(configfile.FlagGCMSIV) {
+ t.Error("GCMSIV flag should not be set")
+ }
}
-// Test -passwd flag
-func TestPasswd(t *testing.T) {
- // Create FS
- dir := test_helpers.InitFS(t)
+// Test -init with -gcmsiv
+func TestInitGcmsiv(t *testing.T) {
+ dir := test_helpers.InitFS(t, "-gcmsiv")
+ _, c, err := configfile.LoadConfFile(dir+"/"+configfile.ConfDefaultName, "test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !c.IsFeatureFlagSet(configfile.FlagGCMSIV) {
+ t.Error("GCMSIV flag should be set but is not")
+ }
+}
+
+// Test -init with -reverse
+func TestInitReverse(t *testing.T) {
+ dir := test_helpers.InitFS(t, "-reverse")
+ _, c, err := configfile.LoadConfFile(dir+"/"+configfile.ConfReverseName, "test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !c.IsFeatureFlagSet(configfile.FlagGCMSIV) {
+ t.Error("GCMSIV flag should be set but is not")
+ }
+}
+
+func testPasswd(t *testing.T, dir string, extraArgs ...string) {
// Change password using "-extpass"
- cmd := exec.Command(test_helpers.GocryptfsBinary, "-q", "-passwd", "-extpass", "echo test", dir)
+ args := []string{"-q", "-passwd", "-extpass", "echo test"}
+ args = append(args, extraArgs...)
+ args = append(args, dir)
+ cmd := exec.Command(test_helpers.GocryptfsBinary, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
@@ -43,7 +69,10 @@ func TestPasswd(t *testing.T) {
t.Error(err)
}
// Change password using stdin
- cmd = exec.Command(test_helpers.GocryptfsBinary, "-q", "-passwd", dir)
+ args = []string{"-q", "-passwd", "-extpass", "echo test"}
+ args = append(args, extraArgs...)
+ args = append(args, dir)
+ cmd = exec.Command(test_helpers.GocryptfsBinary, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
p, err := cmd.StdinPipe()
@@ -65,6 +94,20 @@ func TestPasswd(t *testing.T) {
}
}
+// Test -passwd flag
+func TestPasswd(t *testing.T) {
+ // Create FS
+ dir := test_helpers.InitFS(t)
+ testPasswd(t, dir)
+}
+
+// Test -passwd with -reverse
+func TestPasswdReverse(t *testing.T) {
+ // Create FS
+ dir := test_helpers.InitFS(t, "-reverse")
+ testPasswd(t, dir, "-reverse")
+}
+
// Test -init & -config flag
func TestInitConfig(t *testing.T) {
config := test_helpers.TmpDir + "/TestInitConfig.conf"
diff --git a/tests/reverse/correctness_test.go b/tests/reverse/correctness_test.go
new file mode 100644
index 0000000..e268815
--- /dev/null
+++ b/tests/reverse/correctness_test.go
@@ -0,0 +1,17 @@
+package reverse_test
+
+import (
+ "os"
+ "testing"
+)
+
+func TestLongnameStat(t *testing.T) {
+ _, err := os.Stat(dirA + "/" + "")
+ if err != nil {
+ t.Error(err)
+ }
+ _, err = os.Stat(dirA + "/" + "")
+ if err != nil {
+ t.Error(err)
+ }
+}
diff --git a/tests/reverse/longname_perf_test.go b/tests/reverse/longname_perf_test.go
index 43acd25..f170ad7 100644
--- a/tests/reverse/longname_perf_test.go
+++ b/tests/reverse/longname_perf_test.go
@@ -5,34 +5,17 @@ import (
"fmt"
"os"
"testing"
-
- "github.com/rfjakob/gocryptfs/tests/test_helpers"
)
-var dirA, dirB, x240 string
-
-func TestMain(m *testing.M) {
- x240 = string(bytes.Repeat([]byte("x"), 240))
- dirA = test_helpers.TmpDir + "/a"
- dirB = test_helpers.TmpDir + "/b"
- os.Mkdir(dirA, 0700)
- os.Mkdir(dirB, 0700)
- generateFiles(dirA)
- test_helpers.MountOrExit(dirA, dirB, "-zerokey", "-reverse")
- r := m.Run()
- test_helpers.UnmountPanic(dirB)
- os.RemoveAll(test_helpers.TmpDir)
- os.Exit(r)
-}
-
-func genName(i int) string {
- return fmt.Sprintf("%04d.%s", i, x240)
+func genName(i int, postfix string) string {
+ return fmt.Sprintf("%04d.%s", i, postfix)
}
// Create 10000 files with long names
-func generateFiles(dir string) {
+func generateLongnameFiles(dir string) {
+ x240 := string(bytes.Repeat([]byte("x"), 240))
for i := 0; i < 100000; i++ {
- n := genName(i)
+ n := genName(i, x240)
f, err := os.Create(dir + "/" + n)
if err != nil {
panic(err)
@@ -41,18 +24,9 @@ func generateFiles(dir string) {
}
}
-func TestLongnameStat(t *testing.T) {
- _, err := os.Stat(dirA + "/" + genName(0))
- if err != nil {
- t.Error(err)
- }
- _, err = os.Stat(dirA + "/" + genName(9999))
- if err != nil {
- t.Error(err)
- }
-}
-
func BenchmarkLongnameStat(b *testing.B) {
+ // Setup
+ generateLongnameFiles(dirA)
dirFd, err := os.Open(dirB)
if err != nil {
b.Fatal(err)
@@ -63,6 +37,7 @@ func BenchmarkLongnameStat(b *testing.B) {
}
l := len(encryptedNames)
dirFd.Close()
+ // Benchmark
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := os.Stat(dirB + "/" + encryptedNames[i%l])
@@ -70,4 +45,8 @@ func BenchmarkLongnameStat(b *testing.B) {
b.Fatal(err)
}
}
+ // Cleanup
+ b.StopTimer()
+ os.RemoveAll(dirA)
+ os.Mkdir(dirA, 0700)
}
diff --git a/tests/reverse/main_test.go b/tests/reverse/main_test.go
new file mode 100644
index 0000000..3d10750
--- /dev/null
+++ b/tests/reverse/main_test.go
@@ -0,0 +1,32 @@
+package reverse_test
+
+import (
+ "os"
+ "testing"
+
+ "github.com/rfjakob/gocryptfs/tests/test_helpers"
+)
+
+var dirA, dirB, dirC string
+
+func TestMain(m *testing.M) {
+ dirA = test_helpers.TmpDir + "/a"
+ dirB = test_helpers.TmpDir + "/b"
+ dirC = test_helpers.TmpDir + "/c"
+ if err := os.Mkdir(dirA, 0700); err != nil {
+ panic(err)
+ }
+ if err := os.Mkdir(dirB, 0700); err != nil {
+ panic(err)
+ }
+ if err := os.Mkdir(dirC, 0700); err != nil {
+ panic(err)
+ }
+ test_helpers.MountOrExit(dirA, dirB, "-zerokey", "-reverse")
+ test_helpers.MountOrExit(dirB, dirC, "-zerokey", "-gcmsiv")
+ r := m.Run()
+ test_helpers.UnmountPanic(dirC)
+ test_helpers.UnmountPanic(dirB)
+ os.RemoveAll(test_helpers.TmpDir)
+ os.Exit(r)
+}