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