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