]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/sha256/sha256.go
[dev.boringcrypto] misc/boring: add go1.9.2b4 release
[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         "crypto/internal/boring"
12         "hash"
13 )
14
15 func init() {
16         crypto.RegisterHash(crypto.SHA224, New224)
17         crypto.RegisterHash(crypto.SHA256, New)
18 }
19
20 // The size of a SHA256 checksum in bytes.
21 const Size = 32
22
23 // The size of a SHA224 checksum in bytes.
24 const Size224 = 28
25
26 // The blocksize of SHA256 and SHA224 in bytes.
27 const BlockSize = 64
28
29 const (
30         chunk     = 64
31         init0     = 0x6A09E667
32         init1     = 0xBB67AE85
33         init2     = 0x3C6EF372
34         init3     = 0xA54FF53A
35         init4     = 0x510E527F
36         init5     = 0x9B05688C
37         init6     = 0x1F83D9AB
38         init7     = 0x5BE0CD19
39         init0_224 = 0xC1059ED8
40         init1_224 = 0x367CD507
41         init2_224 = 0x3070DD17
42         init3_224 = 0xF70E5939
43         init4_224 = 0xFFC00B31
44         init5_224 = 0x68581511
45         init6_224 = 0x64F98FA7
46         init7_224 = 0xBEFA4FA4
47 )
48
49 // digest represents the partial evaluation of a checksum.
50 type digest struct {
51         h     [8]uint32
52         x     [chunk]byte
53         nx    int
54         len   uint64
55         is224 bool // mark if this digest is SHA-224
56 }
57
58 func (d *digest) Reset() {
59         if !d.is224 {
60                 d.h[0] = init0
61                 d.h[1] = init1
62                 d.h[2] = init2
63                 d.h[3] = init3
64                 d.h[4] = init4
65                 d.h[5] = init5
66                 d.h[6] = init6
67                 d.h[7] = init7
68         } else {
69                 d.h[0] = init0_224
70                 d.h[1] = init1_224
71                 d.h[2] = init2_224
72                 d.h[3] = init3_224
73                 d.h[4] = init4_224
74                 d.h[5] = init5_224
75                 d.h[6] = init6_224
76                 d.h[7] = init7_224
77         }
78         d.nx = 0
79         d.len = 0
80 }
81
82 // New returns a new hash.Hash computing the SHA256 checksum.
83 func New() hash.Hash {
84         if boring.Enabled {
85                 return boring.NewSHA256()
86         }
87         d := new(digest)
88         d.Reset()
89         return d
90 }
91
92 // New224 returns a new hash.Hash computing the SHA224 checksum.
93 func New224() hash.Hash {
94         if boring.Enabled {
95                 return boring.NewSHA224()
96         }
97         d := new(digest)
98         d.is224 = true
99         d.Reset()
100         return d
101 }
102
103 func (d *digest) Size() int {
104         if !d.is224 {
105                 return Size
106         }
107         return Size224
108 }
109
110 func (d *digest) BlockSize() int { return BlockSize }
111
112 func (d *digest) Write(p []byte) (nn int, err error) {
113         boring.Unreachable()
114         nn = len(p)
115         d.len += uint64(nn)
116         if d.nx > 0 {
117                 n := copy(d.x[d.nx:], p)
118                 d.nx += n
119                 if d.nx == chunk {
120                         block(d, d.x[:])
121                         d.nx = 0
122                 }
123                 p = p[n:]
124         }
125         if len(p) >= chunk {
126                 n := len(p) &^ (chunk - 1)
127                 block(d, p[:n])
128                 p = p[n:]
129         }
130         if len(p) > 0 {
131                 d.nx = copy(d.x[:], p)
132         }
133         return
134 }
135
136 func (d0 *digest) Sum(in []byte) []byte {
137         boring.Unreachable()
138         // Make a copy of d0 so that caller can keep writing and summing.
139         d := *d0
140         hash := d.checkSum()
141         if d.is224 {
142                 return append(in, hash[:Size224]...)
143         }
144         return append(in, hash[:]...)
145 }
146
147 func (d *digest) checkSum() [Size]byte {
148         len := d.len
149         // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
150         var tmp [64]byte
151         tmp[0] = 0x80
152         if len%64 < 56 {
153                 d.Write(tmp[0 : 56-len%64])
154         } else {
155                 d.Write(tmp[0 : 64+56-len%64])
156         }
157
158         // Length in bits.
159         len <<= 3
160         for i := uint(0); i < 8; i++ {
161                 tmp[i] = byte(len >> (56 - 8*i))
162         }
163         d.Write(tmp[0:8])
164
165         if d.nx != 0 {
166                 panic("d.nx != 0")
167         }
168
169         h := d.h[:]
170         if d.is224 {
171                 h = d.h[:7]
172         }
173
174         var digest [Size]byte
175         for i, s := range h {
176                 digest[i*4] = byte(s >> 24)
177                 digest[i*4+1] = byte(s >> 16)
178                 digest[i*4+2] = byte(s >> 8)
179                 digest[i*4+3] = byte(s)
180         }
181
182         return digest
183 }
184
185 // Sum256 returns the SHA256 checksum of the data.
186 func Sum256(data []byte) [Size]byte {
187         if boring.Enabled {
188                 h := New()
189                 h.Write(data)
190                 var ret [Size]byte
191                 h.Sum(ret[:0])
192                 return ret
193         }
194         var d digest
195         d.Reset()
196         d.Write(data)
197         return d.checkSum()
198 }
199
200 // Sum224 returns the SHA224 checksum of the data.
201 func Sum224(data []byte) (sum224 [Size224]byte) {
202         if boring.Enabled {
203                 h := New224()
204                 h.Write(data)
205                 var ret [Size224]byte
206                 h.Sum(ret[:0])
207                 return ret
208         }
209         var d digest
210         d.is224 = true
211         d.Reset()
212         d.Write(data)
213         sum := d.checkSum()
214         copy(sum224[:], sum[:Size224])
215         return
216 }