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