1
2
3
4
5 package sha3
6
7 import (
8 "bytes"
9 "crypto/internal/fips140"
10 "crypto/internal/fips140deps/byteorder"
11 "errors"
12 "math/bits"
13 )
14
15 type SHAKE struct {
16 d Digest
17
18
19
20
21
22
23 initBlock []byte
24 }
25
26 func bytepadWrite(c *SHAKE, data []byte, rate int) {
27 rateEnc := leftEncode(uint64(rate))
28 c.Write(rateEnc)
29 c.Write(data)
30 if padlen := rate - (len(rateEnc)+len(data))%rate; padlen < rate {
31 const maxRate = rateK256
32 c.Write(make([]byte, padlen, maxRate))
33 }
34 }
35
36 func leftEncode(x uint64) []byte {
37
38 n := (bits.Len64(x) + 7) / 8
39 if n == 0 {
40 n = 1
41 }
42
43 b := make([]byte, 9)
44 byteorder.BEPutUint64(b[1:], x)
45 b = b[9-n-1:]
46 b[0] = byte(n)
47 return b
48 }
49
50 func newCShake(c *SHAKE, N, S []byte, rate, outputLen int, dsbyte byte) *SHAKE {
51 c.d = Digest{rate: rate, outputLen: outputLen, dsbyte: dsbyte}
52 c.initBlock = make([]byte, 0, 9+len(N)+9+len(S))
53 c.initBlock = append(c.initBlock, leftEncode(uint64(len(N))*8)...)
54 c.initBlock = append(c.initBlock, N...)
55 c.initBlock = append(c.initBlock, leftEncode(uint64(len(S))*8)...)
56 c.initBlock = append(c.initBlock, S...)
57 bytepadWrite(c, c.initBlock, c.d.rate)
58 return c
59 }
60
61 func (s *SHAKE) BlockSize() int { return s.d.BlockSize() }
62 func (s *SHAKE) Size() int { return s.d.Size() }
63
64
65
66
67
68 func (s *SHAKE) Sum(in []byte) []byte { return s.d.Sum(in) }
69
70
71
72 func (s *SHAKE) Write(p []byte) (n int, err error) { return s.d.Write(p) }
73
74 func (s *SHAKE) Read(out []byte) (n int, err error) {
75 fips140.RecordApproved()
76
77
78 return s.d.read(out)
79 }
80
81
82 func (s *SHAKE) Reset() {
83 s.d.Reset()
84 if len(s.initBlock) != 0 {
85 bytepadWrite(s, s.initBlock, s.d.rate)
86 }
87 }
88
89
90 func (s *SHAKE) Clone() *SHAKE {
91 ret := *s
92 return &ret
93 }
94
95 func (s *SHAKE) MarshalBinary() ([]byte, error) {
96 return s.AppendBinary(make([]byte, 0, marshaledSize+len(s.initBlock)))
97 }
98
99 func (s *SHAKE) AppendBinary(b []byte) ([]byte, error) {
100 b, err := s.d.AppendBinary(b)
101 if err != nil {
102 return nil, err
103 }
104 b = append(b, s.initBlock...)
105 return b, nil
106 }
107
108 func (s *SHAKE) UnmarshalBinary(b []byte) error {
109 if len(b) < marshaledSize {
110 return errors.New("sha3: invalid hash state")
111 }
112 if err := s.d.UnmarshalBinary(b[:marshaledSize]); err != nil {
113 return err
114 }
115 s.initBlock = bytes.Clone(b[marshaledSize:])
116 return nil
117 }
118
119
120 func NewShake128() *SHAKE {
121 return &SHAKE{d: Digest{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}}
122 }
123
124
125 func NewShake256() *SHAKE {
126 return &SHAKE{d: Digest{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}}
127 }
128
129
130
131
132
133
134 func NewCShake128(N, S []byte) *SHAKE {
135
136 c := &SHAKE{}
137 return newCShake128(c, N, S)
138 }
139
140 func newCShake128(c *SHAKE, N, S []byte) *SHAKE {
141 if len(N) == 0 && len(S) == 0 {
142 *c = *NewShake128()
143 return c
144 }
145 return newCShake(c, N, S, rateK256, 32, dsbyteCShake)
146 }
147
148
149
150
151
152
153 func NewCShake256(N, S []byte) *SHAKE {
154
155 c := &SHAKE{}
156 return newCShake256(c, N, S)
157 }
158
159 func newCShake256(c *SHAKE, N, S []byte) *SHAKE {
160 if len(N) == 0 && len(S) == 0 {
161 *c = *NewShake256()
162 return c
163 }
164 return newCShake(c, N, S, rateK512, 64, dsbyteCShake)
165 }
166
View as plain text