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