]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/sha256/sha256.go
[dev.boringcrypto] misc/boring: add new releases to RELEASES file
[gostls13.git] / src / crypto / sha256 / sha256.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 sha256 implements the SHA224 and SHA256 hash algorithms as defined
6 // in FIPS 180-4.
7 package sha256
8
9 import (
10         "crypto"
11         "encoding/binary"
12         "errors"
13         "hash"
14 )
15
16 import "crypto/internal/boring"
17
18 func init() {
19         crypto.RegisterHash(crypto.SHA224, New224)
20         crypto.RegisterHash(crypto.SHA256, New)
21 }
22
23 // The size of a SHA256 checksum in bytes.
24 const Size = 32
25
26 // The size of a SHA224 checksum in bytes.
27 const Size224 = 28
28
29 // The blocksize of SHA256 and SHA224 in bytes.
30 const BlockSize = 64
31
32 const (
33         chunk     = 64
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         init0_224 = 0xC1059ED8
43         init1_224 = 0x367CD507
44         init2_224 = 0x3070DD17
45         init3_224 = 0xF70E5939
46         init4_224 = 0xFFC00B31
47         init5_224 = 0x68581511
48         init6_224 = 0x64F98FA7
49         init7_224 = 0xBEFA4FA4
50 )
51
52 // digest represents the partial evaluation of a checksum.
53 type digest struct {
54         h     [8]uint32
55         x     [chunk]byte
56         nx    int
57         len   uint64
58         is224 bool // mark if this digest is SHA-224
59 }
60
61 const (
62         magic224      = "sha\x02"
63         magic256      = "sha\x03"
64         marshaledSize = len(magic256) + 8*4 + chunk + 8
65 )
66
67 func (d *digest) MarshalBinary() ([]byte, error) {
68         b := make([]byte, 0, marshaledSize)
69         if d.is224 {
70                 b = append(b, magic224...)
71         } else {
72                 b = append(b, magic256...)
73         }
74         b = appendUint32(b, d.h[0])
75         b = appendUint32(b, d.h[1])
76         b = appendUint32(b, d.h[2])
77         b = appendUint32(b, d.h[3])
78         b = appendUint32(b, d.h[4])
79         b = appendUint32(b, d.h[5])
80         b = appendUint32(b, d.h[6])
81         b = appendUint32(b, d.h[7])
82         b = append(b, d.x[:d.nx]...)
83         b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
84         b = appendUint64(b, d.len)
85         return b, nil
86 }
87
88 func (d *digest) UnmarshalBinary(b []byte) error {
89         if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
90                 return errors.New("crypto/sha256: invalid hash state identifier")
91         }
92         if len(b) != marshaledSize {
93                 return errors.New("crypto/sha256: invalid hash state size")
94         }
95         b = b[len(magic224):]
96         b, d.h[0] = consumeUint32(b)
97         b, d.h[1] = consumeUint32(b)
98         b, d.h[2] = consumeUint32(b)
99         b, d.h[3] = consumeUint32(b)
100         b, d.h[4] = consumeUint32(b)
101         b, d.h[5] = consumeUint32(b)
102         b, d.h[6] = consumeUint32(b)
103         b, d.h[7] = consumeUint32(b)
104         b = b[copy(d.x[:], b):]
105         b, d.len = consumeUint64(b)
106         d.nx = int(d.len % chunk)
107         return nil
108 }
109
110 func appendUint64(b []byte, x uint64) []byte {
111         var a [8]byte
112         binary.BigEndian.PutUint64(a[:], x)
113         return append(b, a[:]...)
114 }
115
116 func appendUint32(b []byte, x uint32) []byte {
117         var a [4]byte
118         binary.BigEndian.PutUint32(a[:], x)
119         return append(b, a[:]...)
120 }
121
122 func consumeUint64(b []byte) ([]byte, uint64) {
123         _ = b[7]
124         x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
125                 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
126         return b[8:], x
127 }
128
129 func consumeUint32(b []byte) ([]byte, uint32) {
130         _ = b[3]
131         x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
132         return b[4:], x
133 }
134
135 func (d *digest) Reset() {
136         if !d.is224 {
137                 d.h[0] = init0
138                 d.h[1] = init1
139                 d.h[2] = init2
140                 d.h[3] = init3
141                 d.h[4] = init4
142                 d.h[5] = init5
143                 d.h[6] = init6
144                 d.h[7] = init7
145         } else {
146                 d.h[0] = init0_224
147                 d.h[1] = init1_224
148                 d.h[2] = init2_224
149                 d.h[3] = init3_224
150                 d.h[4] = init4_224
151                 d.h[5] = init5_224
152                 d.h[6] = init6_224
153                 d.h[7] = init7_224
154         }
155         d.nx = 0
156         d.len = 0
157 }
158
159 // New returns a new hash.Hash computing the SHA256 checksum. The Hash
160 // also implements encoding.BinaryMarshaler and
161 // encoding.BinaryUnmarshaler to marshal and unmarshal the internal
162 // state of the hash.
163 func New() hash.Hash {
164         if boring.Enabled {
165                 return boring.NewSHA256()
166         }
167         d := new(digest)
168         d.Reset()
169         return d
170 }
171
172 // New224 returns a new hash.Hash computing the SHA224 checksum.
173 func New224() hash.Hash {
174         if boring.Enabled {
175                 return boring.NewSHA224()
176         }
177         d := new(digest)
178         d.is224 = true
179         d.Reset()
180         return d
181 }
182
183 func (d *digest) Size() int {
184         if !d.is224 {
185                 return Size
186         }
187         return Size224
188 }
189
190 func (d *digest) BlockSize() int { return BlockSize }
191
192 func (d *digest) Write(p []byte) (nn int, err error) {
193         boring.Unreachable()
194         nn = len(p)
195         d.len += uint64(nn)
196         if d.nx > 0 {
197                 n := copy(d.x[d.nx:], p)
198                 d.nx += n
199                 if d.nx == chunk {
200                         block(d, d.x[:])
201                         d.nx = 0
202                 }
203                 p = p[n:]
204         }
205         if len(p) >= chunk {
206                 n := len(p) &^ (chunk - 1)
207                 block(d, p[:n])
208                 p = p[n:]
209         }
210         if len(p) > 0 {
211                 d.nx = copy(d.x[:], p)
212         }
213         return
214 }
215
216 func (d *digest) Sum(in []byte) []byte {
217         boring.Unreachable()
218         // Make a copy of d so that caller can keep writing and summing.
219         d0 := *d
220         hash := d0.checkSum()
221         if d0.is224 {
222                 return append(in, hash[:Size224]...)
223         }
224         return append(in, hash[:]...)
225 }
226
227 func (d *digest) checkSum() [Size]byte {
228         len := d.len
229         // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
230         var tmp [64]byte
231         tmp[0] = 0x80
232         if len%64 < 56 {
233                 d.Write(tmp[0 : 56-len%64])
234         } else {
235                 d.Write(tmp[0 : 64+56-len%64])
236         }
237
238         // Length in bits.
239         len <<= 3
240         binary.BigEndian.PutUint64(tmp[:], len)
241         d.Write(tmp[0:8])
242
243         if d.nx != 0 {
244                 panic("d.nx != 0")
245         }
246
247         var digest [Size]byte
248
249         binary.BigEndian.PutUint32(digest[0:], d.h[0])
250         binary.BigEndian.PutUint32(digest[4:], d.h[1])
251         binary.BigEndian.PutUint32(digest[8:], d.h[2])
252         binary.BigEndian.PutUint32(digest[12:], d.h[3])
253         binary.BigEndian.PutUint32(digest[16:], d.h[4])
254         binary.BigEndian.PutUint32(digest[20:], d.h[5])
255         binary.BigEndian.PutUint32(digest[24:], d.h[6])
256         if !d.is224 {
257                 binary.BigEndian.PutUint32(digest[28:], d.h[7])
258         }
259
260         return digest
261 }
262
263 // Sum256 returns the SHA256 checksum of the data.
264 func Sum256(data []byte) [Size]byte {
265         if boring.Enabled {
266                 h := New()
267                 h.Write(data)
268                 var ret [Size]byte
269                 h.Sum(ret[:0])
270                 return ret
271         }
272         var d digest
273         d.Reset()
274         d.Write(data)
275         return d.checkSum()
276 }
277
278 // Sum224 returns the SHA224 checksum of the data.
279 func Sum224(data []byte) (sum224 [Size224]byte) {
280         if boring.Enabled {
281                 h := New224()
282                 h.Write(data)
283                 var ret [Size224]byte
284                 h.Sum(ret[:0])
285                 return ret
286         }
287         var d digest
288         d.is224 = true
289         d.Reset()
290         d.Write(data)
291         sum := d.checkSum()
292         copy(sum224[:], sum[:Size224])
293         return
294 }