aboutsummaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-12-05 18:48:21 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-10-27 12:00:35 +0000
commit333e90448a0e55f2e1161853caecf3d30ef3a74a (patch)
treeecdf3def80d320fd29ea5ae5f7a8016b1c5767a9 /src/crypto
parent8a013233ac53d934e53cd7d118b5ff7836d8973a (diff)
downloadgo-333e90448a0e55f2e1161853caecf3d30ef3a74a.tar.gz
go-333e90448a0e55f2e1161853caecf3d30ef3a74a.zip
crypto/rand: generate random numbers using RtlGenRandom on Windows
CryptGenRandom appears to be unfavorable these days, whereas the classic RtlGenRandom is still going strong. This commit also moves the warnBlocked function into rand_unix, rather than rand, because it's now only used on unix. Fixes #33542 Change-Id: I5c02a5917572f54079d627972401efb6e1ce4057 Reviewed-on: https://go-review.googlesource.com/c/go/+/210057 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Filippo Valsorda <filippo@golang.org> Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/rand/rand.go6
-rw-r--r--src/crypto/rand/rand_unix.go4
-rw-r--r--src/crypto/rand/rand_windows.go40
3 files changed, 13 insertions, 37 deletions
diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
index a5ccd19de3..fddd1147e6 100644
--- a/src/crypto/rand/rand.go
+++ b/src/crypto/rand/rand.go
@@ -14,7 +14,7 @@ import "io"
// On Linux and FreeBSD, Reader uses getrandom(2) if available, /dev/urandom otherwise.
// On OpenBSD, Reader uses getentropy(2).
// On other Unix-like systems, Reader reads from /dev/urandom.
-// On Windows systems, Reader uses the CryptGenRandom API.
+// On Windows systems, Reader uses the RtlGenRandom API.
// On Wasm, Reader uses the Web Crypto API.
var Reader io.Reader
@@ -23,7 +23,3 @@ var Reader io.Reader
func Read(b []byte) (n int, err error) {
return io.ReadFull(Reader, b)
}
-
-func warnBlocked() {
- println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
-}
diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
index 0610f691b0..548a5e4cb9 100644
--- a/src/crypto/rand/rand_unix.go
+++ b/src/crypto/rand/rand_unix.go
@@ -47,6 +47,10 @@ type devReader struct {
// urandom-style randomness.
var altGetRandom func([]byte) (ok bool)
+func warnBlocked() {
+ println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
+}
+
func (r *devReader) Read(b []byte) (n int, err error) {
if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
// First use of randomness. Start timer to warn about
diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
index 78a4ed6d67..8b2c960906 100644
--- a/src/crypto/rand/rand_windows.go
+++ b/src/crypto/rand/rand_windows.go
@@ -9,48 +9,24 @@ package rand
import (
"os"
- "sync"
- "sync/atomic"
"syscall"
- "time"
)
-// Implemented by using Windows CryptoAPI 2.0.
-
func init() { Reader = &rngReader{} }
-// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
-type rngReader struct {
- used int32 // atomic; whether this rngReader has been used
- prov syscall.Handle
- mu sync.Mutex
-}
+type rngReader struct{}
func (r *rngReader) Read(b []byte) (n int, err error) {
- if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
- // First use of randomness. Start timer to warn about
- // being blocked on entropy not being available.
- t := time.AfterFunc(60*time.Second, warnBlocked)
- defer t.Stop()
- }
- r.mu.Lock()
- if r.prov == 0 {
- const provType = syscall.PROV_RSA_FULL
- const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
- err := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
- if err != nil {
- r.mu.Unlock()
- return 0, os.NewSyscallError("CryptAcquireContext", err)
- }
- }
- r.mu.Unlock()
+ // RtlGenRandom only accepts 2**32-1 bytes at a time, so truncate.
+ inputLen := uint32(len(b))
- if len(b) == 0 {
+ if inputLen == 0 {
return 0, nil
}
- err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
+
+ err = syscall.RtlGenRandom(&b[0], inputLen)
if err != nil {
- return 0, os.NewSyscallError("CryptGenRandom", err)
+ return 0, os.NewSyscallError("RtlGenRandom", err)
}
- return len(b), nil
+ return int(inputLen), nil
}