1
2
3
4
5
6
7
8
9
10
11 package sha3
12
13 import (
14 "crypto/internal/fips"
15 "crypto/internal/fips/subtle"
16 "errors"
17 )
18
19
20 type spongeDirection int
21
22 const (
23
24 spongeAbsorbing spongeDirection = iota
25
26 spongeSqueezing
27 )
28
29 type Digest struct {
30 a [1600 / 8]byte
31
32
33
34
35 n, rate int
36
37
38
39
40
41
42
43
44
45
46
47
48
49 dsbyte byte
50
51 outputLen int
52 state spongeDirection
53 }
54
55
56 func (d *Digest) BlockSize() int { return d.rate }
57
58
59 func (d *Digest) Size() int { return d.outputLen }
60
61
62 func (d *Digest) Reset() {
63
64 for i := range d.a {
65 d.a[i] = 0
66 }
67 d.state = spongeAbsorbing
68 d.n = 0
69 }
70
71 func (d *Digest) Clone() *Digest {
72 ret := *d
73 return &ret
74 }
75
76
77 func (d *Digest) permute() {
78 keccakF1600(&d.a)
79 d.n = 0
80 }
81
82
83
84 func (d *Digest) padAndPermute() {
85
86
87
88
89 d.a[d.n] ^= d.dsbyte
90
91
92
93 d.a[d.rate-1] ^= 0x80
94
95 d.permute()
96 d.state = spongeSqueezing
97 }
98
99
100 func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) }
101 func (d *Digest) writeGeneric(p []byte) (n int, err error) {
102 if d.state != spongeAbsorbing {
103 panic("sha3: Write after Read")
104 }
105
106 n = len(p)
107
108 for len(p) > 0 {
109 x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
110 d.n += x
111 p = p[x:]
112
113
114 if d.n == d.rate {
115 d.permute()
116 }
117 }
118
119 return
120 }
121
122
123 func (d *Digest) readGeneric(out []byte) (n int, err error) {
124
125 if d.state == spongeAbsorbing {
126 d.padAndPermute()
127 }
128
129 n = len(out)
130
131
132 for len(out) > 0 {
133
134 if d.n == d.rate {
135 d.permute()
136 }
137
138 x := copy(out, d.a[d.n:d.rate])
139 d.n += x
140 out = out[x:]
141 }
142
143 return
144 }
145
146
147
148 func (d *Digest) Sum(b []byte) []byte {
149 fips.RecordApproved()
150 return d.sum(b)
151 }
152
153 func (d *Digest) sumGeneric(b []byte) []byte {
154 if d.state != spongeAbsorbing {
155 panic("sha3: Sum after Read")
156 }
157
158
159
160 dup := d.Clone()
161 hash := make([]byte, dup.outputLen, 64)
162 dup.read(hash)
163 return append(b, hash...)
164 }
165
166 const (
167 magicSHA3 = "sha\x08"
168 magicShake = "sha\x09"
169 magicCShake = "sha\x0a"
170 magicKeccak = "sha\x0b"
171
172 marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
173 )
174
175 func (d *Digest) MarshalBinary() ([]byte, error) {
176 return d.AppendBinary(make([]byte, 0, marshaledSize))
177 }
178
179 func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
180 switch d.dsbyte {
181 case dsbyteSHA3:
182 b = append(b, magicSHA3...)
183 case dsbyteShake:
184 b = append(b, magicShake...)
185 case dsbyteCShake:
186 b = append(b, magicCShake...)
187 case dsbyteKeccak:
188 b = append(b, magicKeccak...)
189 default:
190 panic("unknown dsbyte")
191 }
192
193 b = append(b, byte(d.rate))
194 b = append(b, d.a[:]...)
195 b = append(b, byte(d.n), byte(d.state))
196 return b, nil
197 }
198
199 func (d *Digest) UnmarshalBinary(b []byte) error {
200 if len(b) != marshaledSize {
201 return errors.New("sha3: invalid hash state")
202 }
203
204 magic := string(b[:len(magicSHA3)])
205 b = b[len(magicSHA3):]
206 switch {
207 case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
208 case magic == magicShake && d.dsbyte == dsbyteShake:
209 case magic == magicCShake && d.dsbyte == dsbyteCShake:
210 case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
211 default:
212 return errors.New("sha3: invalid hash state identifier")
213 }
214
215 rate := int(b[0])
216 b = b[1:]
217 if rate != d.rate {
218 return errors.New("sha3: invalid hash state function")
219 }
220
221 copy(d.a[:], b)
222 b = b[len(d.a):]
223
224 n, state := int(b[0]), spongeDirection(b[1])
225 if n > d.rate {
226 return errors.New("sha3: invalid hash state")
227 }
228 d.n = n
229 if state != spongeAbsorbing && state != spongeSqueezing {
230 return errors.New("sha3: invalid hash state")
231 }
232 d.state = state
233
234 return nil
235 }
236
View as plain text