mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
crypto/rand: warn to stderr if blocked 60+ sec on first Reader.Read call
Fixes #22614 Change-Id: I220afbaaeab4dec6d59eeeef12107234a77f1587 Reviewed-on: https://go-review.googlesource.com/c/139419 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
d16e4d34fc
commit
1961d8d72a
3 changed files with 21 additions and 0 deletions
|
|
@ -23,3 +23,7 @@ var Reader io.Reader
|
||||||
func Read(b []byte) (n int, err error) {
|
func Read(b []byte) (n int, err error) {
|
||||||
return io.ReadFull(Reader, b)
|
return io.ReadFull(Reader, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func warnBlocked() {
|
||||||
|
println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -39,6 +40,7 @@ type devReader struct {
|
||||||
name string
|
name string
|
||||||
f io.Reader
|
f io.Reader
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
used int32 // atomic; whether this devReader has been used
|
||||||
}
|
}
|
||||||
|
|
||||||
// altGetRandom if non-nil specifies an OS-specific function to get
|
// altGetRandom if non-nil specifies an OS-specific function to get
|
||||||
|
|
@ -46,6 +48,12 @@ type devReader struct {
|
||||||
var altGetRandom func([]byte) (ok bool)
|
var altGetRandom func([]byte) (ok bool)
|
||||||
|
|
||||||
func (r *devReader) Read(b []byte) (n int, err error) {
|
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
|
||||||
|
// being blocked on entropy not being available.
|
||||||
|
t := time.AfterFunc(60*time.Second, warnBlocked)
|
||||||
|
defer t.Stop()
|
||||||
|
}
|
||||||
if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
|
if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ package rand
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implemented by using Windows CryptoAPI 2.0.
|
// Implemented by using Windows CryptoAPI 2.0.
|
||||||
|
|
@ -19,11 +21,18 @@ func init() { Reader = &rngReader{} }
|
||||||
|
|
||||||
// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
|
// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
|
||||||
type rngReader struct {
|
type rngReader struct {
|
||||||
|
used int32 // atomic; whether this rngReader has been used
|
||||||
prov syscall.Handle
|
prov syscall.Handle
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rngReader) Read(b []byte) (n int, err error) {
|
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()
|
r.mu.Lock()
|
||||||
if r.prov == 0 {
|
if r.prov == 0 {
|
||||||
const provType = syscall.PROV_RSA_FULL
|
const provType = syscall.PROV_RSA_FULL
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue