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 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 // SHA-3 state context and Read/Write operations
17 18 // initBlock is the cSHAKE specific initialization set of bytes. It is initialized
19 // by newCShake function and stores concatenation of N followed by S, encoded
20 // by the method specified in 3.3 of [1].
21 // It is stored here in order for Reset() to be able to put context into
22 // initial state.
23 initBlock []byte
24 }
25 26 func bytepad(data []byte, rate int) []byte {
27 out := []byte{:0:9+len(data)+rate-1}
28 out = append(out, leftEncode(uint64(rate))...)
29 out = append(out, data...)
30 if padlen := rate - len(out)%rate; padlen < rate {
31 out = append(out, []byte{:padlen}...)
32 }
33 return out
34 }
35 36 func leftEncode(x uint64) []byte {
37 // Let n be the smallest positive integer for which 2^(8n) > x.
38 n := (bits.Len64(x) + 7) / 8
39 if n == 0 {
40 n = 1
41 }
42 // Return n || x with n as a byte and x an n bytes in big-endian order.
43 b := []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(N, S []byte, rate, outputLen int, dsbyte byte) *SHAKE {
51 c := &SHAKE{d: Digest{rate: rate, outputLen: outputLen, dsbyte: dsbyte}}
52 c.initBlock = []byte{:0:9+len(N)+9+len(S)} // leftEncode returns max 9 bytes
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 c.Write(bytepad(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 // Sum appends a portion of output to b and returns the resulting slice. The
65 // output length is selected to provide full-strength generic security: 32 bytes
66 // for SHAKE128 and 64 bytes for SHAKE256. It does not change the underlying
67 // state. It panics if any output has already been read.
68 func (s *SHAKE) Sum(in []byte) []byte { return s.d.Sum(in) }
69 70 // Write absorbs more data into the hash's state.
71 // It panics if any output has already been read.
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 // Note that read is not exposed on Digest since SHA-3 does not offer
77 // variable output length. It is only used internally by Sum.
78 return s.d.read(out)
79 }
80 81 // Reset resets the hash to initial state.
82 func (s *SHAKE) Reset() {
83 s.d.Reset()
84 if len(s.initBlock) != 0 {
85 s.Write(bytepad(s.initBlock, s.d.rate))
86 }
87 }
88 89 // Clone returns a copy of the SHAKE context in its current state.
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([]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 // NewShake128 creates a new SHAKE128 XOF.
120 func NewShake128() *SHAKE {
121 return &SHAKE{d: Digest{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}}
122 }
123 124 // NewShake256 creates a new SHAKE256 XOF.
125 func NewShake256() *SHAKE {
126 return &SHAKE{d: Digest{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}}
127 }
128 129 // NewCShake128 creates a new cSHAKE128 XOF.
130 //
131 // N is used to define functions based on cSHAKE, it can be empty when plain
132 // cSHAKE is desired. S is a customization byte string used for domain
133 // separation. When N and S are both empty, this is equivalent to NewShake128.
134 func NewCShake128(N, S []byte) *SHAKE {
135 if len(N) == 0 && len(S) == 0 {
136 return NewShake128()
137 }
138 return newCShake(N, S, rateK256, 32, dsbyteCShake)
139 }
140 141 // NewCShake256 creates a new cSHAKE256 XOF.
142 //
143 // N is used to define functions based on cSHAKE, it can be empty when plain
144 // cSHAKE is desired. S is a customization byte string used for domain
145 // separation. When N and S are both empty, this is equivalent to NewShake256.
146 func NewCShake256(N, S []byte) *SHAKE {
147 if len(N) == 0 && len(S) == 0 {
148 return NewShake256()
149 }
150 return newCShake(N, S, rateK512, 64, dsbyteCShake)
151 }
152