Source file src/crypto/internal/fips140/drbg/rand.go
1 // Copyright 2024 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 drbg provides cryptographically secure random bytes 6 // usable by FIPS code. In FIPS mode it uses an SP 800-90A Rev. 1 7 // Deterministic Random Bit Generator (DRBG). Otherwise, 8 // it uses the operating system's random number generator. 9 package drbg 10 11 import ( 12 "crypto/internal/fips140" 13 "crypto/internal/sysrand" 14 "io" 15 "sync" 16 "sync/atomic" 17 ) 18 19 // getEntropy is very slow (~500µs), so we don't want it on the hot path. 20 // We keep both a persistent DRBG instance and a pool of additional instances. 21 // Occasional uses will use drbgInstance, even if the pool was emptied since the 22 // last use. Frequent concurrent uses will fill the pool and use it. 23 var drbgInstance atomic.Pointer[Counter] 24 var drbgPool = sync.Pool{ 25 New: func() any { 26 return NewCounter(getEntropy()) 27 }, 28 } 29 30 // Read fills b with cryptographically secure random bytes. In FIPS mode, it 31 // uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG). 32 // Otherwise, it uses the operating system's random number generator. 33 func Read(b []byte) { 34 if testingReader != nil { 35 fips140.RecordNonApproved() 36 // Avoid letting b escape in the non-testing case. 37 bb := make([]byte, len(b)) 38 testingReader.Read(bb) 39 copy(b, bb) 40 return 41 } 42 43 if !fips140.Enabled { 44 sysrand.Read(b) 45 return 46 } 47 48 // At every read, 128 random bits from the operating system are mixed as 49 // additional input, to make the output as strong as non-FIPS randomness. 50 // This is not credited as entropy for FIPS purposes, as allowed by Section 51 // 8.7.2: "Note that a DRBG does not rely on additional input to provide 52 // entropy, even though entropy could be provided in the additional input". 53 additionalInput := new([SeedSize]byte) 54 sysrand.Read(additionalInput[:16]) 55 56 drbg := drbgInstance.Swap(nil) 57 if drbg == nil { 58 drbg = drbgPool.Get().(*Counter) 59 } 60 defer func() { 61 if !drbgInstance.CompareAndSwap(nil, drbg) { 62 drbgPool.Put(drbg) 63 } 64 }() 65 66 for len(b) > 0 { 67 size := min(len(b), maxRequestSize) 68 if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired { 69 // See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in 70 // Section 9.3.2: if Generate reports a reseed is required, the 71 // additional input is passed to Reseed along with the entropy and 72 // then nulled before the next Generate call. 73 drbg.Reseed(getEntropy(), additionalInput) 74 additionalInput = nil 75 continue 76 } 77 b = b[size:] 78 } 79 } 80 81 var testingReader io.Reader 82 83 // SetTestingReader sets a global, deterministic cryptographic randomness source 84 // for testing purposes. Its Read method must never return an error, it must 85 // never return short, and it must be safe for concurrent use. 86 // 87 // This is only intended to be used by the testing/cryptotest package. 88 func SetTestingReader(r io.Reader) { 89 testingReader = r 90 } 91 92 // DefaultReader is a sentinel type, embedded in the default 93 // [crypto/rand.Reader], used to recognize it when passed to 94 // APIs that accept a rand io.Reader. 95 // 96 // Any [io.Reader] that embeds this type is assumed to 97 // call [Read] as its [io.Reader.Read] method. 98 type DefaultReader struct{} 99 100 func (d DefaultReader) defaultReader() {} 101 102 // IsDefaultReader reports whether the r embeds the [DefaultReader] type. 103 func IsDefaultReader(r io.Reader) bool { 104 _, ok := r.(interface{ defaultReader() }) 105 return ok 106 } 107 108 // ReadWithReader uses Reader to fill b with cryptographically secure random 109 // bytes. It is intended for use in APIs that expose a rand io.Reader. 110 func ReadWithReader(r io.Reader, b []byte) error { 111 if IsDefaultReader(r) { 112 Read(b) 113 return nil 114 } 115 116 fips140.RecordNonApproved() 117 _, err := io.ReadFull(r, b) 118 return err 119 } 120