diff options
Diffstat (limited to 'libgo/go/crypto/rand')
-rw-r--r-- | libgo/go/crypto/rand/eagain.go | 27 | ||||
-rw-r--r-- | libgo/go/crypto/rand/rand.go | 2 | ||||
-rw-r--r-- | libgo/go/crypto/rand/rand_linux.go | 6 | ||||
-rw-r--r-- | libgo/go/crypto/rand/rand_unix.go | 18 | ||||
-rw-r--r-- | libgo/go/crypto/rand/util_test.go | 2 |
5 files changed, 50 insertions, 5 deletions
diff --git a/libgo/go/crypto/rand/eagain.go b/libgo/go/crypto/rand/eagain.go new file mode 100644 index 00000000000..2c853d0a134 --- /dev/null +++ b/libgo/go/crypto/rand/eagain.go @@ -0,0 +1,27 @@ +// 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. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package rand + +import ( + "os" + "syscall" +) + +func init() { + isEAGAIN = unixIsEAGAIN +} + +// unixIsEAGAIN reports whether err is a syscall.EAGAIN wrapped in a PathError. +// See golang.org/issue/9205 +func unixIsEAGAIN(err error) bool { + if pe, ok := err.(*os.PathError); ok { + if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN { + return true + } + } + return false +} diff --git a/libgo/go/crypto/rand/rand.go b/libgo/go/crypto/rand/rand.go index 4da3adb7010..ee32fa0bd67 100644 --- a/libgo/go/crypto/rand/rand.go +++ b/libgo/go/crypto/rand/rand.go @@ -10,7 +10,9 @@ import "io" // Reader is a global, shared instance of a cryptographically // strong pseudo-random generator. +// // On Unix-like systems, Reader reads from /dev/urandom. +// On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise. // On Windows systems, Reader uses the CryptGenRandom API. var Reader io.Reader diff --git a/libgo/go/crypto/rand/rand_linux.go b/libgo/go/crypto/rand/rand_linux.go index 8cb59c75dff..7d6d9e8a094 100644 --- a/libgo/go/crypto/rand/rand_linux.go +++ b/libgo/go/crypto/rand/rand_linux.go @@ -5,7 +5,7 @@ package rand import ( - "internal/syscall" + "internal/syscall/unix" "sync" ) @@ -25,7 +25,7 @@ func pickStrategy() { // - 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) + n, err := unix.GetRandom(buf[:], unix.GRND_NONBLOCK) useSyscall = n == 1 && err == nil } @@ -34,6 +34,6 @@ func getRandomLinux(p []byte) (ok bool) { if !useSyscall { return false } - n, err := syscall.GetRandom(p, 0) + n, err := unix.GetRandom(p, 0) return n == len(p) && err == nil } diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go index 62d0fbdb350..75c36e05b34 100644 --- a/libgo/go/crypto/rand/rand_unix.go +++ b/libgo/go/crypto/rand/rand_unix.go @@ -58,12 +58,28 @@ func (r *devReader) Read(b []byte) (n int, err error) { if runtime.GOOS == "plan9" { r.f = f } else { - r.f = bufio.NewReader(f) + r.f = bufio.NewReader(hideAgainReader{f}) } } return r.f.Read(b) } +var isEAGAIN func(error) bool // set by eagain.go on unix systems + +// hideAgainReader masks EAGAIN reads from /dev/urandom. +// See golang.org/issue/9205 +type hideAgainReader struct { + r io.Reader +} + +func (hr hideAgainReader) Read(p []byte) (n int, err error) { + n, err = hr.r.Read(p) + if err != nil && isEAGAIN != nil && isEAGAIN(err) { + err = nil + } + return +} + // Alternate pseudo-random implementation for use on // systems without a reliable /dev/urandom. diff --git a/libgo/go/crypto/rand/util_test.go b/libgo/go/crypto/rand/util_test.go index 1e2a4dd84b7..2f7cba8364a 100644 --- a/libgo/go/crypto/rand/util_test.go +++ b/libgo/go/crypto/rand/util_test.go @@ -10,7 +10,7 @@ import ( "testing" ) -// http://golang.org/issue/6849. +// https://golang.org/issue/6849. func TestPrimeSmall(t *testing.T) { for n := 2; n < 10; n++ { p, err := rand.Prime(rand.Reader, n) |