Compare commits

..

No commits in common. "b370325ccf8a15d3b58418d85fd22e32e2aeb2fc" and "a55b3cc15a6d9bce116a90f33df4bc99d9dd6a10" have entirely different histories.

28 changed files with 204 additions and 306 deletions

View File

@ -13,16 +13,16 @@ jobs:
go:
- "1.13.x" # Ubuntu 20.04 LTS "focal"
- "1.15.x" # Debian 11 "Bullseye"
- "1.18.x" # Ubuntu 22.04 LTS "jammy"
- "oldstable" # 2nd-latest Golang upstream stable
- "stable" # Latest Go upstream stable
- "1.17.x" # Golang upstream stable
- "1.18.x" # Golang upstream stable
- "1.19.x" # Golang upstream stable
# Don't cancel everything when one Go version fails
fail-fast: false
runs-on: ubuntu-latest
steps:
- name: Install Go ${{ matrix.go }}
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go }}
@ -30,7 +30,7 @@ jobs:
# https://github.com/actions/runner/issues/1188
- run: ls -l /proc/self/fd
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Make "git describe" work
@ -42,7 +42,7 @@ jobs:
# Build & upload static binary
- run: ./build-without-openssl.bash
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v2
with:
name: gocryptfs static binary (Go ${{ matrix.go }})
path: gocryptfs

View File

@ -305,10 +305,8 @@ runs as root, you can enable device files by passing the opposite mount option,
"dev", and if you want to enable suid-binaries, pass "suid".
"ro" (equivalent to passing the "-ro" option) and "noexec" may also be
interesting. For a complete list see the section
`FILESYSTEM-INDEPENDENT MOUNT OPTIONS` in mount(8). On MacOS, "local" enables volume-based trash
if you have `.Trashes` folder in the root of your volume (might need to be manually created)
note, though, that "local" is marked as "experimental" in [osxfuse](https://github.com/osxfuse/osxfuse/wiki/Mount-options#local);
"noapplexattr", "noappledouble" may also be interesting.
`FILESYSTEM-INDEPENDENT MOUNT OPTIONS` in mount(8). On MacOS, "local",
"noapplexattr", "noappledouble" may be interesting.
Note that unlike "-o", "-ko" is a regular option and must be passed BEFORE
the directories. Example:
@ -480,12 +478,11 @@ for details.
#### -fido2 DEVICE_PATH
Use a FIDO2 token to initialize and unlock the filesystem.
Use "fido2-token -L" to obtain the FIDO2 token device path.
For linux, "fido2-tools" package is needed.
Applies to: all actions that ask for a password.
#### -masterkey string
Use an explicit master key specified on the command line or, if the special
Use a explicit master key specified on the command line or, if the special
value "stdin" is used, read the masterkey from stdin, instead of reading
the config file and asking for the decryption password.
@ -565,44 +562,15 @@ Quiet - silence informational messages.
Applies to: all actions.
#### -scryptn int
gocryptfs uses *scrypt* for hashing the password when mounting,
which protects from brute-force attacks.
`-scryptn` controls the *scrypt* cost parameter "N" expressed as scryptn=log2(N).
Possible values are `-scryptn=10` to `-scryptn=28`, representing N=2^10 to N=2^28.
scrypt cost parameter expressed as scryptn=log2(N). Possible values are
10 to 28, representing N=2^10 to N=2^28.
Setting this to a lower
value speeds up mounting and reduces its memory needs, but makes
the password susceptible to brute-force attacks. The default is 16.
The memory usage for *scrypt* during mounting is as follows:
scryptn Memory Usage
======= ============
10 1 MiB
11 2
12 4
13 8
14 16
15 32
16 64
17 128
18 256
19 512
20 1 GiB
21 2
22 4
23 8
24 16
25 32
26 64
27 128
28 256
Applies to: `-init`, `-passwd`
See also: the benchmarks in the gocryptfs source code in internal/configfile.
#### -trace string
Write execution trace to file. View the trace using "go tool trace FILE".

View File

@ -62,6 +62,7 @@ distribution must be installed for mounting to work.
gocryptfs is also available as a package in most distributions. Examples:
* Debian, Ubuntu: `apt install gocryptfs`
* Fedora: `dnf install gocryptfs`
* Arch: `pacman -S gocryptfs`
* MacPorts: `port install gocryptfs`
@ -195,25 +196,6 @@ RM: 2,367
Changelog
---------
#### v2.3.1, 2023-03-04
* Optimize NFS streaming write performance ([#712](https://github.com/rfjakob/gocryptfs/issues/712),
[commit](https://github.com/rfjakob/gocryptfs/commit/8f3ec5dcaa6eb18d11746675190a7aaceb422764)).
You should see about a 4x performance increase.
* Use `debug.ReadBuildInfo()` to provide some
version information even when not built with `build.bash` ([#701](https://github.com/rfjakob/gocryptfs/pull/701)) .
* Fix bug that caused the `logger` process to be killed when started from `xfce4-terminal`,
and that terminal window was closed ([#660](https://github.com/rfjakob/gocryptfs/issues/660),
[commit](https://github.com/rfjakob/gocryptfs/commit/ff32e9979130e6237b0d97ef88304fa79ce61b06)).
* MacOS: Fix reverse mount failing with `read-only file system` ([#690](https://github.com/rfjakob/gocryptfs/pull/690))
* Make gocryptfs compile on riscv64 by switching from [jacobsa/crypto](https://github.com/jacobsa/crypto)
to maintained fork [aperturerobotics/jacobsa-crypto](https://github.com/aperturerobotics/jacobsa-crypto)
([#674](https://github.com/rfjakob/gocryptfs/pull/674))
#### v2.3.0, 2022-10-21
* Identical to v2.3, just tagged once more in full semver x.y.z format. This make Go's fetching logic happy,
which ignores v2.3 (without the third digit) completely.
Fixes [#694](https://github.com/rfjakob/gocryptfs/issues/694), [#688](https://github.com/rfjakob/gocryptfs/issues/688).
#### v2.3, 2022-08-28
* Add **`-longnamemax`** flag to `-init` ([#499](https://github.com/rfjakob/gocryptfs/issues/499)).
Can be used to work around file or path length restrictions on online storage.
@ -598,7 +580,7 @@ Changelog
* **Add reverse mode ([#19](https://github.com/rfjakob/gocryptfs/issues/19))**
* AES-SIV (RFC5297) encryption to implement deterministic encryption
securely. Uses the excellent
[jacobsa/crypto](https://github.com/aperturerobotics/jacobsa-crypto) library.
[jacobsa/crypto](https://github.com/jacobsa/crypto) library.
The corresponding feature flag is called `AESSIV`.
* New command-line options: `-reverse`, `-aessiv`
* Filesystems using reverse mode can only be mounted with gocryptfs v1.1

11
go.mod
View File

@ -3,13 +3,18 @@ module github.com/rfjakob/gocryptfs/v2
go 1.16
require (
github.com/aperturerobotics/jacobsa-crypto v1.0.0
github.com/hanwen/go-fuse/v2 v2.1.1-0.20221117175120-915cf5413cde
github.com/hanwen/go-fuse/v2 v2.1.1-0.20211219085202-934a183ed914
github.com/jacobsa/crypto v0.0.0-20190317225127-9f44e2d11115
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd // indirect
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff // indirect
github.com/jacobsa/ogletest v0.0.0-20170503003838-80d50a735a11 // indirect
github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb // indirect
github.com/pkg/xattr v0.4.3
github.com/rfjakob/eme v1.1.2
github.com/sabhiram/go-gitignore v0.0.0-20201211210132-54b8a0bf510f
github.com/spf13/pflag v1.0.5
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035
)

21
go.sum
View File

@ -1,10 +1,9 @@
github.com/aperturerobotics/jacobsa-crypto v0.0.0-20190317225127-9f44e2d11115/go.mod h1:XKd7k7LIBmeR/WGENaSpUSjQbWBVKZFhMT7+zKM5KVU=
github.com/aperturerobotics/jacobsa-crypto v1.0.0 h1:ARfIuzgovK+5leAKbFHcicKEgMzD94tb/FTiWSHdGLU=
github.com/aperturerobotics/jacobsa-crypto v1.0.0/go.mod h1:xq0oOkHSPQ1E5ByqbwLhCJ1mygYHtXTMQnvHD4tz4Cc=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hanwen/go-fuse/v2 v2.1.1-0.20221117175120-915cf5413cde h1:fgTauqHA48CDt+qVQR+PJXqiI9bpYQglMIIi+h/mMts=
github.com/hanwen/go-fuse/v2 v2.1.1-0.20221117175120-915cf5413cde/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc=
github.com/hanwen/go-fuse/v2 v2.1.1-0.20211219085202-934a183ed914 h1:hGXMxS1wTE4y+f7iBqFArrJ6X8QozHnEdnVzGZI9Ywc=
github.com/hanwen/go-fuse/v2 v2.1.1-0.20211219085202-934a183ed914/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc=
github.com/jacobsa/crypto v0.0.0-20190317225127-9f44e2d11115 h1:YuDUUFNM21CAbyPOpOP8BicaTD/0klJEKt5p8yuw+uY=
github.com/jacobsa/crypto v0.0.0-20190317225127-9f44e2d11115/go.mod h1:LadVJg0XuawGk+8L1rYnIED8451UyNxEMdTWCEt5kmU=
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd h1:9GCSedGjMcLZCrusBZuo4tyKLpKUPenUUqi34AkuFmA=
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd/go.mod h1:TlmyIZDpGmwRoTWiakdr+HA1Tukze6C6XbRVidYq02M=
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff h1:2xRHTvkpJ5zJmglXLRqHiZQNjUoOkhUyhTAhEQvPAWw=
@ -31,21 +30,21 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0=
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo=
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=

View File

@ -1,45 +1,60 @@
package configfile
import (
"fmt"
"testing"
)
/*
$ time go test -bench . -run none
goos: linux
goarch: amd64
pkg: github.com/rfjakob/gocryptfs/v2/internal/configfile
cpu: Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
BenchmarkScryptN/10-4 339 3488649 ns/op 1053167 B/op 22 allocs/op ... 3ms+1MiB
BenchmarkScryptN/11-4 175 6816072 ns/op 2101742 B/op 22 allocs/op
BenchmarkScryptN/12-4 87 13659346 ns/op 4198898 B/op 22 allocs/op
BenchmarkScryptN/13-4 43 27443071 ns/op 8393209 B/op 22 allocs/op
BenchmarkScryptN/14-4 21 56931664 ns/op 16781820 B/op 22 allocs/op
BenchmarkScryptN/15-4 10 108494502 ns/op 33559027 B/op 22 allocs/op
BenchmarkScryptN/16-4 5 217347137 ns/op 67113465 B/op 22 allocs/op ... 217ms+67MiB
BenchmarkScryptN/17-4 3 449680138 ns/op 134222362 B/op 22 allocs/op
BenchmarkScryptN/18-4 2 867481653 ns/op 268440064 B/op 22 allocs/op
BenchmarkScryptN/19-4 1 1738085333 ns/op 536875536 B/op 23 allocs/op
BenchmarkScryptN/20-4 1 3508224867 ns/op 1073746448 B/op 23 allocs/op
BenchmarkScryptN/21-4 1 9536561994 ns/op 2147488272 B/op 23 allocs/op
BenchmarkScryptN/22-4 1 16937072495 ns/op 4294971920 B/op 23 allocs/op
Results on a 2.7GHz Pentium G630:
gocryptfs/cryptfs$ go test -bench=.
PASS
ok github.com/rfjakob/gocryptfs/v2/internal/configfile 47.545s
BenchmarkScrypt10-2 300 6021435 ns/op ... 6ms
BenchmarkScrypt11-2 100 11861460 ns/op
BenchmarkScrypt12-2 100 23420822 ns/op
BenchmarkScrypt13-2 30 47666518 ns/op
BenchmarkScrypt14-2 20 92561590 ns/op ... 92ms
BenchmarkScrypt15-2 10 183971593 ns/op
BenchmarkScrypt16-2 3 368506365 ns/op
BenchmarkScrypt17-2 2 755502608 ns/op ... 755ms
ok github.com/rfjakob/gocryptfs/v2/cryptfs 18.772s
*/
func BenchmarkScryptN(b *testing.B) {
for n := 10; n <= 20; n++ {
b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
benchmarkScryptN(b, n)
})
}
}
func benchmarkScryptN(b *testing.B, n int) {
func benchmarkScryptN(n int, b *testing.B) {
kdf := NewScryptKDF(n)
for i := 0; i < b.N; i++ {
kdf.DeriveKey(testPw)
}
b.ReportAllocs()
}
func BenchmarkScrypt10(b *testing.B) {
benchmarkScryptN(10, b)
}
func BenchmarkScrypt11(b *testing.B) {
benchmarkScryptN(11, b)
}
func BenchmarkScrypt12(b *testing.B) {
benchmarkScryptN(12, b)
}
func BenchmarkScrypt13(b *testing.B) {
benchmarkScryptN(13, b)
}
func BenchmarkScrypt14(b *testing.B) {
benchmarkScryptN(14, b)
}
func BenchmarkScrypt15(b *testing.B) {
benchmarkScryptN(15, b)
}
func BenchmarkScrypt16(b *testing.B) {
benchmarkScryptN(16, b)
}
func BenchmarkScrypt17(b *testing.B) {
benchmarkScryptN(17, b)
}

View File

@ -12,15 +12,15 @@ type testRange struct {
}
func TestSplitRange(t *testing.T) {
ranges := []testRange{
{0, 70000},
{0, 10},
{234, 6511},
{65444, 54},
{0, 1024 * 1024},
{0, 65536},
{6654, 8945},
}
var ranges []testRange
ranges = append(ranges, testRange{0, 70000},
testRange{0, 10},
testRange{234, 6511},
testRange{65444, 54},
testRange{0, 1024 * 1024},
testRange{0, 65536},
testRange{6654, 8945})
key := make([]byte, cryptocore.KeyLen)
cc := cryptocore.New(key, cryptocore.BackendGoGCM, DefaultIVBits, true)
@ -42,13 +42,13 @@ func TestSplitRange(t *testing.T) {
}
func TestCiphertextRange(t *testing.T) {
ranges := []testRange{
{0, 70000},
{0, 10},
{234, 6511},
{65444, 54},
{6654, 8945},
}
var ranges []testRange
ranges = append(ranges, testRange{0, 70000},
testRange{0, 10},
testRange{234, 6511},
testRange{65444, 54},
testRange{6654, 8945})
key := make([]byte, cryptocore.KeyLen)
cc := cryptocore.New(key, cryptocore.BackendGoGCM, DefaultIVBits, true)

View File

@ -6,11 +6,10 @@ import (
)
// SanitizePath adapts filepath.Clean for FUSE paths.
// 1. Leading slash(es) are dropped
// 2. It returns "" instead of "."
// 3. If the cleaned path points above CWD (start with ".."), an empty string
// is returned
//
// 1) Leading slash(es) are dropped
// 2) It returns "" instead of "."
// 3) If the cleaned path points above CWD (start with ".."), an empty string
// is returned
// See the TestSanitizePath testcases for examples.
func SanitizePath(path string) string {
// (1)

View File

@ -5,7 +5,7 @@
//
// Use like this:
//
// import _ "github.com/rfjakob/gocryptfs/v2/internal/ensurefds012"
// import _ "github.com/rfjakob/gocryptfs/v2/internal/ensurefds012"
//
// The import line MUST be in the alphabitcally first source code file of
// package main!
@ -13,17 +13,17 @@
// You can test if it works as expected by inserting a long sleep into main,
// startings gocryptfs with all fds closed like this,
//
// $ ./gocryptfs 0<&- 1>&- 2>&-
// $ ./gocryptfs 0<&- 1>&- 2>&-
//
// and then checking the open fds. It should look like this:
//
// $ ls -l /proc/$(pgrep gocryptfs)/fd
// total 0
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 0 -> /dev/null
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 1 -> /dev/null
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 2 -> /dev/null
// l-wx------. 1 jakob jakob 64 Jan 5 15:54 3 -> /dev/null
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 4 -> 'anon_inode:[eventpoll]'
// $ ls -l /proc/$(pgrep gocryptfs)/fd
// total 0
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 0 -> /dev/null
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 1 -> /dev/null
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 2 -> /dev/null
// l-wx------. 1 jakob jakob 64 Jan 5 15:54 3 -> /dev/null
// lrwx------. 1 jakob jakob 64 Jan 5 15:54 4 -> 'anon_inode:[eventpoll]'
//
// See https://github.com/rfjakob/gocryptfs/issues/320 for details.
package ensurefds012

View File

@ -273,10 +273,6 @@ func (f *File) doWrite(data []byte, off int64) (uint32, syscall.Errno) {
if err == io.EOF {
fileID, err = f.createHeader()
fileWasEmpty = true
} else if err != nil {
// Other errors mean readFileID() found a corrupt header
tlog.Warn.Printf("doWrite %d: corrupt header: %v", f.qIno.Ino, err)
return 0, syscall.EIO
}
if err != nil {
return 0, fs.ToErrno(err)
@ -384,7 +380,7 @@ func (f *File) Write(ctx context.Context, data []byte, off int64) (uint32, sysca
}
}
n, errno := f.doWrite(data, off)
if errno == 0 {
if errno != 0 {
f.lastOpCount = openfiletable.WriteOpCount()
f.lastWrittenOffset = off + int64(len(data)) - 1
}

View File

@ -30,8 +30,8 @@ var allocateWarnOnce sync.Once
//
// mode=FALLOC_DEFAULT is implemented as a two-step process:
//
// (1) Allocate the space using FALLOC_FL_KEEP_SIZE
// (2) Set the file size using ftruncate (via truncateGrowFile)
// (1) Allocate the space using FALLOC_FL_KEEP_SIZE
// (2) Set the file size using ftruncate (via truncateGrowFile)
//
// This allows us to reuse the file grow mechanics from Truncate as they are
// complicated and hard to get right.

View File

@ -3,8 +3,8 @@
//
// Format of the returned inode numbers:
//
// [spill bit = 0][15 bit namespace id][48 bit passthru inode number]
// [spill bit = 1][63 bit spill inode number ]
// [spill bit = 0][15 bit namespace id][48 bit passthru inode number]
// [spill bit = 1][63 bit spill inode number ]
//
// Each (Dev, Tag) tuple gets a namespace id assigned. The original inode
// number is then passed through in the lower 48 bits.

View File

@ -5,7 +5,7 @@ import (
"encoding/hex"
"testing"
"github.com/aperturerobotics/jacobsa-crypto/siv"
"github.com/jacobsa/crypto/siv"
)
// Test all supported key lengths

View File

@ -6,7 +6,7 @@ import (
"crypto/cipher"
"log"
"github.com/aperturerobotics/jacobsa-crypto/siv"
"github.com/jacobsa/crypto/siv"
)
type sivAead struct {
@ -63,7 +63,7 @@ func (s *sivAead) Seal(dst, nonce, plaintext, authData []byte) []byte {
if len(s.key) == 0 {
log.Panic("Key has been wiped?")
}
// https://github.com/aperturerobotics/jacobsa-crypto/blob/master/siv/encrypt.go#L48:
// https://github.com/jacobsa/crypto/blob/master/siv/encrypt.go#L48:
// As per RFC 5297 section 3, you may use this function for nonce-based
// authenticated encryption by passing a nonce as the last associated
// data element.

View File

@ -12,17 +12,17 @@ import (
//
// Examples: On my desktop PC:
//
// $ grep "model name" /proc/cpuinfo
// model name : Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
// $ grep "model name" /proc/cpuinfo
// model name : Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz
//
// --> Returns "Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz".
//
// On a Raspberry Pi 4:
//
// $ grep "model name" /proc/cpuinfo
// (empty)
// $ grep Hardware /proc/cpuinfo
// Hardware : BCM2835
// $ grep "model name" /proc/cpuinfo
// (empty)
// $ grep Hardware /proc/cpuinfo
// Hardware : BCM2835
//
// --> Returns "BCM2835"
func cpuModelName() string {

View File

@ -23,7 +23,7 @@ import (
const adLen = 24
// gocryptfs uses fixed-size 4 kiB blocks
const gocryptfsBlockSize = 4096
const blockSize = 4096
// Run - run the speed the test and print the results.
func Run() {
@ -83,11 +83,6 @@ func randBytes(n int) []byte {
// bEncrypt benchmarks the encryption speed of cipher "c"
func bEncrypt(b *testing.B, c cipher.AEAD) {
bEncryptBlockSize(b, c, gocryptfsBlockSize)
}
// bEncryptBlockSize benchmarks the encryption speed of cipher "c" at block size "blockSize"
func bEncryptBlockSize(b *testing.B, c cipher.AEAD, blockSize int) {
authData := randBytes(adLen)
iv := randBytes(c.NonceSize())
in := make([]byte, blockSize)
@ -102,12 +97,13 @@ func bEncryptBlockSize(b *testing.B, c cipher.AEAD, blockSize int) {
// Encrypt and append to nonce
c.Seal(dst, iv, in, authData)
}
}
func bDecrypt(b *testing.B, c cipher.AEAD) {
authData := randBytes(adLen)
iv := randBytes(c.NonceSize())
plain := randBytes(gocryptfsBlockSize)
plain := randBytes(blockSize)
ciphertext := c.Seal(iv, iv, plain, authData)
b.SetBytes(int64(len(plain)))
@ -133,10 +129,6 @@ func bStupidGCM(b *testing.B) {
// bGoGCM benchmarks Go stdlib GCM
func bGoGCM(b *testing.B) {
bGoGCMBlockSize(b, gocryptfsBlockSize)
}
func bGoGCMBlockSize(b *testing.B, blockSize int) {
gAES, err := aes.NewCipher(randBytes(32))
if err != nil {
b.Fatal(err)
@ -145,10 +137,10 @@ func bGoGCMBlockSize(b *testing.B, blockSize int) {
if err != nil {
b.Fatal(err)
}
bEncryptBlockSize(b, gGCM, blockSize)
bEncrypt(b, gGCM)
}
// bAESSIV benchmarks AES-SIV from github.com/aperturerobotics/jacobsa-crypto/siv
// bAESSIV benchmarks AES-SIV from github.com/jacobsa/crypto/siv
func bAESSIV(b *testing.B) {
c := siv_aead.New(randBytes(64))
bEncrypt(b, c)

View File

@ -3,7 +3,6 @@ package speed
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"testing"
"golang.org/x/crypto/chacha20poly1305"
@ -39,13 +38,6 @@ func BenchmarkGoGCM(b *testing.B) {
bGoGCM(b)
}
func BenchmarkGoGCMBlockSize(b *testing.B) {
for blockSize := 16; blockSize <= 1024*1024; blockSize *= 2 {
name := fmt.Sprintf("%d", blockSize)
b.Run(name, func(b *testing.B) { bGoGCMBlockSize(b, blockSize) })
}
}
func BenchmarkGoGCMDecrypt(b *testing.B) {
gAES, err := aes.NewCipher(randBytes(32))
if err != nil {

View File

@ -16,13 +16,13 @@
// However, OpenSSL has optimized assembly for almost all platforms, which Go
// does not. Example for a 32-bit ARM device (Odroid XU4):
//
// $ gocrypts -speed
// gocryptfs v2.1-68-gedf9d4c.stupidchacha; go-fuse v2.1.1-0.20210825171523-3ab5d95a30ae; 2021-09-04 go1.16.7 linux/arm
// AES-GCM-256-OpenSSL 56.84 MB/s (selected in auto mode)
// AES-GCM-256-Go 16.61 MB/s
// AES-SIV-512-Go 16.49 MB/s
// XChaCha20-Poly1305-Go 39.08 MB/s (use via -xchacha flag)
// XChaCha20-Poly1305-OpenSSL 141.82 MB/s
// $ gocrypts -speed
// gocryptfs v2.1-68-gedf9d4c.stupidchacha; go-fuse v2.1.1-0.20210825171523-3ab5d95a30ae; 2021-09-04 go1.16.7 linux/arm
// AES-GCM-256-OpenSSL 56.84 MB/s (selected in auto mode)
// AES-GCM-256-Go 16.61 MB/s
// AES-SIV-512-Go 16.49 MB/s
// XChaCha20-Poly1305-Go 39.08 MB/s (use via -xchacha flag)
// XChaCha20-Poly1305-OpenSSL 141.82 MB/s
//
// This package is "stupid" in the sense that it only supports a narrow set of
// key- and iv-lengths, and panics if it does not like what you pass it.
@ -33,7 +33,7 @@
// Corrupt ciphertexts never cause a panic. Instead, ErrAuth is returned on
// decryption.
//
// # XChaCha20-Poly1305
// XChaCha20-Poly1305
//
// The XChaCha20-Poly1305 implementation is more complicated than the others,
// because OpenSSL does not support XChaCha20-Poly1305 directly. Follow
@ -43,16 +43,16 @@
// Fortunately, XChaCha20-Poly1305 is just ChaCha20-Poly1305 with some key+iv
// mixing using HChaCha20 in front:
//
// key (32 bytes), iv (24 bytes)
// |
// v
// HChaCha20 (provided by golang.org/x/crypto/chacha20)
// |
// v
// key2 (32 bytes), iv2 (16 bytes)
// |
// v
// ChaCha20-Poly1305 (OpenSSL EVP_chacha20_poly1305)
// key (32 bytes), iv (24 bytes)
// |
// v
// HChaCha20 (provided by golang.org/x/crypto/chacha20)
// |
// v
// key2 (32 bytes), iv2 (16 bytes)
// |
// v
// ChaCha20-Poly1305 (OpenSSL EVP_chacha20_poly1305)
//
// As HChaCha20 is very fast, XChaCha20-Poly1305 gets almost the same throughput
// as ChaCha20-Poly1305 (for 4kiB blocks).

View File

@ -11,9 +11,9 @@ import (
//
// Go GCM is only faster if the CPU either:
//
// 1. Is X86_64 && has AES instructions && Go is v1.6 or higher
// 2. Is ARM64 && has AES instructions && Go is v1.11 or higher
// (commit https://github.com/golang/go/commit/4f1f503373cda7160392be94e3849b0c9b9ebbda)
// 1) Is X86_64 && has AES instructions && Go is v1.6 or higher
// 2) Is ARM64 && has AES instructions && Go is v1.11 or higher
// (commit https://github.com/golang/go/commit/4f1f503373cda7160392be94e3849b0c9b9ebbda)
//
// See https://github.com/rfjakob/gocryptfs/wiki/CPU-Benchmarks
// for benchmarks.

34
main.go
View File

@ -4,6 +4,7 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
@ -19,9 +20,22 @@ import (
"github.com/rfjakob/gocryptfs/v2/internal/fido2"
"github.com/rfjakob/gocryptfs/v2/internal/readpassword"
"github.com/rfjakob/gocryptfs/v2/internal/speed"
"github.com/rfjakob/gocryptfs/v2/internal/stupidgcm"
"github.com/rfjakob/gocryptfs/v2/internal/tlog"
)
// GitVersion is the gocryptfs version according to git, set by build.bash
var GitVersion = "[GitVersion not set - please compile using ./build.bash]"
// GitVersionFuse is the go-fuse library version, set by build.bash
var GitVersionFuse = "[GitVersionFuse not set - please compile using ./build.bash]"
// BuildDate is a date string like "2017-09-06", set by build.bash
var BuildDate = "0000-00-00"
// raceDetector is set to true by race.go if we are compiled with "go build -race"
var raceDetector bool
// loadConfig loads the config file `args.config` and decrypts the masterkey,
// or gets via the `-masterkey` or `-zerokey` command line options, if specified.
func loadConfig(args *argContainer) (masterkey []byte, cf *configfile.ConfFile, err error) {
@ -123,6 +137,26 @@ func changePassword(args *argContainer) {
tlog.Info.Printf(tlog.ColorGreen + "Password changed." + tlog.ColorReset)
}
// printVersion prints a version string like this:
// gocryptfs v1.7-32-gcf99cfd; go-fuse v1.0.0-174-g22a9cb9; 2019-05-12 go1.12 linux/amd64
func printVersion() {
var tagsSlice []string
if stupidgcm.BuiltWithoutOpenssl {
tagsSlice = append(tagsSlice, "without_openssl")
}
tags := ""
if tagsSlice != nil {
tags = " " + strings.Join(tagsSlice, " ")
}
built := fmt.Sprintf("%s %s", BuildDate, runtime.Version())
if raceDetector {
built += " -race"
}
fmt.Printf("%s %s%s; go-fuse %s; %s %s/%s\n",
tlog.ProgramName, GitVersion, tags, GitVersionFuse, built,
runtime.GOOS, runtime.GOARCH)
}
func main() {
mxp := runtime.GOMAXPROCS(0)
if mxp < 4 && os.Getenv("GOMAXPROCS") == "" {

View File

@ -120,18 +120,9 @@ func doMount(args *argContainer) {
tlog.Info.Println(tlog.ColorGreen + "Filesystem mounted and ready." + tlog.ColorReset)
// We have been forked into the background, as evidenced by the set
// "notifypid".
// Do what daemons should do: https://man7.org/linux/man-pages/man7/daemon.7.html
if args.notifypid > 0 {
// Chdir to the root directory so we don't block unmounting the CWD
os.Chdir("/")
// Disconnect from the controlling terminal by creating a new session.
// This prevents us from getting SIGINT when the user presses Ctrl-C
// to exit a running script that has called gocryptfs, or SIGHUP when
// xfce4-terminal closes itself ( https://github.com/rfjakob/gocryptfs/issues/660 ).
_, err = syscall.Setsid()
if err != nil {
tlog.Warn.Printf("Setsid: %v", err)
}
// Switch to syslog
if !args.nosyslog {
// Switch all of our logs and the generic logger to syslog
@ -143,6 +134,13 @@ func doMount(args *argContainer) {
// Daemons should redirect stdin, stdout and stderr
redirectStdFds()
}
// Disconnect from the controlling terminal by creating a new session.
// This prevents us from getting SIGINT when the user presses Ctrl-C
// to exit a running script that has called gocryptfs.
_, err = syscall.Setsid()
if err != nil {
tlog.Warn.Printf("Setsid: %v", err)
}
// Send SIGUSR1 to our parent
sendUsr1(args.notifypid)
}

View File

@ -462,9 +462,7 @@ func TestPasswdPasswordIncorrect(t *testing.T) {
// Check that we correctly background on mount and close stderr and stdout.
// Something like
//
// gocryptfs a b | cat
//
// gocryptfs a b | cat
// must not hang ( https://github.com/rfjakob/gocryptfs/issues/130 ).
func TestMountBackground(t *testing.T) {
dir := test_helpers.InitFS(t)

View File

@ -204,9 +204,7 @@ func TestWrite0200File(t *testing.T) {
// TestMvWarnings:
// When xattr support was introduced, mv threw warnings like these:
//
// mv: preserving permissions for b/x: Operation not permitted
//
// mv: preserving permissions for b/x: Operation not permitted
// because we returned EPERM when it tried to set system.posix_acl_access.
// Now we return EOPNOTSUPP and mv is happy.
func TestMvWarnings(t *testing.T) {

View File

@ -134,7 +134,7 @@ func TestConcurrentReadCreate(t *testing.T) {
//
// So far, it only has triggered warnings like this
//
// go-fuse: warning: Inode.Path: inode i4201033 is orphaned, replacing segment with ".go-fuse.5577006791947779410/deleted"
// go-fuse: warning: Inode.Path: inode i4201033 is orphaned, replacing segment with ".go-fuse.5577006791947779410/deleted"
//
// but none of the "blocked waiting for FORGET".
func TestInoReuse(t *testing.T) {

View File

@ -92,10 +92,10 @@ func TestFiltered(t *testing.T) {
// Only works on filesystems that recycle inode numbers (ext4 does),
// and then the test causes a hang with these messages:
//
// go-fuse: blocked for 5 seconds waiting for FORGET on i4329366
// go-fuse: blocked for 11 seconds waiting for FORGET on i4329366
// go-fuse: blocked for 17 seconds waiting for FORGET on i4329366
// [...]
// go-fuse: blocked for 5 seconds waiting for FORGET on i4329366
// go-fuse: blocked for 11 seconds waiting for FORGET on i4329366
// go-fuse: blocked for 17 seconds waiting for FORGET on i4329366
// [...]
//
// The test runs with -plaintextnames because that makes it easier to manipulate
// cipherdir directly.

View File

@ -35,15 +35,15 @@ func findIno(dir string, ino uint64) string {
// TestVirtualFileIno creates a directory tree like this:
//
// TestVirtualFileIno <---- parent
// └── xxxxxxx[...] <---- child
// TestVirtualFileIno <---- parent
// └── xxxxxxx[...] <---- child
//
// Which looks like this encrypted:
//
// OLUKdPMg6l87EiKVlufgwIkQL8MD6JdUgOR3a8nEZ-w <---- parent
// ├── gocryptfs.diriv <---- diriv
// ├── gocryptfs.longname.e31v1ax4h_F0l4jhlN8kCjaWWMq8rO9VVBZ15IYsV50 <---- child
// └── gocryptfs.longname.e31v1ax4h_F0l4jhlN8kCjaWWMq8rO9VVBZ15IYsV50.name <---- name
// OLUKdPMg6l87EiKVlufgwIkQL8MD6JdUgOR3a8nEZ-w <---- parent
// ├── gocryptfs.diriv <---- diriv
// ├── gocryptfs.longname.e31v1ax4h_F0l4jhlN8kCjaWWMq8rO9VVBZ15IYsV50 <---- child
// └── gocryptfs.longname.e31v1ax4h_F0l4jhlN8kCjaWWMq8rO9VVBZ15IYsV50.name <---- name
//
// It verifies that the inode numbers match what we expect.
func TestVirtualFileIno(t *testing.T) {

View File

@ -67,10 +67,10 @@ func doInit() {
// ResetTmpDir deletes TmpDir, create new dir tree:
//
// TmpDir
// |-- DefaultPlainDir
// *-- DefaultCipherDir
// *-- gocryptfs.diriv
// TmpDir
// |-- DefaultPlainDir
// *-- DefaultCipherDir
// *-- gocryptfs.diriv
func ResetTmpDir(createDirIV bool) {
// Try to unmount and delete everything
entries, err := ioutil.ReadDir(TmpDir)
@ -138,7 +138,7 @@ func isExt4(path string) bool {
// InitFS creates a new empty cipherdir and calls
//
// gocryptfs -q -init -extpass "echo test" -scryptn=10 $extraArgs $cipherdir
// gocryptfs -q -init -extpass "echo test" -scryptn=10 $extraArgs $cipherdir
//
// It returns cipherdir without a trailing slash.
//

View File

@ -1,78 +0,0 @@
package main
import (
"fmt"
"runtime"
"runtime/debug"
"strings"
"github.com/rfjakob/gocryptfs/v2/internal/stupidgcm"
"github.com/rfjakob/gocryptfs/v2/internal/tlog"
)
const (
gitVersionNotSet = "[GitVersion not set - please compile using ./build.bash]"
gitVersionFuseNotSet = "[GitVersionFuse not set - please compile using ./build.bash]"
buildDateNotSet = "0000-00-00"
)
var (
// GitVersion is the gocryptfs version according to git, set by build.bash
GitVersion = gitVersionNotSet
// GitVersionFuse is the go-fuse library version, set by build.bash
GitVersionFuse = gitVersionFuseNotSet
// BuildDate is a date string like "2017-09-06", set by build.bash
BuildDate = buildDateNotSet
)
func init() {
versionFromBuildInfo()
}
// raceDetector is set to true by race.go if we are compiled with "go build -race"
var raceDetector bool
// printVersion prints a version string like this:
// gocryptfs v1.7-32-gcf99cfd; go-fuse v1.0.0-174-g22a9cb9; 2019-05-12 go1.12 linux/amd64
func printVersion() {
var tagsSlice []string
if stupidgcm.BuiltWithoutOpenssl {
tagsSlice = append(tagsSlice, "without_openssl")
}
tags := ""
if tagsSlice != nil {
tags = " " + strings.Join(tagsSlice, " ")
}
built := fmt.Sprintf("%s %s", BuildDate, runtime.Version())
if raceDetector {
built += " -race"
}
fmt.Printf("%s %s%s; go-fuse %s; %s %s/%s\n",
tlog.ProgramName, GitVersion, tags, GitVersionFuse, built,
runtime.GOOS, runtime.GOARCH)
}
// versionFromBuildInfo tries to get some information out of the information baked in
// by the Go compiler. Does nothing when build.bash was used to build.
func versionFromBuildInfo() {
info, ok := debug.ReadBuildInfo()
if !ok {
tlog.Debug.Println("versionFromBuildInfo: ReadBuildInfo() failed")
return
}
// Fill our version strings
if GitVersion == gitVersionNotSet && info.Main.Version != "(devel)" {
GitVersion = info.Main.Version
}
if GitVersionFuse == gitVersionFuseNotSet {
for _, m := range info.Deps {
if m.Path == "github.com/hanwen/go-fuse/v2" {
GitVersionFuse = m.Version
if m.Replace != nil {
GitVersionFuse = m.Replace.Version
}
break
}
}
}
}