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 6 7 import ( 8 "crypto/internal/entropy" 9 "crypto/internal/fips140" 10 "crypto/internal/randutil" 11 "crypto/internal/sysrand" 12 "io" 13 "sync" 14 ) 15 16 var mu sync.Mutex 17 var drbg *Counter 18 19 // Read fills b with cryptographically secure random bytes. In FIPS mode, it 20 // uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG). 21 // Otherwise, it uses the operating system's random number generator. 22 func Read(b []byte) { 23 if !fips140.Enabled { 24 sysrand.Read(b) 25 return 26 } 27 28 // At every read, 128 random bits from the operating system are mixed as 29 // additional input, to make the output as strong as non-FIPS randomness. 30 // This is not credited as entropy for FIPS purposes, as allowed by Section 31 // 8.7.2: "Note that a DRBG does not rely on additional input to provide 32 // entropy, even though entropy could be provided in the additional input". 33 additionalInput := new([SeedSize]byte) 34 sysrand.Read(additionalInput[:16]) 35 36 mu.Lock() 37 defer mu.Unlock() 38 39 if drbg == nil { 40 entropy.Depleted(func(seed *[48]byte) { 41 drbg = NewCounter(seed) 42 }) 43 } 44 45 for len(b) > 0 { 46 size := min(len(b), maxRequestSize) 47 if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired { 48 // See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in 49 // Section 9.3.2: if Generate reports a reseed is required, the 50 // additional input is passed to Reseed along with the entropy and 51 // then nulled before the next Generate call. 52 entropy.Depleted(func(seed *[48]byte) { 53 drbg.Reseed(seed, additionalInput) 54 }) 55 additionalInput = nil 56 continue 57 } 58 b = b[size:] 59 } 60 } 61 62 // DefaultReader is a sentinel type, embedded in the default 63 // [crypto/rand.Reader], used to recognize it when passed to 64 // APIs that accept a rand io.Reader. 65 type DefaultReader interface{ defaultReader() } 66 67 // ReadWithReader uses Reader to fill b with cryptographically secure random 68 // bytes. It is intended for use in APIs that expose a rand io.Reader. 69 // 70 // If Reader is not the default Reader from crypto/rand, 71 // [randutil.MaybeReadByte] and [fips140.RecordNonApproved] are called. 72 func ReadWithReader(r io.Reader, b []byte) error { 73 if _, ok := r.(DefaultReader); ok { 74 Read(b) 75 return nil 76 } 77 78 fips140.RecordNonApproved() 79 randutil.MaybeReadByte(r) 80 _, err := io.ReadFull(r, b) 81 return err 82 } 83 84 // ReadWithReaderDeterministic is like ReadWithReader, but it doesn't call 85 // [randutil.MaybeReadByte] on non-default Readers. 86 func ReadWithReaderDeterministic(r io.Reader, b []byte) error { 87 if _, ok := r.(DefaultReader); ok { 88 Read(b) 89 return nil 90 } 91 92 fips140.RecordNonApproved() 93 _, err := io.ReadFull(r, b) 94 return err 95 } 96