src/crypto/ecdh/nist.go | 2 +- src/crypto/ecdsa/ecdsa.go | 4 ++-- src/crypto/ed25519/ed25519.go | 3 +-- src/crypto/internal/rand/rand.go | 10 +++++++++- src/crypto/rand/rand.go | 19 +++++++------------ src/crypto/rsa/fips.go | 15 ++++++++------- src/crypto/rsa/pkcs1v15.go | 2 +- src/crypto/rsa/rsa.go | 2 +- diff --git a/src/crypto/ecdh/nist.go b/src/crypto/ecdh/nist.go index de7348d92323494e2ddc4fffc86aba121e777399..13865ea70129895ce10a56f303ac465be0944de9 100644 --- a/src/crypto/ecdh/nist.go +++ b/src/crypto/ecdh/nist.go @@ -27,7 +27,7 @@ return c.name } func (c *nistCurve) GenerateKey(r io.Reader) (*PrivateKey, error) { - if boring.Enabled && r == boring.RandReader { + if boring.Enabled && rand.IsDefaultReader(r) { key, bytes, err := boring.GenerateKeyECDH(c.name) if err != nil { return nil, err diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index aee15b9283854385ab88cc67267ededa900ed430..b336f32eb69ef57cd5797535c01b93357dfff6f9 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -334,7 +334,7 @@ // Since Go 1.26, a secure source of random bytes is always used, and the Reader is // ignored unless GODEBUG=cryptocustomrand=1 is set. This setting will be removed // in a future Go release. Instead, use [testing/cryptotest.SetGlobalRandom]. func GenerateKey(c elliptic.Curve, r io.Reader) (*PrivateKey, error) { - if boring.Enabled && r == boring.RandReader { + if boring.Enabled && rand.IsDefaultReader(r) { x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name) if err != nil { return nil, err @@ -380,7 +380,7 @@ // is always used, and the Reader is ignored unless GODEBUG=cryptocustomrand=1 // is set. This setting will be removed in a future Go release. Instead, use // [testing/cryptotest.SetGlobalRandom]. func SignASN1(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { - if boring.Enabled && r == boring.RandReader { + if boring.Enabled && rand.IsDefaultReader(r) { b, err := boringPrivateKey(priv) if err != nil { return nil, err diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go index f09dabe23e875dd6ba9d7dcc34daf22eb844d65a..a0263638ef19fe744b6e4694d63a0a23517a23ab 100644 --- a/src/crypto/ed25519/ed25519.go +++ b/src/crypto/ed25519/ed25519.go @@ -17,7 +17,6 @@ package ed25519 import ( "crypto" - "crypto/internal/fips140/drbg" "crypto/internal/fips140/ed25519" "crypto/internal/fips140cache" "crypto/internal/fips140only" @@ -153,7 +152,7 @@ func GenerateKey(random io.Reader) (PublicKey, PrivateKey, error) { if random == nil { if cryptocustomrand.Value() == "1" { random = cryptorand.Reader - if _, ok := random.(drbg.DefaultReader); !ok { + if !rand.IsDefaultReader(random) { cryptocustomrand.IncNonDefault() } } else { diff --git a/src/crypto/internal/rand/rand.go b/src/crypto/internal/rand/rand.go index 3a780952e705e5b3277ea95d6833414326736f55..29648b9f386ed76d5b4df12c5ca85dde2a7ca19a 100644 --- a/src/crypto/internal/rand/rand.go +++ b/src/crypto/internal/rand/rand.go @@ -55,7 +55,7 @@ // // If returning a non-default Reader, it calls [randutil.MaybeReadByte] on it. func CustomReader(r io.Reader) io.Reader { if cryptocustomrand.Value() == "1" { - if _, ok := r.(drbg.DefaultReader); !ok { + if !IsDefaultReader(r) { randutil.MaybeReadByte(r) cryptocustomrand.IncNonDefault() } @@ -63,3 +63,11 @@ return r } return Reader } + +// IsDefaultReader reports whether r is the default [crypto/rand.Reader]. +// +// If true, the Read method of r can be assumed to call [drbg.Read]. +func IsDefaultReader(r io.Reader) bool { + _, ok := r.(drbg.DefaultReader) + return ok +} diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go index 004e6b6fedc7fc4e696cba7f546fc0732bcbdcd9..018fe013cef6005780026fb9cb6bc4fbde3d3cc5 100644 --- a/src/crypto/rand/rand.go +++ b/src/crypto/rand/rand.go @@ -31,15 +31,7 @@ // - On wasip1/wasm, Reader uses random_get. // // In FIPS 140-3 mode, the output passes through an SP 800-90A Rev. 1 // Deterministric Random Bit Generator (DRBG). -var Reader io.Reader - -func init() { - if boring.Enabled { - Reader = boring.RandReader - return - } - Reader = rand.Reader -} +var Reader io.Reader = rand.Reader // fatal is [runtime.fatal], pushed via linkname. // @@ -57,9 +49,12 @@ // We don't want b to escape to the heap, but escape analysis can't see // through a potentially overridden Reader, so we special-case the default // case which we can keep non-escaping, and in the general case we read into // a heap buffer and copy from it. - if _, ok := Reader.(drbg.DefaultReader); ok { - boring.Unreachable() - drbg.Read(b) + if rand.IsDefaultReader(Reader) { + if boring.Enabled { + _, err = io.ReadFull(boring.RandReader, b) + } else { + drbg.Read(b) + } } else { bb := make([]byte, len(b)) _, err = io.ReadFull(Reader, bb) diff --git a/src/crypto/rsa/fips.go b/src/crypto/rsa/fips.go index 75aa3d3d725757c0bef36881a7f5ab711a9e435c..fb2395886b053bfaa0ff9eda3f9eea36b0781500 100644 --- a/src/crypto/rsa/fips.go +++ b/src/crypto/rsa/fips.go @@ -10,6 +10,7 @@ "crypto/internal/boring" "crypto/internal/fips140/rsa" "crypto/internal/fips140hash" "crypto/internal/fips140only" + "crypto/internal/rand" "errors" "hash" "io" @@ -59,9 +60,9 @@ // function. The opts argument may be nil, in which case sensible defaults are // used. If opts.Hash is set, it overrides hash. // // The signature is randomized depending on the message, key, and salt size, -// using bytes from rand. Most applications should use [crypto/rand.Reader] as -// rand. -func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) { +// using bytes from random. Most applications should use [crypto/rand.Reader] as +// random. +func SignPSS(random io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) { if err := checkPublicKeySize(&priv.PublicKey); err != nil { return nil, err } @@ -70,7 +71,7 @@ if opts != nil && opts.Hash != 0 { hash = opts.Hash } - if boring.Enabled && rand == boring.RandReader { + if boring.Enabled && rand.IsDefaultReader(random) { bkey, err := boringPrivateKey(priv) if err != nil { return nil, err @@ -87,7 +88,7 @@ } if fips140only.Enforced() && !fips140only.ApprovedHash(h) { return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") } - if fips140only.Enforced() && !fips140only.ApprovedRandomReader(rand) { + if fips140only.Enforced() && !fips140only.ApprovedRandomReader(random) { return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") } @@ -116,7 +117,7 @@ return nil, errors.New("crypto/rsa: invalid PSS salt length") } } - return fipsError2(rsa.SignPSS(rand, k, h, digest, saltLength)) + return fipsError2(rsa.SignPSS(random, k, h, digest, saltLength)) } // VerifyPSS verifies a PSS signature. @@ -216,7 +217,7 @@ defer hash.Reset() defer mgfHash.Reset() - if boring.Enabled && random == boring.RandReader { + if boring.Enabled && rand.IsDefaultReader(random) { k := pub.Size() if len(msg) > k-2*hash.Size()-2 { return nil, ErrMessageTooLong diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go index 0f216e0193252c6794ec7b3d39d90997cb11ba20..5269d7b971bda7db86d236c3c8c9435d91995a75 100644 --- a/src/crypto/rsa/pkcs1v15.go +++ b/src/crypto/rsa/pkcs1v15.go @@ -61,7 +61,7 @@ if len(msg) > k-11 { return nil, ErrMessageTooLong } - if boring.Enabled && random == boring.RandReader { + if boring.Enabled && rand.IsDefaultReader(random) { bkey, err := boringPublicKey(pub) if err != nil { return nil, err diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go index 62f2de30b0b8711a9a3bf7a59337a2ba1024ba31..b94b129867727bf802fb456b781dfcc6fbbddd2b 100644 --- a/src/crypto/rsa/rsa.go +++ b/src/crypto/rsa/rsa.go @@ -314,7 +314,7 @@ if err := checkKeySize(bits); err != nil { return nil, err } - if boring.Enabled && random == boring.RandReader && + if boring.Enabled && rand.IsDefaultReader(random) && (bits == 2048 || bits == 3072 || bits == 4096) { bN, bE, bD, bP, bQ, bDp, bDq, bQinv, err := boring.GenerateKeyRSA(bits) if err != nil {