From 5eb3981fe23080fd73269e89ba7abefd9bd4d342 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 21 Jun 2018 13:56:39 +0100 Subject: [PATCH] crypto/rand module code refactoring --- src/crypto/rand/rand_batched.go | 42 +++++++++++++++++++++++++++++++++ src/crypto/rand/rand_freebsd.go | 36 ---------------------------- src/crypto/rand/rand_linux.go | 38 +---------------------------- 3 files changed, 43 insertions(+), 73 deletions(-) create mode 100644 src/crypto/rand/rand_batched.go diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go new file mode 100644 index 0000000000..63ef762719 --- /dev/null +++ b/src/crypto/rand/rand_batched.go @@ -0,0 +1,42 @@ +// 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 linux freebsd + +package rand + +import ( + "internal/syscall/unix" +) + +// maxGetRandomRead is platform dependent. +func init() { + altGetRandom = batched(getRandomLinux, maxGetRandomRead) +} + +// batched returns a function that calls f to populate a []byte by chunking it +// into subslices of, at most, readMax bytes. +func batched(f func([]byte) bool, readMax int) func([]byte) bool { + return func(buf []byte) bool { + for len(buf) > readMax { + if !f(buf[:readMax]) { + return false + } + buf = buf[readMax:] + } + return len(buf) == 0 || f(buf) + } +} + +// If the kernel is too old to support the getrandom syscall(), +// unix.GetRandom will immediately return ENOSYS and we will then fall back to +// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS +// result so we only suffer the syscall overhead once in this case. +// If the kernel supports the getrandom() syscall, unix.GetRandom will block +// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). +// In this case, unix.GetRandom will not return an error. +func getRandomLinux(p []byte) (ok bool) { + n, err := unix.GetRandom(p, 0) + return n == len(p) && err == nil +} diff --git a/src/crypto/rand/rand_freebsd.go b/src/crypto/rand/rand_freebsd.go index 0dfaa161b8..b4d6653343 100644 --- a/src/crypto/rand/rand_freebsd.go +++ b/src/crypto/rand/rand_freebsd.go @@ -2,44 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd - package rand -import ( - "internal/syscall/unix" -) - -func init() { - altGetRandom = batched(getRandomFreeBSD, maxGetRandomRead) -} - // maxGetRandomRead is the maximum number of bytes to ask for in one call to the // getrandom() syscall. In FreeBSD at most 256 bytes will be returned per call. const maxGetRandomRead = (1 << 8) - -// batched returns a function that calls f to populate a []byte by chunking it -// into subslices of, at most, readMax bytes. -func batched(f func([]byte) bool, readMax int) func([]byte) bool { - return func(buf []byte) bool { - for len(buf) > readMax { - if !f(buf[:readMax]) { - return false - } - buf = buf[readMax:] - } - return len(buf) == 0 || f(buf) - } -} - -// If the kernel is too old (before 12) to support the getrandom syscall(), -// unix.GetRandom will immediately return ENOSYS and we will then fall back to -// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS -// result so we only suffer the syscall overhead once in this case. -// If the kernel supports the getrandom() syscall, unix.GetRandom will block -// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). -// In this case, unix.GetRandom will not return an error. -func getRandomFreeBSD(p []byte) (ok bool) { - n, err := unix.GetRandom(p, 0) - return n == len(p) && err == nil -} diff --git a/src/crypto/rand/rand_linux.go b/src/crypto/rand/rand_linux.go index 998d449c76..659f59098f 100644 --- a/src/crypto/rand/rand_linux.go +++ b/src/crypto/rand/rand_linux.go @@ -1,19 +1,9 @@ -// Copyright 2014 The Go Authors. All rights reserved. +// Copyright 2018 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 linux - package rand -import ( - "internal/syscall/unix" -) - -func init() { - altGetRandom = batched(getRandomLinux, maxGetRandomRead) -} - // maxGetRandomRead is the maximum number of bytes to ask for in one call to the // getrandom() syscall. In linux at most 2^25-1 bytes will be returned per call. // From the manpage @@ -22,29 +12,3 @@ func init() { // is returned by a single call to getrandom() on systems where int // has a size of 32 bits. const maxGetRandomRead = (1 << 25) - 1 - -// batched returns a function that calls f to populate a []byte by chunking it -// into subslices of, at most, readMax bytes. -func batched(f func([]byte) bool, readMax int) func([]byte) bool { - return func(buf []byte) bool { - for len(buf) > readMax { - if !f(buf[:readMax]) { - return false - } - buf = buf[readMax:] - } - return len(buf) == 0 || f(buf) - } -} - -// If the kernel is too old (before 3.17) to support the getrandom syscall(), -// unix.GetRandom will immediately return ENOSYS and we will then fall back to -// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS -// result so we only suffer the syscall overhead once in this case. -// If the kernel supports the getrandom() syscall, unix.GetRandom will block -// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). -// In this case, unix.GetRandom will not return an error. -func getRandomLinux(p []byte) (ok bool) { - n, err := unix.GetRandom(p, 0) - return n == len(p) && err == nil -}