crypto: use rand.IsDefaultReader instead of comparing to boring.RandReader

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>
This commit is contained in:
qmuntal 2025-12-03 11:20:41 +01:00 committed by Quim Muntal
parent 7b67b68a0d
commit 1681c3b67f
8 changed files with 30 additions and 27 deletions

View 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

View 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

View 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 {

View 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
}

View 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)

View 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

View 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

View 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 {