]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/sha512/sha512.go
[dev.boringcrypto] misc/boring: add go1.9.2b4 release
[gostls13.git] / src / crypto / sha512 / sha512.go
1 // Copyright 2009 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 sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256
6 // hash algorithms as defined in FIPS 180-4.
7 package sha512
8
9 import (
10         "crypto"
11         "crypto/internal/boring"
12         "hash"
13 )
14
15 func init() {
16         crypto.RegisterHash(crypto.SHA384, New384)
17         crypto.RegisterHash(crypto.SHA512, New)
18         crypto.RegisterHash(crypto.SHA512_224, New512_224)
19         crypto.RegisterHash(crypto.SHA512_256, New512_256)
20 }
21
22 const (
23         // Size is the size, in bytes, of a SHA-512 checksum.
24         Size = 64
25
26         // Size224 is the size, in bytes, of a SHA-512/224 checksum.
27         Size224 = 28
28
29         // Size256 is the size, in bytes, of a SHA-512/256 checksum.
30         Size256 = 32
31
32         // Size384 is the size, in bytes, of a SHA-384 checksum.
33         Size384 = 48
34
35         // BlockSize is the block size, in bytes, of the SHA-512/224,
36         // SHA-512/256, SHA-384 and SHA-512 hash functions.
37         BlockSize = 128
38 )
39
40 const (
41         chunk     = 128
42         init0     = 0x6a09e667f3bcc908
43         init1     = 0xbb67ae8584caa73b
44         init2     = 0x3c6ef372fe94f82b
45         init3     = 0xa54ff53a5f1d36f1
46         init4     = 0x510e527fade682d1
47         init5     = 0x9b05688c2b3e6c1f
48         init6     = 0x1f83d9abfb41bd6b
49         init7     = 0x5be0cd19137e2179
50         init0_224 = 0x8c3d37c819544da2
51         init1_224 = 0x73e1996689dcd4d6
52         init2_224 = 0x1dfab7ae32ff9c82
53         init3_224 = 0x679dd514582f9fcf
54         init4_224 = 0x0f6d2b697bd44da8
55         init5_224 = 0x77e36f7304c48942
56         init6_224 = 0x3f9d85a86a1d36c8
57         init7_224 = 0x1112e6ad91d692a1
58         init0_256 = 0x22312194fc2bf72c
59         init1_256 = 0x9f555fa3c84c64c2
60         init2_256 = 0x2393b86b6f53b151
61         init3_256 = 0x963877195940eabd
62         init4_256 = 0x96283ee2a88effe3
63         init5_256 = 0xbe5e1e2553863992
64         init6_256 = 0x2b0199fc2c85b8aa
65         init7_256 = 0x0eb72ddc81c52ca2
66         init0_384 = 0xcbbb9d5dc1059ed8
67         init1_384 = 0x629a292a367cd507
68         init2_384 = 0x9159015a3070dd17
69         init3_384 = 0x152fecd8f70e5939
70         init4_384 = 0x67332667ffc00b31
71         init5_384 = 0x8eb44a8768581511
72         init6_384 = 0xdb0c2e0d64f98fa7
73         init7_384 = 0x47b5481dbefa4fa4
74 )
75
76 // digest represents the partial evaluation of a checksum.
77 type digest struct {
78         h        [8]uint64
79         x        [chunk]byte
80         nx       int
81         len      uint64
82         function crypto.Hash
83 }
84
85 func (d *digest) Reset() {
86         switch d.function {
87         case crypto.SHA384:
88                 d.h[0] = init0_384
89                 d.h[1] = init1_384
90                 d.h[2] = init2_384
91                 d.h[3] = init3_384
92                 d.h[4] = init4_384
93                 d.h[5] = init5_384
94                 d.h[6] = init6_384
95                 d.h[7] = init7_384
96         case crypto.SHA512_224:
97                 d.h[0] = init0_224
98                 d.h[1] = init1_224
99                 d.h[2] = init2_224
100                 d.h[3] = init3_224
101                 d.h[4] = init4_224
102                 d.h[5] = init5_224
103                 d.h[6] = init6_224
104                 d.h[7] = init7_224
105         case crypto.SHA512_256:
106                 d.h[0] = init0_256
107                 d.h[1] = init1_256
108                 d.h[2] = init2_256
109                 d.h[3] = init3_256
110                 d.h[4] = init4_256
111                 d.h[5] = init5_256
112                 d.h[6] = init6_256
113                 d.h[7] = init7_256
114         default:
115                 d.h[0] = init0
116                 d.h[1] = init1
117                 d.h[2] = init2
118                 d.h[3] = init3
119                 d.h[4] = init4
120                 d.h[5] = init5
121                 d.h[6] = init6
122                 d.h[7] = init7
123         }
124         d.nx = 0
125         d.len = 0
126 }
127
128 // New returns a new hash.Hash computing the SHA-512 checksum.
129 func New() hash.Hash {
130         if boring.Enabled {
131                 return boring.NewSHA512()
132         }
133         d := &digest{function: crypto.SHA512}
134         d.Reset()
135         return d
136 }
137
138 // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum.
139 func New512_224() hash.Hash {
140         d := &digest{function: crypto.SHA512_224}
141         d.Reset()
142         return d
143 }
144
145 // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum.
146 func New512_256() hash.Hash {
147         d := &digest{function: crypto.SHA512_256}
148         d.Reset()
149         return d
150 }
151
152 // New384 returns a new hash.Hash computing the SHA-384 checksum.
153 func New384() hash.Hash {
154         if boring.Enabled {
155                 return boring.NewSHA384()
156         }
157         d := &digest{function: crypto.SHA384}
158         d.Reset()
159         return d
160 }
161
162 func (d *digest) Size() int {
163         switch d.function {
164         case crypto.SHA512_224:
165                 return Size224
166         case crypto.SHA512_256:
167                 return Size256
168         case crypto.SHA384:
169                 return Size384
170         default:
171                 return Size
172         }
173 }
174
175 func (d *digest) BlockSize() int { return BlockSize }
176
177 func (d *digest) Write(p []byte) (nn int, err error) {
178         if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
179                 boring.Unreachable()
180         }
181         nn = len(p)
182         d.len += uint64(nn)
183         if d.nx > 0 {
184                 n := copy(d.x[d.nx:], p)
185                 d.nx += n
186                 if d.nx == chunk {
187                         block(d, d.x[:])
188                         d.nx = 0
189                 }
190                 p = p[n:]
191         }
192         if len(p) >= chunk {
193                 n := len(p) &^ (chunk - 1)
194                 block(d, p[:n])
195                 p = p[n:]
196         }
197         if len(p) > 0 {
198                 d.nx = copy(d.x[:], p)
199         }
200         return
201 }
202
203 func (d0 *digest) Sum(in []byte) []byte {
204         if d0.function != crypto.SHA512_224 && d0.function != crypto.SHA512_256 {
205                 boring.Unreachable()
206         }
207         // Make a copy of d0 so that caller can keep writing and summing.
208         d := new(digest)
209         *d = *d0
210         hash := d.checkSum()
211         switch d.function {
212         case crypto.SHA384:
213                 return append(in, hash[:Size384]...)
214         case crypto.SHA512_224:
215                 return append(in, hash[:Size224]...)
216         case crypto.SHA512_256:
217                 return append(in, hash[:Size256]...)
218         default:
219                 return append(in, hash[:]...)
220         }
221 }
222
223 func (d *digest) checkSum() [Size]byte {
224         // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
225         len := d.len
226         var tmp [128]byte
227         tmp[0] = 0x80
228         if len%128 < 112 {
229                 d.Write(tmp[0 : 112-len%128])
230         } else {
231                 d.Write(tmp[0 : 128+112-len%128])
232         }
233
234         // Length in bits.
235         len <<= 3
236         for i := uint(0); i < 16; i++ {
237                 tmp[i] = byte(len >> (120 - 8*i))
238         }
239         d.Write(tmp[0:16])
240
241         if d.nx != 0 {
242                 panic("d.nx != 0")
243         }
244
245         h := d.h[:]
246         if d.function == crypto.SHA384 {
247                 h = d.h[:6]
248         }
249
250         var digest [Size]byte
251         for i, s := range h {
252                 digest[i*8] = byte(s >> 56)
253                 digest[i*8+1] = byte(s >> 48)
254                 digest[i*8+2] = byte(s >> 40)
255                 digest[i*8+3] = byte(s >> 32)
256                 digest[i*8+4] = byte(s >> 24)
257                 digest[i*8+5] = byte(s >> 16)
258                 digest[i*8+6] = byte(s >> 8)
259                 digest[i*8+7] = byte(s)
260         }
261
262         return digest
263 }
264
265 // Sum512 returns the SHA512 checksum of the data.
266 func Sum512(data []byte) [Size]byte {
267         if boring.Enabled {
268                 h := New()
269                 h.Write(data)
270                 var ret [Size]byte
271                 h.Sum(ret[:0])
272                 return ret
273         }
274         d := digest{function: crypto.SHA512}
275         d.Reset()
276         d.Write(data)
277         return d.checkSum()
278 }
279
280 // Sum384 returns the SHA384 checksum of the data.
281 func Sum384(data []byte) (sum384 [Size384]byte) {
282         if boring.Enabled {
283                 h := New384()
284                 h.Write(data)
285                 var ret [Size384]byte
286                 h.Sum(ret[:0])
287                 return ret
288         }
289         d := digest{function: crypto.SHA384}
290         d.Reset()
291         d.Write(data)
292         sum := d.checkSum()
293         copy(sum384[:], sum[:Size384])
294         return
295 }
296
297 // Sum512_224 returns the Sum512/224 checksum of the data.
298 func Sum512_224(data []byte) (sum224 [Size224]byte) {
299         d := digest{function: crypto.SHA512_224}
300         d.Reset()
301         d.Write(data)
302         sum := d.checkSum()
303         copy(sum224[:], sum[:Size224])
304         return
305 }
306
307 // Sum512_256 returns the Sum512/256 checksum of the data.
308 func Sum512_256(data []byte) (sum256 [Size256]byte) {
309         d := digest{function: crypto.SHA512_256}
310         d.Reset()
311         d.Write(data)
312         sum := d.checkSum()
313         copy(sum256[:], sum[:Size256])
314         return
315 }