diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2014-08-12 14:35:27 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2014-08-12 14:35:27 -0700 |
commit | c3374e3eaf4ec6bc10cb6637f089fd5845bb1270 (patch) | |
tree | cb0a025dbbe72900d2e36dfb439ab81a07a75749 /src/pkg/crypto | |
parent | da708d8620611d27dc1789b778fc66ec262cf155 (diff) | |
download | go-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.go | 39 | ||||
-rw-r--r-- | src/pkg/crypto/rand/rand_unix.go | 11 |
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 { |