aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/crypto
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2014-08-12 14:35:27 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2014-08-12 14:35:27 -0700
commit67e1d40031d66bc2b67f422a17af0fea7e60effd (patch)
tree9302ebe606b672661d70325f1464faf188094ce4 /src/pkg/crypto
parent1837419f302da9b36055bf12b6a7f92c420cb32b (diff)
downloadgo-67e1d40031d66bc2b67f422a17af0fea7e60effd.tar.xz
crypto/rand: use getrandom system call on Linux
Adds internal/syscall package. Fixes #8520 LGTM=r, agl R=agl, rsc, r CC=golang-codereviews, iant https://golang.org/cl/123260044
Diffstat (limited to 'src/pkg/crypto')
-rw-r--r--src/pkg/crypto/rand/rand_linux.go39
-rw-r--r--src/pkg/crypto/rand/rand_unix.go11
2 files changed, 49 insertions, 1 deletions
diff --git a/src/pkg/crypto/rand/rand_linux.go b/src/pkg/crypto/rand/rand_linux.go
new file mode 100644
index 0000000000..8cb59c75df
--- /dev/null
+++ b/src/pkg/crypto/rand/rand_linux.go
@@ -0,0 +1,39 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+import (
+ "internal/syscall"
+ "sync"
+)
+
+func init() {
+ altGetRandom = getRandomLinux
+}
+
+var (
+ once sync.Once
+ useSyscall bool
+)
+
+func pickStrategy() {
+ // Test whether we should use the system call or /dev/urandom.
+ // We'll fall back to urandom if:
+ // - the kernel is too old (before 3.17)
+ // - the machine has no entropy available (early boot + no hardware
+ // entropy source?) and we want to avoid blocking later.
+ var buf [1]byte
+ n, err := syscall.GetRandom(buf[:], syscall.GRND_NONBLOCK)
+ useSyscall = n == 1 && err == nil
+}
+
+func getRandomLinux(p []byte) (ok bool) {
+ once.Do(pickStrategy)
+ if !useSyscall {
+ return false
+ }
+ n, err := syscall.GetRandom(p, 0)
+ return n == len(p) && err == nil
+}
diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go
index 1e741fda19..62d0fbdb35 100644
--- a/src/pkg/crypto/rand/rand_unix.go
+++ b/src/pkg/crypto/rand/rand_unix.go
@@ -20,6 +20,8 @@ import (
"time"
)
+const urandomDevice = "/dev/urandom"
+
// Easy implementation: read from /dev/urandom.
// This is sufficient on Linux, OS X, and FreeBSD.
@@ -27,7 +29,7 @@ func init() {
if runtime.GOOS == "plan9" {
Reader = newReader(nil)
} else {
- Reader = &devReader{name: "/dev/urandom"}
+ Reader = &devReader{name: urandomDevice}
}
}
@@ -38,7 +40,14 @@ type devReader struct {
mu sync.Mutex
}
+// altGetRandom if non-nil specifies an OS-specific function to get
+// urandom-style randomness.
+var altGetRandom func([]byte) (ok bool)
+
func (r *devReader) Read(b []byte) (n int, err error) {
+ if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
+ return len(b), nil
+ }
r.mu.Lock()
defer r.mu.Unlock()
if r.f == nil {