Skip to content

Commit

Permalink
prefer_openssl: autodetect whether to use OpenSSL or Go GCM
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rfjakob committed May 11, 2016
1 parent 384342f commit c54198e
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 8 deletions.
6 changes: 4 additions & 2 deletions Documentation/MANPAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,10 @@ continue be printed to stdout and stderr.
used internally for daemonization.

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

**-passwd**
: Change password
Expand Down
54 changes: 54 additions & 0 deletions internal/prefer_openssl/cpuinfo.pentium_g630.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Pentium(R) CPU G630 @ 2.70GHz
stepping : 7
microcode : 0x29
cpu MHz : 2700.000
cache size : 3072 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
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
bugs :
bogomips : 5387.85
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Pentium(R) CPU G630 @ 2.70GHz
stepping : 7
microcode : 0x29
cpu MHz : 2700.000
cache size : 3072 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
apicid : 2
initial apicid : 2
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
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
bugs :
bogomips : 5387.85
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

52 changes: 52 additions & 0 deletions internal/prefer_openssl/cpuinfo.xeon_e312xx.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel Xeon E312xx (Sandy Bridge)
stepping : 1
microcode : 0x1
cpu MHz : 3300.022
cache size : 4096 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
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
bogomips : 6600.04
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel Xeon E312xx (Sandy Bridge)
stepping : 1
microcode : 0x1
cpu MHz : 3300.022
cache size : 4096 KB
physical id : 1
siblings : 1
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
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
bogomips : 6600.04
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:

29 changes: 29 additions & 0 deletions internal/prefer_openssl/prefer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package prefer_openssl

import (
"fmt"
"io/ioutil"
"regexp"
)

// filePreferOpenSSL tells us if OpenSSL is faster than Go GCM on this machine.
// Go GCM is fastern when the CPU has AES instructions and Go is v1.6 or higher.
//
// See https://github.com/rfjakob/gocryptfs/issues/23#issuecomment-218286502
// for benchmarks.
//
// filePreferOpenSSL takes an explicit filename so it can be tested with saved
// cpuinfo files instead of /proc/cpuinfo.
func filePreferOpenSSL(file string) bool {
ci, err := ioutil.ReadFile(file)
if err != nil {
fmt.Println(err)
return true
}
haveAes, err := regexp.Match(`(?m)^flags.*\baes\b`, ci)
if err != nil {
fmt.Println(err)
return true
}
return !haveAes
}
9 changes: 9 additions & 0 deletions internal/prefer_openssl/prefer_go1.5.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build !go1.6
// = go 1.5 or lower

package prefer_openssl

func PreferOpenSSL() bool {
// OpenSSL is always faster than Go GCM on old Go versions.
return true
}
13 changes: 13 additions & 0 deletions internal/prefer_openssl/prefer_go1.6.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// +build go1.6
// = go 1.6 or higher

package prefer_openssl

// PreferOpenSSL tells us if OpenSSL is faster than Go GCM on this machine.
// Go GCM is fastern when the CPU has AES instructions and Go is v1.6 or higher.
//
// See https://github.com/rfjakob/gocryptfs/issues/23#issuecomment-218286502
// for benchmarks.
func PreferOpenSSL() bool {
return filePreferOpenSSL("/proc/cpuinfo")
}
19 changes: 19 additions & 0 deletions internal/prefer_openssl/prefer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package prefer_openssl

import (
"testing"
)

// Has AES instructions
func TestXeonE312xx(t *testing.T) {
if filePreferOpenSSL("cpuinfo.xeon_e312xx.txt") == true {
t.Fail()
}
}

// Pentium G do not have AES instructions
func TestPentiumG630(t *testing.T) {
if filePreferOpenSSL("cpuinfo.pentium_g630.txt") == false {
t.Fail()
}
}
28 changes: 22 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"path/filepath"
"runtime"
"runtime/pprof"
"strconv"
"syscall"
"time"

Expand All @@ -25,6 +26,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/cryptocore"
"github.com/rfjakob/gocryptfs/internal/fusefrontend"
"github.com/rfjakob/gocryptfs/internal/nametransform"
"github.com/rfjakob/gocryptfs/internal/prefer_openssl"
"github.com/rfjakob/gocryptfs/internal/toggledlog"
)

Expand Down Expand Up @@ -149,14 +151,15 @@ func main() {
setupColors()

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

// "-openssl" needs some post-processing
if opensslAuto == "auto" {
args.openssl = prefer_openssl.PreferOpenSSL()
} else {
args.openssl, err = strconv.ParseBool(opensslAuto)
if err != nil {
fmt.Printf(colorRed+"Invalid \"-openssl\" setting: %v\n"+colorReset, err)
os.Exit(ERREXIT_USAGE)
}
}

// Fork a child into the background if "-f" is not set AND we are mounting a filesystem
if !args.foreground && flagSet.NArg() == 2 {
forkChild() // does not return
}
if args.debug {
toggledlog.Debug.Enabled = true
}
// "-v"
if args.version {
toggledlog.Debug.Printf("openssl=%v\n", args.openssl)
printVersion()
os.Exit(0)
}
if args.debug {
toggledlog.Debug.Enabled = true
toggledlog.Debug.Printf("Debug output enabled")
}
if args.wpanic {
toggledlog.Warn.Wpanic = true
toggledlog.Debug.Printf("Panicing on warnings")
Expand Down Expand Up @@ -255,7 +269,9 @@ func main() {
}
// "-openssl"
if args.openssl == false {
toggledlog.Info.Printf("Openssl disabled")
toggledlog.Debug.Printf("OpenSSL disabled, using Go GCM")
} else {
toggledlog.Debug.Printf("OpenSSL enabled")
}
// Operation flags: init, passwd or mount
// "-init"
Expand Down

0 comments on commit c54198e

Please sign in to comment.