Source file src/crypto/internal/rand/rand.go
1 // Copyright 2025 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rand 6 7 import ( 8 "crypto/internal/boring" 9 "crypto/internal/fips140/drbg" 10 "crypto/internal/randutil" 11 "internal/godebug" 12 "io" 13 _ "unsafe" 14 ) 15 16 // defaultReader aliases [drbg.DefaultReader], so that [reader] 17 // does not have an exported DefaultReader field. 18 type defaultReader = drbg.DefaultReader 19 20 type reader struct{ defaultReader } 21 22 func (r reader) Read(b []byte) (n int, err error) { 23 if boring.Enabled { 24 if _, err := boring.RandReader.Read(b); err != nil { 25 panic("crypto/rand: boring RandReader failed: " + err.Error()) 26 } 27 return len(b), nil 28 } 29 drbg.Read(b) 30 return len(b), nil 31 } 32 33 // Reader is an io.Reader that calls [drbg.Read]. 34 // 35 // It should be used internally instead of [crypto/rand.Reader], because the 36 // latter can be set by applications outside of tests. These applications then 37 // risk breaking between Go releases, if the way the Reader is used changes. 38 var Reader io.Reader = reader{} 39 40 // SetTestingReader overrides all calls to [drbg.Read]. The Read method of 41 // r must never return an error or return short. 42 // 43 // SetTestingReader panics when building against Go Cryptographic Module v1.0.0. 44 // 45 // SetTestingReader is pulled by [testing/cryptotest.SetGlobalRandom] via go:linkname. 46 // 47 //go:linkname SetTestingReader crypto/internal/rand.SetTestingReader 48 func SetTestingReader(r io.Reader) { 49 testingReader = r 50 fips140SetTestingReader(r) 51 } 52 53 var testingReader io.Reader 54 55 var cryptocustomrand = godebug.New("cryptocustomrand") 56 57 // CustomReader returns [Reader] or, only if the GODEBUG setting 58 // "cryptocustomrand=1" is set, the provided io.Reader. 59 // 60 // If returning a non-default Reader, it calls [randutil.MaybeReadByte] on it, 61 // unless it's the global testing Reader set with [SetTestingReader]. 62 func CustomReader(r io.Reader) io.Reader { 63 if cryptocustomrand.Value() == "1" { 64 if !IsDefaultReader(r) { 65 if r != testingReader { 66 randutil.MaybeReadByte(r) 67 } 68 cryptocustomrand.IncNonDefault() 69 } 70 return r 71 } 72 return Reader 73 } 74