]> git.feebdaed.xyz Git - 0xmirror/go.git/commitdiff
crypto: use rand.IsDefaultReader instead of comparing to boring.RandReader
authorqmuntal <quimmuntal@gmail.com>
Wed, 3 Dec 2025 10:20:41 +0000 (11:20 +0100)
committerQuim Muntal <quimmuntal@gmail.com>
Thu, 4 Dec 2025 16:39:49 +0000 (08:39 -0800)
Several crypto functions accepting a rand parameter skip calling
boringcrypto when the rand is not boring.RandReader.

The new crypto/internal/rand package currently defines its own Reader
that wraps boring.RandReader. That will unintentionally bypass
boringcrypto when used with the aforementioned functions.

Fixes #76672

Change-Id: Ie0c1345530c734a23815f9593590b5d32604f54d
Reviewed-on: https://go-review.googlesource.com/c/go/+/726220
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/crypto/ecdh/nist.go
src/crypto/ecdsa/ecdsa.go
src/crypto/ed25519/ed25519.go
src/crypto/internal/rand/rand.go
src/crypto/rand/rand.go
src/crypto/rsa/fips.go
src/crypto/rsa/pkcs1v15.go
src/crypto/rsa/rsa.go

index de7348d92323494e2ddc4fffc86aba121e777399..13865ea70129895ce10a56f303ac465be0944de9 100644 (file)
@@ -27,7 +27,7 @@ func (c *nistCurve) String() string {
 }
 
 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
index aee15b9283854385ab88cc67267ededa900ed430..b336f32eb69ef57cd5797535c01b93357dfff6f9 100644 (file)
@@ -334,7 +334,7 @@ func (priv *PrivateKey) Sign(random io.Reader, digest []byte, opts crypto.Signer
 // 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 @@ func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], ran
 // 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
index f09dabe23e875dd6ba9d7dcc34daf22eb844d65a..a0263638ef19fe744b6e4694d63a0a23517a23ab 100644 (file)
@@ -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 {
index 3a780952e705e5b3277ea95d6833414326736f55..29648b9f386ed76d5b4df12c5ca85dde2a7ca19a 100644 (file)
@@ -55,7 +55,7 @@ var cryptocustomrand = godebug.New("cryptocustomrand")
 // 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 @@ func CustomReader(r io.Reader) io.Reader {
        }
        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
+}
index 004e6b6fedc7fc4e696cba7f546fc0732bcbdcd9..018fe013cef6005780026fb9cb6bc4fbde3d3cc5 100644 (file)
@@ -31,15 +31,7 @@ import (
 //
 // 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 @@ func Read(b []byte) (n int, err error) {
        // 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)
index 75aa3d3d725757c0bef36881a7f5ab711a9e435c..fb2395886b053bfaa0ff9eda3f9eea36b0781500 100644 (file)
@@ -10,6 +10,7 @@ import (
        "crypto/internal/fips140/rsa"
        "crypto/internal/fips140hash"
        "crypto/internal/fips140only"
+       "crypto/internal/rand"
        "errors"
        "hash"
        "io"
@@ -59,9 +60,9 @@ func (opts *PSSOptions) saltLength() int {
 // 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 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
                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 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
        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 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
                }
        }
 
-       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 @@ func encryptOAEP(hash hash.Hash, mgfHash hash.Hash, random io.Reader, pub *Publi
        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
index 0f216e0193252c6794ec7b3d39d90997cb11ba20..5269d7b971bda7db86d236c3c8c9435d91995a75 100644 (file)
@@ -61,7 +61,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro
                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
index 62f2de30b0b8711a9a3bf7a59337a2ba1024ba31..b94b129867727bf802fb456b781dfcc6fbbddd2b 100644 (file)
@@ -314,7 +314,7 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
                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 {