summaryrefslogtreecommitdiff
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
commitc3374e3eaf4ec6bc10cb6637f089fd5845bb1270 (patch)
treecb0a025dbbe72900d2e36dfb439ab81a07a75749 /src/pkg/crypto
parentda708d8620611d27dc1789b778fc66ec262cf155 (diff)
downloadgo-c3374e3eaf4ec6bc10cb6637f089fd5845bb1270.tar.gz
crypto/rand: use getrandom system call on Linux
Adds internal/syscall package. Fixes Issue 8520 LGTM=r, agl R=agl, rsc, r CC=golang-codereviews, iant https://codereview.appspot.com/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 000000000..8cb59c75d
--- /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 1e741fda1..62d0fbdb3 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 {