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 func pad000(h *hmac.HMAC, writtenSoFar int) {
120 blockSize := h.BlockSize()
121 if rem := writtenSoFar % blockSize; rem != 0 {
122 h.Write(make([]byte, blockSize-rem))
123 }
124 }
125
126
127 func (d *hmacDRBG) Generate(out []byte) {
128
129 fips140.RecordApproved()
130
131 if len(out) > maxRequestSize {
132 panic("ecdsa: internal error: request size exceeds maximum")
133 }
134
135 if d.reseedCounter > reseedInterval {
136 panic("ecdsa: reseed interval exceeded")
137 }
138
139 tlen := 0
140 for tlen < len(out) {
141
142
143 d.hK.Reset()
144 d.hK.Write(d.V)
145 d.V = d.hK.Sum(d.V[:0])
146 tlen += copy(out[tlen:], d.V)
147 }
148
149
150
151
152
153
154
155 d.hK.Reset()
156 d.hK.Write(d.V)
157 d.hK.Write([]byte{0x00})
158 K := d.hK.Sum(nil)
159
160 d.hK = d.newHMAC(K)
161 d.hK.Write(d.V)
162 d.V = d.hK.Sum(d.V[:0])
163
164 d.reseedCounter++
165 }
166
View as plain text