1
2
3
4
5 package ecdsa
6
7 import (
8 "bytes"
9 "crypto/internal/fips140"
10 "crypto/internal/fips140/hmac"
11 "hash"
12 )
13
14
15
16
17
18
19
20
21
22 type hmacDRBG struct {
23 newHMAC func(key []byte) *hmac.HMAC
24
25 hK *hmac.HMAC
26 V []byte
27
28 reseedCounter uint64
29 }
30
31 const (
32 reseedInterval = 1 << 48
33 maxRequestSize = (1 << 19) / 8
34 )
35
36
37 type plainPersonalizationString []byte
38
39 func (plainPersonalizationString) isPersonalizationString() {}
40
41
42
43
44 type blockAlignedPersonalizationString [][]byte
45
46 func (blockAlignedPersonalizationString) isPersonalizationString() {}
47
48 type personalizationString interface {
49 isPersonalizationString()
50 }
51
52 func newDRBG[H hash.Hash](hash func() H, entropy, nonce []byte, s personalizationString) *hmacDRBG {
53
54 fips140.RecordApproved()
55
56 d := &hmacDRBG{
57 newHMAC: func(key []byte) *hmac.HMAC {
58 return hmac.New(hash, key)
59 },
60 }
61 size := hash().Size()
62
63
64 K := make([]byte, size)
65
66
67 d.V = bytes.Repeat([]byte{0x01}, size)
68
69
70
71 h := hmac.New(hash, K)
72 h.Write(d.V)
73 h.Write([]byte{0x00})
74 h.Write(entropy)
75 h.Write(nonce)
76 switch s := s.(type) {
77 case plainPersonalizationString:
78 h.Write(s)
79 case blockAlignedPersonalizationString:
80 l := len(d.V) + 1 + len(entropy) + len(nonce)
81 for _, b := range s {
82 pad000(h, l)
83 h.Write(b)
84 l = len(b)
85 }
86 }
87 K = h.Sum(K[:0])
88
89 h = hmac.New(hash, K)
90 h.Write(d.V)
91 d.V = h.Sum(d.V[:0])
92
93 h.Reset()
94 h.Write(d.V)
95 h.Write([]byte{0x01})
96 h.Write(entropy)
97 h.Write(nonce)
98 switch s := s.(type) {
99 case plainPersonalizationString:
100 h.Write(s)
101 case blockAlignedPersonalizationString:
102 l := len(d.V) + 1 + len(entropy) + len(nonce)
103 for _, b := range s {
104 pad000(h, l)
105 h.Write(b)
106 l = len(b)
107 }
108 }
109 K = h.Sum(K[:0])
110
111 h = hmac.New(hash, K)
112 h.Write(d.V)
113 d.V = h.Sum(d.V[:0])
114
115 d.hK = h
116 d.reseedCounter = 1
117 return d
118 }
119
120
121
122
123
124
125 func TestingOnlyNewDRBG(hash func() hash.Hash, entropy, nonce []byte, s []byte) *hmacDRBG {
126 return newDRBG(hash, entropy, nonce, plainPersonalizationString(s))
127 }
128
129 func pad000(h *hmac.HMAC, writtenSoFar int) {
130 blockSize := h.BlockSize()
131 if rem := writtenSoFar % blockSize; rem != 0 {
132 h.Write(make([]byte, blockSize-rem))
133 }
134 }
135
136
137 func (d *hmacDRBG) Generate(out []byte) {
138
139 fips140.RecordApproved()
140
141 if len(out) > maxRequestSize {
142 panic("ecdsa: internal error: request size exceeds maximum")
143 }
144
145 if d.reseedCounter > reseedInterval {
146 panic("ecdsa: reseed interval exceeded")
147 }
148
149 tlen := 0
150 for tlen < len(out) {
151
152
153 d.hK.Reset()
154 d.hK.Write(d.V)
155 d.V = d.hK.Sum(d.V[:0])
156 tlen += copy(out[tlen:], d.V)
157 }
158
159
160
161
162
163
164
165 d.hK.Reset()
166 d.hK.Write(d.V)
167 d.hK.Write([]byte{0x00})
168 K := d.hK.Sum(nil)
169
170 d.hK = d.newHMAC(K)
171 d.hK.Write(d.V)
172 d.V = d.hK.Sum(d.V[:0])
173
174 d.reseedCounter++
175 }
176
View as plain text