| // Copyright 2025 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package rand |
| |
| import ( |
| "crypto/internal/boring" |
| "crypto/internal/fips140/drbg" |
| "crypto/internal/randutil" |
| "internal/godebug" |
| "io" |
| _ "unsafe" |
| ) |
| |
| type reader struct { |
| drbg.DefaultReader |
| } |
| |
| func (r reader) Read(b []byte) (n int, err error) { |
| if boring.Enabled { |
| if _, err := boring.RandReader.Read(b); err != nil { |
| panic("crypto/rand: boring RandReader failed: " + err.Error()) |
| } |
| return len(b), nil |
| } |
| drbg.Read(b) |
| return len(b), nil |
| } |
| |
| // Reader is an io.Reader that calls [drbg.Read]. |
| // |
| // It should be used internally instead of [crypto/rand.Reader], because the |
| // latter can be set by applications outside of tests. These applications then |
| // risk breaking between Go releases, if the way the Reader is used changes. |
| var Reader io.Reader = reader{} |
| |
| // SetTestingReader overrides all calls to [drbg.Read]. The Read method of |
| // r must never return an error or return short. |
| // |
| // SetTestingReader panics when building against Go Cryptographic Module v1.0.0. |
| // |
| // SetTestingReader is pulled by [testing/cryptotest.setGlobalRandom] via go:linkname. |
| // |
| //go:linkname SetTestingReader crypto/internal/rand.SetTestingReader |
| func SetTestingReader(r io.Reader) { |
| fips140SetTestingReader(r) |
| } |
| |
| var cryptocustomrand = godebug.New("cryptocustomrand") |
| |
| // CustomReader returns [Reader] or, only if the GODEBUG setting |
| // "cryptocustomrand=1" is set, the provided io.Reader. |
| // |
| // If returning a non-default Reader, it calls [randutil.MaybeReadByte] on it. |
| func CustomReader(r io.Reader) io.Reader { |
| if cryptocustomrand.Value() == "1" { |
| if !IsDefaultReader(r) { |
| randutil.MaybeReadByte(r) |
| cryptocustomrand.IncNonDefault() |
| } |
| 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 |
| } |