| 
									
										
										
										
											2016-02-11 08:40:09 +08:00
										 |  |  | // +build linux,amd64,cgo
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Minio Cloud Storage, (C) 2016 Minio, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-01-15 10:17:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-22 05:40:54 +08:00
										 |  |  | // Copyright 2009 The Go Authors. All rights reserved.
 | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style
 | 
					
						
							|  |  |  | // license that can be found in the LICENSE file of
 | 
					
						
							|  |  |  | // Golang project:
 | 
					
						
							|  |  |  | //    https://github.com/golang/go/blob/master/LICENSE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Using this part of Minio codebase under the license
 | 
					
						
							|  |  |  | // Apache License Version 2.0 with modifications
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-27 09:23:42 +08:00
										 |  |  | // Package sha256 provides SHA256SSE3, SHA256AVX, SHA256AVX2
 | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | package sha256 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-21 08:01:27 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 	"hash" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-16 04:45:02 +08:00
										 |  |  | 	"github.com/klauspost/cpuid" | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-21 02:22:00 +08:00
										 |  |  | // Size - The size of a SHA256 checksum in bytes.
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | const Size = 32 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-21 02:22:00 +08:00
										 |  |  | // BlockSize - The blocksize of SHA256 in bytes.
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | const BlockSize = 64 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	chunk = 64 | 
					
						
							|  |  |  | 	init0 = 0x6A09E667 | 
					
						
							|  |  |  | 	init1 = 0xBB67AE85 | 
					
						
							|  |  |  | 	init2 = 0x3C6EF372 | 
					
						
							|  |  |  | 	init3 = 0xA54FF53A | 
					
						
							|  |  |  | 	init4 = 0x510E527F | 
					
						
							|  |  |  | 	init5 = 0x9B05688C | 
					
						
							|  |  |  | 	init6 = 0x1F83D9AB | 
					
						
							|  |  |  | 	init7 = 0x5BE0CD19 | 
					
						
							| 
									
										
										
										
											2014-12-21 08:01:27 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | // digest represents the partial evaluation of a checksum.
 | 
					
						
							|  |  |  | type digest struct { | 
					
						
							|  |  |  | 	h   [8]uint32 | 
					
						
							|  |  |  | 	x   [chunk]byte | 
					
						
							|  |  |  | 	nx  int | 
					
						
							|  |  |  | 	len uint64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 18:36:12 +08:00
										 |  |  | // Reset digest back to default
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | func (d *digest) Reset() { | 
					
						
							|  |  |  | 	d.h[0] = init0 | 
					
						
							|  |  |  | 	d.h[1] = init1 | 
					
						
							|  |  |  | 	d.h[2] = init2 | 
					
						
							|  |  |  | 	d.h[3] = init3 | 
					
						
							|  |  |  | 	d.h[4] = init4 | 
					
						
							|  |  |  | 	d.h[5] = init5 | 
					
						
							|  |  |  | 	d.h[6] = init6 | 
					
						
							|  |  |  | 	d.h[7] = init7 | 
					
						
							|  |  |  | 	d.nx = 0 | 
					
						
							|  |  |  | 	d.len = 0 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | func block(dig *digest, p []byte) { | 
					
						
							|  |  |  | 	switch true { | 
					
						
							| 
									
										
										
										
											2016-02-16 04:45:02 +08:00
										 |  |  | 	case cpuid.CPU.AVX2(): | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 		blockAVX2(dig, p) | 
					
						
							| 
									
										
										
										
											2016-02-16 04:45:02 +08:00
										 |  |  | 	case cpuid.CPU.AVX(): | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 		blockAVX(dig, p) | 
					
						
							| 
									
										
										
										
											2016-02-16 04:45:02 +08:00
										 |  |  | 	case cpuid.CPU.SSSE3(): | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 		blockSSE(dig, p) | 
					
						
							| 
									
										
										
										
											2015-04-28 04:48:56 +08:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2015-07-30 04:09:52 +08:00
										 |  |  | 		blockGeneric(dig, p) | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // New returns a new hash.Hash computing the SHA256 checksum.
 | 
					
						
							|  |  |  | func New() hash.Hash { | 
					
						
							|  |  |  | 	d := new(digest) | 
					
						
							|  |  |  | 	d.Reset() | 
					
						
							|  |  |  | 	return d | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-11 08:40:09 +08:00
										 |  |  | // Sum256 - single caller sha256 helper
 | 
					
						
							|  |  |  | func Sum256(data []byte) [Size]byte { | 
					
						
							|  |  |  | 	var d digest | 
					
						
							|  |  |  | 	d.Reset() | 
					
						
							|  |  |  | 	d.Write(data) | 
					
						
							|  |  |  | 	return d.checkSum() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 18:36:12 +08:00
										 |  |  | // Return size of checksum
 | 
					
						
							|  |  |  | func (d *digest) Size() int { return Size } | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 18:36:12 +08:00
										 |  |  | // Return blocksize of checksum
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | func (d *digest) BlockSize() int { return BlockSize } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 18:36:12 +08:00
										 |  |  | // Write to digest
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | func (d *digest) Write(p []byte) (nn int, err error) { | 
					
						
							|  |  |  | 	nn = len(p) | 
					
						
							|  |  |  | 	d.len += uint64(nn) | 
					
						
							|  |  |  | 	if d.nx > 0 { | 
					
						
							|  |  |  | 		n := copy(d.x[d.nx:], p) | 
					
						
							|  |  |  | 		d.nx += n | 
					
						
							|  |  |  | 		if d.nx == chunk { | 
					
						
							|  |  |  | 			block(d, d.x[:]) | 
					
						
							|  |  |  | 			d.nx = 0 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		p = p[n:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(p) >= chunk { | 
					
						
							|  |  |  | 		n := len(p) &^ (chunk - 1) | 
					
						
							|  |  |  | 		block(d, p[:n]) | 
					
						
							|  |  |  | 		p = p[n:] | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 	if len(p) > 0 { | 
					
						
							|  |  |  | 		d.nx = copy(d.x[:], p) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 18:36:12 +08:00
										 |  |  | // Return sha256 sum in bytes
 | 
					
						
							| 
									
										
										
										
											2015-03-10 07:15:06 +08:00
										 |  |  | func (d *digest) Sum(in []byte) []byte { | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 	// Make a copy of d0 so that caller can keep writing and summing.
 | 
					
						
							| 
									
										
										
										
											2015-03-10 07:15:06 +08:00
										 |  |  | 	d0 := *d | 
					
						
							|  |  |  | 	hash := d0.checkSum() | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 	return append(in, hash[:]...) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 18:36:12 +08:00
										 |  |  | // Intermediate checksum function
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | func (d *digest) checkSum() [Size]byte { | 
					
						
							|  |  |  | 	len := d.len | 
					
						
							|  |  |  | 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
 | 
					
						
							|  |  |  | 	var tmp [64]byte | 
					
						
							|  |  |  | 	tmp[0] = 0x80 | 
					
						
							|  |  |  | 	if len%64 < 56 { | 
					
						
							|  |  |  | 		d.Write(tmp[0 : 56-len%64]) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		d.Write(tmp[0 : 64+56-len%64]) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Length in bits.
 | 
					
						
							|  |  |  | 	len <<= 3 | 
					
						
							|  |  |  | 	for i := uint(0); i < 8; i++ { | 
					
						
							|  |  |  | 		tmp[i] = byte(len >> (56 - 8*i)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	d.Write(tmp[0:8]) | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 	if d.nx != 0 { | 
					
						
							|  |  |  | 		panic("d.nx != 0") | 
					
						
							| 
									
										
										
										
											2014-12-14 12:27:34 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-21 20:11:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	h := d.h[:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var digest [Size]byte | 
					
						
							|  |  |  | 	for i, s := range h { | 
					
						
							|  |  |  | 		digest[i*4] = byte(s >> 24) | 
					
						
							|  |  |  | 		digest[i*4+1] = byte(s >> 16) | 
					
						
							|  |  |  | 		digest[i*4+2] = byte(s >> 8) | 
					
						
							|  |  |  | 		digest[i*4+3] = byte(s) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return digest | 
					
						
							|  |  |  | } |