aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/sha256-simd/sha256.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/minio/sha256-simd/sha256.go')
-rw-r--r--vendor/github.com/minio/sha256-simd/sha256.go468
1 files changed, 468 insertions, 0 deletions
diff --git a/vendor/github.com/minio/sha256-simd/sha256.go b/vendor/github.com/minio/sha256-simd/sha256.go
new file mode 100644
index 0000000..f146bbd
--- /dev/null
+++ b/vendor/github.com/minio/sha256-simd/sha256.go
@@ -0,0 +1,468 @@
1/*
2 * Minio Cloud Storage, (C) 2016 Minio, Inc.
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package sha256
18
19import (
20 "crypto/sha256"
21 "encoding/binary"
22 "errors"
23 "hash"
24)
25
26// Size - The size of a SHA256 checksum in bytes.
27const Size = 32
28
29// BlockSize - The blocksize of SHA256 in bytes.
30const BlockSize = 64
31
32const (
33 chunk = BlockSize
34 init0 = 0x6A09E667
35 init1 = 0xBB67AE85
36 init2 = 0x3C6EF372
37 init3 = 0xA54FF53A
38 init4 = 0x510E527F
39 init5 = 0x9B05688C
40 init6 = 0x1F83D9AB
41 init7 = 0x5BE0CD19
42)
43
44// digest represents the partial evaluation of a checksum.
45type digest struct {
46 h [8]uint32
47 x [chunk]byte
48 nx int
49 len uint64
50}
51
52// Reset digest back to default
53func (d *digest) Reset() {
54 d.h[0] = init0
55 d.h[1] = init1
56 d.h[2] = init2
57 d.h[3] = init3
58 d.h[4] = init4
59 d.h[5] = init5
60 d.h[6] = init6
61 d.h[7] = init7
62 d.nx = 0
63 d.len = 0
64}
65
66type blockfuncType int
67
68const (
69 blockfuncStdlib blockfuncType = iota
70 blockfuncIntelSha
71 blockfuncArmSha2
72 blockfuncForceGeneric = -1
73)
74
75var blockfunc blockfuncType
76
77func init() {
78 switch {
79 case hasIntelSha:
80 blockfunc = blockfuncIntelSha
81 case hasArmSha2():
82 blockfunc = blockfuncArmSha2
83 }
84}
85
86// New returns a new hash.Hash computing the SHA256 checksum.
87func New() hash.Hash {
88 if blockfunc == blockfuncStdlib {
89 // Fallback to the standard golang implementation
90 // if no features were found.
91 return sha256.New()
92 }
93
94 d := new(digest)
95 d.Reset()
96 return d
97}
98
99// Sum256 - single caller sha256 helper
100func Sum256(data []byte) (result [Size]byte) {
101 var d digest
102 d.Reset()
103 d.Write(data)
104 result = d.checkSum()
105 return
106}
107
108// Return size of checksum
109func (d *digest) Size() int { return Size }
110
111// Return blocksize of checksum
112func (d *digest) BlockSize() int { return BlockSize }
113
114// Write to digest
115func (d *digest) Write(p []byte) (nn int, err error) {
116 nn = len(p)
117 d.len += uint64(nn)
118 if d.nx > 0 {
119 n := copy(d.x[d.nx:], p)
120 d.nx += n
121 if d.nx == chunk {
122 block(d, d.x[:])
123 d.nx = 0
124 }
125 p = p[n:]
126 }
127 if len(p) >= chunk {
128 n := len(p) &^ (chunk - 1)
129 block(d, p[:n])
130 p = p[n:]
131 }
132 if len(p) > 0 {
133 d.nx = copy(d.x[:], p)
134 }
135 return
136}
137
138// Return sha256 sum in bytes
139func (d *digest) Sum(in []byte) []byte {
140 // Make a copy of d0 so that caller can keep writing and summing.
141 d0 := *d
142 hash := d0.checkSum()
143 return append(in, hash[:]...)
144}
145
146// Intermediate checksum function
147func (d *digest) checkSum() (digest [Size]byte) {
148 n := d.nx
149
150 var k [64]byte
151 copy(k[:], d.x[:n])
152
153 k[n] = 0x80
154
155 if n >= 56 {
156 block(d, k[:])
157
158 // clear block buffer - go compiles this to optimal 1x xorps + 4x movups
159 // unfortunately expressing this more succinctly results in much worse code
160 k[0] = 0
161 k[1] = 0
162 k[2] = 0
163 k[3] = 0
164 k[4] = 0
165 k[5] = 0
166 k[6] = 0
167 k[7] = 0
168 k[8] = 0
169 k[9] = 0
170 k[10] = 0
171 k[11] = 0
172 k[12] = 0
173 k[13] = 0
174 k[14] = 0
175 k[15] = 0
176 k[16] = 0
177 k[17] = 0
178 k[18] = 0
179 k[19] = 0
180 k[20] = 0
181 k[21] = 0
182 k[22] = 0
183 k[23] = 0
184 k[24] = 0
185 k[25] = 0
186 k[26] = 0
187 k[27] = 0
188 k[28] = 0
189 k[29] = 0
190 k[30] = 0
191 k[31] = 0
192 k[32] = 0
193 k[33] = 0
194 k[34] = 0
195 k[35] = 0
196 k[36] = 0
197 k[37] = 0
198 k[38] = 0
199 k[39] = 0
200 k[40] = 0
201 k[41] = 0
202 k[42] = 0
203 k[43] = 0
204 k[44] = 0
205 k[45] = 0
206 k[46] = 0
207 k[47] = 0
208 k[48] = 0
209 k[49] = 0
210 k[50] = 0
211 k[51] = 0
212 k[52] = 0
213 k[53] = 0
214 k[54] = 0
215 k[55] = 0
216 k[56] = 0
217 k[57] = 0
218 k[58] = 0
219 k[59] = 0
220 k[60] = 0
221 k[61] = 0
222 k[62] = 0
223 k[63] = 0
224 }
225 binary.BigEndian.PutUint64(k[56:64], uint64(d.len)<<3)
226 block(d, k[:])
227
228 {
229 const i = 0
230 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
231 }
232 {
233 const i = 1
234 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
235 }
236 {
237 const i = 2
238 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
239 }
240 {
241 const i = 3
242 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
243 }
244 {
245 const i = 4
246 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
247 }
248 {
249 const i = 5
250 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
251 }
252 {
253 const i = 6
254 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
255 }
256 {
257 const i = 7
258 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
259 }
260
261 return
262}
263
264func block(dig *digest, p []byte) {
265 if blockfunc == blockfuncIntelSha {
266 blockIntelShaGo(dig, p)
267 } else if blockfunc == blockfuncArmSha2 {
268 blockArmSha2Go(dig, p)
269 } else {
270 blockGeneric(dig, p)
271 }
272}
273
274func blockGeneric(dig *digest, p []byte) {
275 var w [64]uint32
276 h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
277 for len(p) >= chunk {
278 // Can interlace the computation of w with the
279 // rounds below if needed for speed.
280 for i := 0; i < 16; i++ {
281 j := i * 4
282 w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
283 }
284 for i := 16; i < 64; i++ {
285 v1 := w[i-2]
286 t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10)
287 v2 := w[i-15]
288 t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3)
289 w[i] = t1 + w[i-7] + t2 + w[i-16]
290 }
291
292 a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7
293
294 for i := 0; i < 64; i++ {
295 t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i]
296
297 t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c))
298
299 h = g
300 g = f
301 f = e
302 e = d + t1
303 d = c
304 c = b
305 b = a
306 a = t1 + t2
307 }
308
309 h0 += a
310 h1 += b
311 h2 += c
312 h3 += d
313 h4 += e
314 h5 += f
315 h6 += g
316 h7 += h
317
318 p = p[chunk:]
319 }
320
321 dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
322}
323
324var _K = []uint32{
325 0x428a2f98,
326 0x71374491,
327 0xb5c0fbcf,
328 0xe9b5dba5,
329 0x3956c25b,
330 0x59f111f1,
331 0x923f82a4,
332 0xab1c5ed5,
333 0xd807aa98,
334 0x12835b01,
335 0x243185be,
336 0x550c7dc3,
337 0x72be5d74,
338 0x80deb1fe,
339 0x9bdc06a7,
340 0xc19bf174,
341 0xe49b69c1,
342 0xefbe4786,
343 0x0fc19dc6,
344 0x240ca1cc,
345 0x2de92c6f,
346 0x4a7484aa,
347 0x5cb0a9dc,
348 0x76f988da,
349 0x983e5152,
350 0xa831c66d,
351 0xb00327c8,
352 0xbf597fc7,
353 0xc6e00bf3,
354 0xd5a79147,
355 0x06ca6351,
356 0x14292967,
357 0x27b70a85,
358 0x2e1b2138,
359 0x4d2c6dfc,
360 0x53380d13,
361 0x650a7354,
362 0x766a0abb,
363 0x81c2c92e,
364 0x92722c85,
365 0xa2bfe8a1,
366 0xa81a664b,
367 0xc24b8b70,
368 0xc76c51a3,
369 0xd192e819,
370 0xd6990624,
371 0xf40e3585,
372 0x106aa070,
373 0x19a4c116,
374 0x1e376c08,
375 0x2748774c,
376 0x34b0bcb5,
377 0x391c0cb3,
378 0x4ed8aa4a,
379 0x5b9cca4f,
380 0x682e6ff3,
381 0x748f82ee,
382 0x78a5636f,
383 0x84c87814,
384 0x8cc70208,
385 0x90befffa,
386 0xa4506ceb,
387 0xbef9a3f7,
388 0xc67178f2,
389}
390
391const (
392 magic256 = "sha\x03"
393 marshaledSize = len(magic256) + 8*4 + chunk + 8
394)
395
396func (d *digest) MarshalBinary() ([]byte, error) {
397 b := make([]byte, 0, marshaledSize)
398 b = append(b, magic256...)
399 b = appendUint32(b, d.h[0])
400 b = appendUint32(b, d.h[1])
401 b = appendUint32(b, d.h[2])
402 b = appendUint32(b, d.h[3])
403 b = appendUint32(b, d.h[4])
404 b = appendUint32(b, d.h[5])
405 b = appendUint32(b, d.h[6])
406 b = appendUint32(b, d.h[7])
407 b = append(b, d.x[:d.nx]...)
408 b = b[:len(b)+len(d.x)-d.nx] // already zero
409 b = appendUint64(b, d.len)
410 return b, nil
411}
412
413func (d *digest) UnmarshalBinary(b []byte) error {
414 if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 {
415 return errors.New("crypto/sha256: invalid hash state identifier")
416 }
417 if len(b) != marshaledSize {
418 return errors.New("crypto/sha256: invalid hash state size")
419 }
420 b = b[len(magic256):]
421 b, d.h[0] = consumeUint32(b)
422 b, d.h[1] = consumeUint32(b)
423 b, d.h[2] = consumeUint32(b)
424 b, d.h[3] = consumeUint32(b)
425 b, d.h[4] = consumeUint32(b)
426 b, d.h[5] = consumeUint32(b)
427 b, d.h[6] = consumeUint32(b)
428 b, d.h[7] = consumeUint32(b)
429 b = b[copy(d.x[:], b):]
430 b, d.len = consumeUint64(b)
431 d.nx = int(d.len % chunk)
432 return nil
433}
434
435func appendUint32(b []byte, v uint32) []byte {
436 return append(b,
437 byte(v>>24),
438 byte(v>>16),
439 byte(v>>8),
440 byte(v),
441 )
442}
443
444func appendUint64(b []byte, v uint64) []byte {
445 return append(b,
446 byte(v>>56),
447 byte(v>>48),
448 byte(v>>40),
449 byte(v>>32),
450 byte(v>>24),
451 byte(v>>16),
452 byte(v>>8),
453 byte(v),
454 )
455}
456
457func consumeUint64(b []byte) ([]byte, uint64) {
458 _ = b[7]
459 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
460 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
461 return b[8:], x
462}
463
464func consumeUint32(b []byte) ([]byte, uint32) {
465 _ = b[3]
466 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
467 return b[4:], x
468}