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