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/fips140"
9 "crypto/internal/fips140/aes"
10 "crypto/internal/fips140/subtle"
11 "crypto/internal/fips140deps/byteorder"
12 "math/bits"
13 )
14 15 // Counter is an SP 800-90A Rev. 1 CTR_DRBG instantiated with AES-256.
16 //
17 // Per Table 3, it has a security strength of 256 bits, a seed size of 384 bits,
18 // a counter length of 128 bits, a reseed interval of 2^48 requests, and a
19 // maximum request size of 2^19 bits (2^16 bytes, 64 KiB).
20 //
21 // We support a narrow range of parameters that fit the needs of our RNG:
22 // AES-256, no derivation function, no personalization string, no prediction
23 // resistance, and 384-bit additional input.
24 //
25 // WARNING: this type provides tightly scoped support for the DRBG
26 // functionality we need for FIPS 140-3 _only_. This type _should not_ be used
27 // outside of the FIPS 140-3 module for any other use.
28 //
29 // In particular, as documented, Counter does not support the derivation
30 // function, or personalization strings which are necessary for safely using
31 // this DRBG for generic purposes without leaking sensitive values.
32 type Counter struct {
33 // c is instantiated with K as the key and V as the counter.
34 c aes.CTR
35 36 reseedCounter uint64
37 }
38 39 const (
40 keySize = 256 / 8
41 SeedSize = keySize + aes.BlockSize
42 reseedInterval = 1 << 48
43 maxRequestSize = (1 << 19) / 8
44 )
45 46 func NewCounter(entropy *[SeedSize]byte) *Counter {
47 // CTR_DRBG_Instantiate_algorithm, per Section 10.2.1.3.1.
48 fips140.RecordApproved()
49 50 K := []byte{:keySize}
51 V := []byte{:aes.BlockSize}
52 53 // V starts at 0, but is incremented in CTR_DRBG_Update before each use,
54 // unlike AES-CTR where it is incremented after each use.
55 V[len(V)-1] = 1
56 57 cipher, err := aes.New(K)
58 if err != nil {
59 panic(err)
60 }
61 62 c := &Counter{}
63 c.c = *aes.NewCTR(cipher, V)
64 c.update(entropy)
65 c.reseedCounter = 1
66 return c
67 }
68 69 func (c *Counter) update(seed *[SeedSize]byte) {
70 // CTR_DRBG_Update, per Section 10.2.1.2.
71 72 temp := []byte{:SeedSize}
73 c.c.XORKeyStream(temp, seed[:])
74 K := temp[:keySize]
75 V := temp[keySize:]
76 77 // Again, we pre-increment V, like in NewCounter.
78 increment((*[aes.BlockSize]byte)(V))
79 80 cipher, err := aes.New(K)
81 if err != nil {
82 panic(err)
83 }
84 c.c = *aes.NewCTR(cipher, V)
85 }
86 87 func increment(v *[aes.BlockSize]byte) {
88 hi := byteorder.BEUint64(v[:8])
89 lo := byteorder.BEUint64(v[8:])
90 lo, c := bits.Add64(lo, 1, 0)
91 hi, _ = bits.Add64(hi, 0, c)
92 byteorder.BEPutUint64(v[:8], hi)
93 byteorder.BEPutUint64(v[8:], lo)
94 }
95 96 func (c *Counter) Reseed(entropy, additionalInput *[SeedSize]byte) {
97 // CTR_DRBG_Reseed_algorithm, per Section 10.2.1.4.1.
98 fips140.RecordApproved()
99 100 var seed [SeedSize]byte
101 subtle.XORBytes(seed[:], entropy[:], additionalInput[:])
102 c.update(&seed)
103 c.reseedCounter = 1
104 }
105 106 // Generate produces at most maxRequestSize bytes of random data in out.
107 func (c *Counter) Generate(out []byte, additionalInput *[SeedSize]byte) (reseedRequired bool) {
108 // CTR_DRBG_Generate_algorithm, per Section 10.2.1.5.1.
109 fips140.RecordApproved()
110 111 if len(out) > maxRequestSize {
112 panic("crypto/drbg: internal error: request size exceeds maximum")
113 }
114 115 // Step 1.
116 if c.reseedCounter > reseedInterval {
117 return true
118 }
119 120 // Step 2.
121 if additionalInput != nil {
122 c.update(additionalInput)
123 } else {
124 // If the additional input is null, the first CTR_DRBG_Update is
125 // skipped, but the additional input is replaced with an all-zero string
126 // for the second CTR_DRBG_Update.
127 additionalInput = &[SeedSize]byte{}
128 }
129 130 // Steps 3-5.
131 clear(out)
132 c.c.XORKeyStream(out, out)
133 aes.RoundToBlock(&c.c)
134 135 // Step 6.
136 c.update(additionalInput)
137 138 // Step 7.
139 c.reseedCounter++
140 141 // Step 8.
142 return false
143 }
144