OSDN Git Service

add package
[bytom/vapor.git] / vendor / github.com / minio / sha256-simd / sha256.go
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
17 package sha256
18
19 import (
20         "crypto/sha256"
21         "encoding/binary"
22         "hash"
23         "runtime"
24 )
25
26 // Size - The size of a SHA256 checksum in bytes.
27 const Size = 32
28
29 // BlockSize - The blocksize of SHA256 in bytes.
30 const BlockSize = 64
31
32 const (
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.
45 type digest struct {
46         h   [8]uint32
47         x   [chunk]byte
48         nx  int
49         len uint64
50 }
51
52 // Reset digest back to default
53 func (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
66 type blockfuncType int
67
68 const (
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
76 )
77
78 var blockfunc blockfuncType
79
80 func block(dig *digest, p []byte) {
81         if blockfunc == blockfuncSha {
82                 blockShaGo(dig, p)
83         } else if blockfunc == blockfuncAvx2 {
84                 blockAvx2Go(dig, p)
85         } else if blockfunc == blockfuncAvx {
86                 blockAvxGo(dig, p)
87         } else if blockfunc == blockfuncSsse {
88                 blockSsseGo(dig, p)
89         } else if blockfunc == blockfuncArm {
90                 blockArmGo(dig, p)
91         } else if blockfunc == blockfuncGeneric {
92                 blockGeneric(dig, p)
93         }
94 }
95
96 func init() {
97         is386bit := runtime.GOARCH == "386"
98         isARM := runtime.GOARCH == "arm"
99         switch {
100         case is386bit || isARM:
101                 blockfunc = blockfuncGeneric
102         case sha && ssse3 && sse41:
103                 blockfunc = blockfuncSha
104         case avx2:
105                 blockfunc = blockfuncAvx2
106         case avx:
107                 blockfunc = blockfuncAvx
108         case ssse3:
109                 blockfunc = blockfuncSsse
110         case armSha:
111                 blockfunc = blockfuncArm
112         default:
113                 blockfunc = blockfuncGeneric
114         }
115 }
116
117 // New returns a new hash.Hash computing the SHA256 checksum.
118 func New() hash.Hash {
119         if blockfunc != blockfuncGeneric {
120                 d := new(digest)
121                 d.Reset()
122                 return d
123         }
124         // Fallback to the standard golang implementation
125         // if no features were found.
126         return sha256.New()
127 }
128
129 // Sum256 - single caller sha256 helper
130 func Sum256(data []byte) (result [Size]byte) {
131         var d digest
132         d.Reset()
133         d.Write(data)
134         result = d.checkSum()
135         return
136 }
137
138 // Return size of checksum
139 func (d *digest) Size() int { return Size }
140
141 // Return blocksize of checksum
142 func (d *digest) BlockSize() int { return BlockSize }
143
144 // Write to digest
145 func (d *digest) Write(p []byte) (nn int, err error) {
146         nn = len(p)
147         d.len += uint64(nn)
148         if d.nx > 0 {
149                 n := copy(d.x[d.nx:], p)
150                 d.nx += n
151                 if d.nx == chunk {
152                         block(d, d.x[:])
153                         d.nx = 0
154                 }
155                 p = p[n:]
156         }
157         if len(p) >= chunk {
158                 n := len(p) &^ (chunk - 1)
159                 block(d, p[:n])
160                 p = p[n:]
161         }
162         if len(p) > 0 {
163                 d.nx = copy(d.x[:], p)
164         }
165         return
166 }
167
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.
171         d0 := *d
172         hash := d0.checkSum()
173         return append(in, hash[:]...)
174 }
175
176 // Intermediate checksum function
177 func (d *digest) checkSum() (digest [Size]byte) {
178         n := d.nx
179
180         var k [64]byte
181         copy(k[:], d.x[:n])
182
183         k[n] = 0x80
184
185         if n >= 56 {
186                 block(d, k[:])
187
188                 // clear block buffer - go compiles this to optimal 1x xorps + 4x movups
189                 // unfortunately expressing this more succinctly results in much worse code
190                 k[0] = 0
191                 k[1] = 0
192                 k[2] = 0
193                 k[3] = 0
194                 k[4] = 0
195                 k[5] = 0
196                 k[6] = 0
197                 k[7] = 0
198                 k[8] = 0
199                 k[9] = 0
200                 k[10] = 0
201                 k[11] = 0
202                 k[12] = 0
203                 k[13] = 0
204                 k[14] = 0
205                 k[15] = 0
206                 k[16] = 0
207                 k[17] = 0
208                 k[18] = 0
209                 k[19] = 0
210                 k[20] = 0
211                 k[21] = 0
212                 k[22] = 0
213                 k[23] = 0
214                 k[24] = 0
215                 k[25] = 0
216                 k[26] = 0
217                 k[27] = 0
218                 k[28] = 0
219                 k[29] = 0
220                 k[30] = 0
221                 k[31] = 0
222                 k[32] = 0
223                 k[33] = 0
224                 k[34] = 0
225                 k[35] = 0
226                 k[36] = 0
227                 k[37] = 0
228                 k[38] = 0
229                 k[39] = 0
230                 k[40] = 0
231                 k[41] = 0
232                 k[42] = 0
233                 k[43] = 0
234                 k[44] = 0
235                 k[45] = 0
236                 k[46] = 0
237                 k[47] = 0
238                 k[48] = 0
239                 k[49] = 0
240                 k[50] = 0
241                 k[51] = 0
242                 k[52] = 0
243                 k[53] = 0
244                 k[54] = 0
245                 k[55] = 0
246                 k[56] = 0
247                 k[57] = 0
248                 k[58] = 0
249                 k[59] = 0
250                 k[60] = 0
251                 k[61] = 0
252                 k[62] = 0
253                 k[63] = 0
254         }
255         binary.BigEndian.PutUint64(k[56:64], uint64(d.len)<<3)
256         block(d, k[:])
257
258         {
259                 const i = 0
260                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
261         }
262         {
263                 const i = 1
264                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
265         }
266         {
267                 const i = 2
268                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
269         }
270         {
271                 const i = 3
272                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
273         }
274         {
275                 const i = 4
276                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
277         }
278         {
279                 const i = 5
280                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
281         }
282         {
283                 const i = 6
284                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
285         }
286         {
287                 const i = 7
288                 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i])
289         }
290
291         return
292 }