Skip to content

Commit c54198e

Browse files
committed
prefer_openssl: autodetect whether to use OpenSSL or Go GCM
Go GCM is faster than OpenSSL if the CPU has AES instructions and you are running Go 1.6+. The "-openssl" option now defaults to "auto". "gocryptfs -debug -version" displays the result of the autodetection. See #23 for details and benchmarks.
1 parent 384342f commit c54198e

File tree

8 files changed

+202
-8
lines changed

8 files changed

+202
-8
lines changed

Documentation/MANPAGE.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ continue be printed to stdout and stderr.
9696
used internally for daemonization.
9797

9898
**-openssl bool**
99-
: Use OpenSSL instead of built-in Go crypto (default true). Using
100-
built-in crypto is 4x slower.
99+
: Use OpenSSL instead of built-in Go crypto (default "auto"). Using
100+
built-in crypto is 4x slower unless you CPU has AES instructions and
101+
you are using Go 1.6+. In mode "auto", gocrypts chooses the faster
102+
option.
101103

102104
**-passwd**
103105
: Change password
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
processor : 0
2+
vendor_id : GenuineIntel
3+
cpu family : 6
4+
model : 42
5+
model name : Intel(R) Pentium(R) CPU G630 @ 2.70GHz
6+
stepping : 7
7+
microcode : 0x29
8+
cpu MHz : 2700.000
9+
cache size : 3072 KB
10+
physical id : 0
11+
siblings : 2
12+
core id : 0
13+
cpu cores : 2
14+
apicid : 0
15+
initial apicid : 0
16+
fpu : yes
17+
fpu_exception : yes
18+
cpuid level : 13
19+
wp : yes
20+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt tsc_deadline_timer xsave lahf_lm arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid xsaveopt
21+
bugs :
22+
bogomips : 5387.85
23+
clflush size : 64
24+
cache_alignment : 64
25+
address sizes : 36 bits physical, 48 bits virtual
26+
power management:
27+
28+
processor : 1
29+
vendor_id : GenuineIntel
30+
cpu family : 6
31+
model : 42
32+
model name : Intel(R) Pentium(R) CPU G630 @ 2.70GHz
33+
stepping : 7
34+
microcode : 0x29
35+
cpu MHz : 2700.000
36+
cache size : 3072 KB
37+
physical id : 0
38+
siblings : 2
39+
core id : 1
40+
cpu cores : 2
41+
apicid : 2
42+
initial apicid : 2
43+
fpu : yes
44+
fpu_exception : yes
45+
cpuid level : 13
46+
wp : yes
47+
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt tsc_deadline_timer xsave lahf_lm arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid xsaveopt
48+
bugs :
49+
bogomips : 5387.85
50+
clflush size : 64
51+
cache_alignment : 64
52+
address sizes : 36 bits physical, 48 bits virtual
53+
power management:
54+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
processor : 0
2+
vendor_id : GenuineIntel
3+
cpu family : 6
4+
model : 42
5+
model name : Intel Xeon E312xx (Sandy Bridge)
6+
stepping : 1
7+
microcode : 0x1
8+
cpu MHz : 3300.022
9+
cache size : 4096 KB
10+
physical id : 0
11+
siblings : 1
12+
core id : 0
13+
cpu cores : 1
14+
apicid : 0
15+
initial apicid : 0
16+
fpu : yes
17+
fpu_exception : yes
18+
cpuid level : 13
19+
wp : yes
20+
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx hypervisor lahf_lm xsaveopt
21+
bogomips : 6600.04
22+
clflush size : 64
23+
cache_alignment : 64
24+
address sizes : 40 bits physical, 48 bits virtual
25+
power management:
26+
27+
processor : 1
28+
vendor_id : GenuineIntel
29+
cpu family : 6
30+
model : 42
31+
model name : Intel Xeon E312xx (Sandy Bridge)
32+
stepping : 1
33+
microcode : 0x1
34+
cpu MHz : 3300.022
35+
cache size : 4096 KB
36+
physical id : 1
37+
siblings : 1
38+
core id : 0
39+
cpu cores : 1
40+
apicid : 1
41+
initial apicid : 1
42+
fpu : yes
43+
fpu_exception : yes
44+
cpuid level : 13
45+
wp : yes
46+
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx hypervisor lahf_lm xsaveopt
47+
bogomips : 6600.04
48+
clflush size : 64
49+
cache_alignment : 64
50+
address sizes : 40 bits physical, 48 bits virtual
51+
power management:
52+

internal/prefer_openssl/prefer.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package prefer_openssl
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"regexp"
7+
)
8+
9+
// filePreferOpenSSL tells us if OpenSSL is faster than Go GCM on this machine.
10+
// Go GCM is fastern when the CPU has AES instructions and Go is v1.6 or higher.
11+
//
12+
// See https://github.com/rfjakob/gocryptfs/issues/23#issuecomment-218286502
13+
// for benchmarks.
14+
//
15+
// filePreferOpenSSL takes an explicit filename so it can be tested with saved
16+
// cpuinfo files instead of /proc/cpuinfo.
17+
func filePreferOpenSSL(file string) bool {
18+
ci, err := ioutil.ReadFile(file)
19+
if err != nil {
20+
fmt.Println(err)
21+
return true
22+
}
23+
haveAes, err := regexp.Match(`(?m)^flags.*\baes\b`, ci)
24+
if err != nil {
25+
fmt.Println(err)
26+
return true
27+
}
28+
return !haveAes
29+
}
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// +build !go1.6
2+
// = go 1.5 or lower
3+
4+
package prefer_openssl
5+
6+
func PreferOpenSSL() bool {
7+
// OpenSSL is always faster than Go GCM on old Go versions.
8+
return true
9+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// +build go1.6
2+
// = go 1.6 or higher
3+
4+
package prefer_openssl
5+
6+
// PreferOpenSSL tells us if OpenSSL is faster than Go GCM on this machine.
7+
// Go GCM is fastern when the CPU has AES instructions and Go is v1.6 or higher.
8+
//
9+
// See https://github.com/rfjakob/gocryptfs/issues/23#issuecomment-218286502
10+
// for benchmarks.
11+
func PreferOpenSSL() bool {
12+
return filePreferOpenSSL("/proc/cpuinfo")
13+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package prefer_openssl
2+
3+
import (
4+
"testing"
5+
)
6+
7+
// Has AES instructions
8+
func TestXeonE312xx(t *testing.T) {
9+
if filePreferOpenSSL("cpuinfo.xeon_e312xx.txt") == true {
10+
t.Fail()
11+
}
12+
}
13+
14+
// Pentium G do not have AES instructions
15+
func TestPentiumG630(t *testing.T) {
16+
if filePreferOpenSSL("cpuinfo.pentium_g630.txt") == false {
17+
t.Fail()
18+
}
19+
}

main.go

+22-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"path/filepath"
1212
"runtime"
1313
"runtime/pprof"
14+
"strconv"
1415
"syscall"
1516
"time"
1617

@@ -25,6 +26,7 @@ import (
2526
"github.com/rfjakob/gocryptfs/internal/cryptocore"
2627
"github.com/rfjakob/gocryptfs/internal/fusefrontend"
2728
"github.com/rfjakob/gocryptfs/internal/nametransform"
29+
"github.com/rfjakob/gocryptfs/internal/prefer_openssl"
2830
"github.com/rfjakob/gocryptfs/internal/toggledlog"
2931
)
3032

@@ -149,14 +151,15 @@ func main() {
149151
setupColors()
150152

151153
// Parse command line arguments
154+
var opensslAuto string
152155
flagSet = flag.NewFlagSet(toggledlog.ProgramName, flag.ExitOnError)
153156
flagSet.Usage = usageText
154157
flagSet.BoolVar(&args.debug, "d", false, "")
155158
flagSet.BoolVar(&args.debug, "debug", false, "Enable debug output")
156159
flagSet.BoolVar(&args.fusedebug, "fusedebug", false, "Enable fuse library debug output")
157160
flagSet.BoolVar(&args.init, "init", false, "Initialize encrypted directory")
158161
flagSet.BoolVar(&args.zerokey, "zerokey", false, "Use all-zero dummy master key")
159-
flagSet.BoolVar(&args.openssl, "openssl", true, "Use OpenSSL instead of built-in Go crypto")
162+
flagSet.StringVar(&opensslAuto, "openssl", "auto", "Use OpenSSL instead of built-in Go crypto")
160163
flagSet.BoolVar(&args.passwd, "passwd", false, "Change password")
161164
flagSet.BoolVar(&args.foreground, "f", false, "Stay in the foreground")
162165
flagSet.BoolVar(&args.version, "version", false, "Print version and exit")
@@ -180,19 +183,30 @@ func main() {
180183
"Setting this to a lower value speeds up mounting but makes the password susceptible to brute-force attacks")
181184
flagSet.Parse(os.Args[1:])
182185

186+
// "-openssl" needs some post-processing
187+
if opensslAuto == "auto" {
188+
args.openssl = prefer_openssl.PreferOpenSSL()
189+
} else {
190+
args.openssl, err = strconv.ParseBool(opensslAuto)
191+
if err != nil {
192+
fmt.Printf(colorRed+"Invalid \"-openssl\" setting: %v\n"+colorReset, err)
193+
os.Exit(ERREXIT_USAGE)
194+
}
195+
}
196+
183197
// Fork a child into the background if "-f" is not set AND we are mounting a filesystem
184198
if !args.foreground && flagSet.NArg() == 2 {
185199
forkChild() // does not return
186200
}
201+
if args.debug {
202+
toggledlog.Debug.Enabled = true
203+
}
187204
// "-v"
188205
if args.version {
206+
toggledlog.Debug.Printf("openssl=%v\n", args.openssl)
189207
printVersion()
190208
os.Exit(0)
191209
}
192-
if args.debug {
193-
toggledlog.Debug.Enabled = true
194-
toggledlog.Debug.Printf("Debug output enabled")
195-
}
196210
if args.wpanic {
197211
toggledlog.Warn.Wpanic = true
198212
toggledlog.Debug.Printf("Panicing on warnings")
@@ -255,7 +269,9 @@ func main() {
255269
}
256270
// "-openssl"
257271
if args.openssl == false {
258-
toggledlog.Info.Printf("Openssl disabled")
272+
toggledlog.Debug.Printf("OpenSSL disabled, using Go GCM")
273+
} else {
274+
toggledlog.Debug.Printf("OpenSSL enabled")
259275
}
260276
// Operation flags: init, passwd or mount
261277
// "-init"

0 commit comments

Comments
 (0)