main
1// Copyright 2014 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
5package sha3
6
7// spongeDirection indicates the direction bytes are flowing through the sponge.
8type spongeDirection int
9
10const (
11 // spongeAbsorbing indicates that the sponge is absorbing input.
12 spongeAbsorbing spongeDirection = iota
13 // spongeSqueezing indicates that the sponge is being squeezed.
14 spongeSqueezing
15)
16
17const (
18 // maxRate is the maximum size of the internal buffer. SHAKE-256
19 // currently needs the largest buffer.
20 maxRate = 168
21)
22
23func (d *State) buf() []byte {
24 return d.storage.asBytes()[d.bufo:d.bufe]
25}
26
27type State struct {
28 // Generic sponge components.
29 a [25]uint64 // main state of the hash
30 rate int // the number of bytes of state to use
31
32 bufo int // offset of buffer in storage
33 bufe int // end of buffer in storage
34
35 // dsbyte contains the "domain separation" bits and the first bit of
36 // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
37 // SHA-3 and SHAKE functions by appending bitstrings to the message.
38 // Using a little-endian bit-ordering convention, these are "01" for SHA-3
39 // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
40 // padding rule from section 5.1 is applied to pad the message to a multiple
41 // of the rate, which involves adding a "1" bit, zero or more "0" bits, and
42 // a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
43 // giving 00000110b (0x06) and 00011111b (0x1f).
44 // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
45 // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
46 // Extendable-Output Functions (May 2014)"
47 dsbyte byte
48
49 storage storageBuf
50
51 // Specific to SHA-3 and SHAKE.
52 outputLen int // the default output size in bytes
53 state spongeDirection // whether the sponge is absorbing or squeezing
54 turbo bool // Whether we're using 12 rounds instead of 24
55}
56
57// BlockSize returns the rate of sponge underlying this hash function.
58func (d *State) BlockSize() int { return d.rate }
59
60// Size returns the output size of the hash function in bytes.
61func (d *State) Size() int { return d.outputLen }
62
63// Reset clears the internal state by zeroing the sponge state and
64// the byte buffer, and setting Sponge.state to absorbing.
65func (d *State) Reset() {
66 // Zero the permutation's state.
67 for i := range d.a {
68 d.a[i] = 0
69 }
70 d.state = spongeAbsorbing
71 d.bufo = 0
72 d.bufe = 0
73}
74
75func (d *State) clone() *State {
76 ret := *d
77 return &ret
78}
79
80// permute applies the KeccakF-1600 permutation. It handles
81// any input-output buffering.
82func (d *State) permute() {
83 switch d.state {
84 case spongeAbsorbing:
85 // If we're absorbing, we need to xor the input into the state
86 // before applying the permutation.
87 xorIn(d, d.buf())
88 d.bufe = 0
89 d.bufo = 0
90 KeccakF1600(&d.a, d.turbo)
91 case spongeSqueezing:
92 // If we're squeezing, we need to apply the permutation before
93 // copying more output.
94 KeccakF1600(&d.a, d.turbo)
95 d.bufe = d.rate
96 d.bufo = 0
97 copyOut(d, d.buf())
98 }
99}
100
101// pads appends the domain separation bits in dsbyte, applies
102// the multi-bitrate 10..1 padding rule, and permutes the state.
103func (d *State) padAndPermute(dsbyte byte) {
104 // Pad with this instance's domain-separator bits. We know that there's
105 // at least one byte of space in d.buf() because, if it were full,
106 // permute would have been called to empty it. dsbyte also contains the
107 // first one bit for the padding. See the comment in the state struct.
108 zerosStart := d.bufe + 1
109 d.bufe = d.rate
110 buf := d.buf()
111 buf[zerosStart-1] = dsbyte
112 for i := zerosStart; i < d.rate; i++ {
113 buf[i] = 0
114 }
115 // This adds the final one bit for the padding. Because of the way that
116 // bits are numbered from the LSB upwards, the final bit is the MSB of
117 // the last byte.
118 buf[d.rate-1] ^= 0x80
119 // Apply the permutation
120 d.permute()
121 d.state = spongeSqueezing
122 d.bufe = d.rate
123 copyOut(d, buf)
124}
125
126// Write absorbs more data into the hash's state. It produces an error
127// if more data is written to the ShakeHash after writing
128func (d *State) Write(p []byte) (written int, err error) {
129 if d.state != spongeAbsorbing {
130 panic("sha3: write to sponge after read")
131 }
132 written = len(p)
133
134 for len(p) > 0 {
135 bufl := d.bufe - d.bufo
136 if bufl == 0 && len(p) >= d.rate {
137 // The fast path; absorb a full "rate" bytes of input and apply the permutation.
138 xorIn(d, p[:d.rate])
139 p = p[d.rate:]
140 KeccakF1600(&d.a, d.turbo)
141 } else {
142 // The slow path; buffer the input until we can fill the sponge, and then xor it in.
143 todo := d.rate - bufl
144 if todo > len(p) {
145 todo = len(p)
146 }
147 d.bufe += todo
148 buf := d.buf()
149 copy(buf[bufl:], p[:todo])
150 p = p[todo:]
151
152 // If the sponge is full, apply the permutation.
153 if d.bufe == d.rate {
154 d.permute()
155 }
156 }
157 }
158
159 return written, nil
160}
161
162// Read squeezes an arbitrary number of bytes from the sponge.
163func (d *State) Read(out []byte) (n int, err error) {
164 // If we're still absorbing, pad and apply the permutation.
165 if d.state == spongeAbsorbing {
166 d.padAndPermute(d.dsbyte)
167 }
168
169 n = len(out)
170
171 // Now, do the squeezing.
172 for len(out) > 0 {
173 buf := d.buf()
174 n := copy(out, buf)
175 d.bufo += n
176 out = out[n:]
177
178 // Apply the permutation if we've squeezed the sponge dry.
179 if d.bufo == d.bufe {
180 d.permute()
181 }
182 }
183
184 return
185}
186
187// Sum applies padding to the hash state and then squeezes out the desired
188// number of output bytes.
189func (d *State) Sum(in []byte) []byte {
190 // Make a copy of the original hash so that caller can keep writing
191 // and summing.
192 dup := d.clone()
193 hash := make([]byte, dup.outputLen)
194 _, _ = dup.Read(hash)
195 return append(in, hash...)
196}
197
198func (d *State) IsAbsorbing() bool {
199 return d.state == spongeAbsorbing
200}