2 * Minio Cloud Storage, (C) 2016 Minio, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 // Size - The size of a SHA256 checksum in bytes.
29 // BlockSize - The blocksize of SHA256 in bytes.
44 // digest represents the partial evaluation of a checksum.
52 // Reset digest back to default
53 func (d *digest) Reset() {
66 type blockfuncType int
69 blockfuncGeneric blockfuncType = iota
70 blockfuncAvx512 blockfuncType = iota
71 blockfuncAvx2 blockfuncType = iota
72 blockfuncAvx blockfuncType = iota
73 blockfuncSsse blockfuncType = iota
74 blockfuncSha blockfuncType = iota
75 blockfuncArm blockfuncType = iota
78 var blockfunc blockfuncType
80 func block(dig *digest, p []byte) {
81 if blockfunc == blockfuncSha {
83 } else if blockfunc == blockfuncAvx2 {
85 } else if blockfunc == blockfuncAvx {
87 } else if blockfunc == blockfuncSsse {
89 } else if blockfunc == blockfuncArm {
91 } else if blockfunc == blockfuncGeneric {
97 is386bit := runtime.GOARCH == "386"
98 isARM := runtime.GOARCH == "arm"
100 case is386bit || isARM:
101 blockfunc = blockfuncGeneric
102 case sha && ssse3 && sse41:
103 blockfunc = blockfuncSha
105 blockfunc = blockfuncAvx2
107 blockfunc = blockfuncAvx
109 blockfunc = blockfuncSsse
111 blockfunc = blockfuncArm
113 blockfunc = blockfuncGeneric
117 // New returns a new hash.Hash computing the SHA256 checksum.
118 func New() hash.Hash {
119 if blockfunc != blockfuncGeneric {
124 // Fallback to the standard golang implementation
125 // if no features were found.
129 // Sum256 - single caller sha256 helper
130 func Sum256(data []byte) (result [Size]byte) {
134 result = d.checkSum()
138 // Return size of checksum
139 func (d *digest) Size() int { return Size }
141 // Return blocksize of checksum
142 func (d *digest) BlockSize() int { return BlockSize }
145 func (d *digest) Write(p []byte) (nn int, err error) {
149 n := copy(d.x[d.nx:], p)
158 n := len(p) &^ (chunk - 1)
163 d.nx = copy(d.x[:], p)
168 // Return sha256 sum in bytes
169 func (d *digest) Sum(in []byte) []byte {
170 // Make a copy of d0 so that caller can keep writing and summing.
172 hash := d0.checkSum()
173 return append(in, hash[:]...)
176 // Intermediate checksum function
177 func (d *digest) checkSum() (digest [Size]byte) {
188 // clear block buffer - go compiles this to optimal 1x xorps + 4x movups
189 // unfortunately expressing this more succinctly results in much worse code
255 binary.BigEndian.PutUint64(k[56:64], uint64(d.len)<<3)
260 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
264 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
268 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
272 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
276 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
280 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
284 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
288 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])