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 := &[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