1
2
3
4
5
6
7 package sha256
8
9 import (
10 "crypto/internal/fips140"
11 "crypto/internal/fips140deps/byteorder"
12 "errors"
13 "hash"
14 )
15
16
17 const size = 32
18
19
20 const size224 = 28
21
22
23 const blockSize = 64
24
25
26
27 const maxAsmIters = 1024
28 const maxAsmSize = blockSize * maxAsmIters
29
30 const (
31 chunk = 64
32 init0 = 0x6A09E667
33 init1 = 0xBB67AE85
34 init2 = 0x3C6EF372
35 init3 = 0xA54FF53A
36 init4 = 0x510E527F
37 init5 = 0x9B05688C
38 init6 = 0x1F83D9AB
39 init7 = 0x5BE0CD19
40 init0_224 = 0xC1059ED8
41 init1_224 = 0x367CD507
42 init2_224 = 0x3070DD17
43 init3_224 = 0xF70E5939
44 init4_224 = 0xFFC00B31
45 init5_224 = 0x68581511
46 init6_224 = 0x64F98FA7
47 init7_224 = 0xBEFA4FA4
48 )
49
50
51 type Digest struct {
52 h [8]uint32
53 x [chunk]byte
54 nx int
55 len uint64
56 is224 bool
57 }
58
59 const (
60 magic224 = "sha\x02"
61 magic256 = "sha\x03"
62 marshaledSize = len(magic256) + 8*4 + chunk + 8
63 )
64
65 func (d *Digest) MarshalBinary() ([]byte, error) {
66 return d.AppendBinary(make([]byte, 0, marshaledSize))
67 }
68
69 func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
70 if d.is224 {
71 b = append(b, magic224...)
72 } else {
73 b = append(b, magic256...)
74 }
75 b = byteorder.BEAppendUint32(b, d.h[0])
76 b = byteorder.BEAppendUint32(b, d.h[1])
77 b = byteorder.BEAppendUint32(b, d.h[2])
78 b = byteorder.BEAppendUint32(b, d.h[3])
79 b = byteorder.BEAppendUint32(b, d.h[4])
80 b = byteorder.BEAppendUint32(b, d.h[5])
81 b = byteorder.BEAppendUint32(b, d.h[6])
82 b = byteorder.BEAppendUint32(b, d.h[7])
83 b = append(b, d.x[:d.nx]...)
84 b = append(b, make([]byte, len(d.x)-d.nx)...)
85 b = byteorder.BEAppendUint64(b, d.len)
86 return b, nil
87 }
88
89 func (d *Digest) UnmarshalBinary(b []byte) error {
90 if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
91 return errors.New("crypto/sha256: invalid hash state identifier")
92 }
93 if len(b) != marshaledSize {
94 return errors.New("crypto/sha256: invalid hash state size")
95 }
96 b = b[len(magic224):]
97 b, d.h[0] = consumeUint32(b)
98 b, d.h[1] = consumeUint32(b)
99 b, d.h[2] = consumeUint32(b)
100 b, d.h[3] = consumeUint32(b)
101 b, d.h[4] = consumeUint32(b)
102 b, d.h[5] = consumeUint32(b)
103 b, d.h[6] = consumeUint32(b)
104 b, d.h[7] = consumeUint32(b)
105 b = b[copy(d.x[:], b):]
106 b, d.len = consumeUint64(b)
107 d.nx = int(d.len % chunk)
108 return nil
109 }
110
111 func consumeUint64(b []byte) ([]byte, uint64) {
112 return b[8:], byteorder.BEUint64(b)
113 }
114
115 func consumeUint32(b []byte) ([]byte, uint32) {
116 return b[4:], byteorder.BEUint32(b)
117 }
118
119 func (d *Digest) Clone() (hash.Cloner, error) {
120 r := *d
121 return &r, nil
122 }
123
124 func (d *Digest) Reset() {
125 if !d.is224 {
126 d.h[0] = init0
127 d.h[1] = init1
128 d.h[2] = init2
129 d.h[3] = init3
130 d.h[4] = init4
131 d.h[5] = init5
132 d.h[6] = init6
133 d.h[7] = init7
134 } else {
135 d.h[0] = init0_224
136 d.h[1] = init1_224
137 d.h[2] = init2_224
138 d.h[3] = init3_224
139 d.h[4] = init4_224
140 d.h[5] = init5_224
141 d.h[6] = init6_224
142 d.h[7] = init7_224
143 }
144 d.nx = 0
145 d.len = 0
146 }
147
148
149 func New() *Digest {
150 d := new(Digest)
151 d.Reset()
152 return d
153 }
154
155
156 func New224() *Digest {
157 d := new(Digest)
158 d.is224 = true
159 d.Reset()
160 return d
161 }
162
163 func (d *Digest) Size() int {
164 if !d.is224 {
165 return size
166 }
167 return size224
168 }
169
170 func (d *Digest) BlockSize() int { return blockSize }
171
172 func (d *Digest) Write(p []byte) (nn int, err error) {
173 nn = len(p)
174 d.len += uint64(nn)
175 if d.nx > 0 {
176 n := copy(d.x[d.nx:], p)
177 d.nx += n
178 if d.nx == chunk {
179 block(d, d.x[:])
180 d.nx = 0
181 }
182 p = p[n:]
183 }
184 if len(p) >= chunk {
185 n := len(p) &^ (chunk - 1)
186 for n > maxAsmSize {
187 block(d, p[:maxAsmSize])
188 p = p[maxAsmSize:]
189 n -= maxAsmSize
190 }
191 block(d, p[:n])
192 p = p[n:]
193 }
194 if len(p) > 0 {
195 d.nx = copy(d.x[:], p)
196 }
197 return
198 }
199
200 func (d *Digest) Sum(in []byte) []byte {
201 fips140.RecordApproved()
202
203 d0 := *d
204 hash := d0.checkSum()
205 if d0.is224 {
206 return append(in, hash[:size224]...)
207 }
208 return append(in, hash[:]...)
209 }
210
211 func (d *Digest) checkSum() [size]byte {
212 len := d.len
213
214 var tmp [64 + 8]byte
215 tmp[0] = 0x80
216 var t uint64
217 if len%64 < 56 {
218 t = 56 - len%64
219 } else {
220 t = 64 + 56 - len%64
221 }
222
223
224 len <<= 3
225 padlen := tmp[:t+8]
226 byteorder.BEPutUint64(padlen[t+0:], len)
227 d.Write(padlen)
228
229 if d.nx != 0 {
230 panic("d.nx != 0")
231 }
232
233 var digest [size]byte
234
235 byteorder.BEPutUint32(digest[0:], d.h[0])
236 byteorder.BEPutUint32(digest[4:], d.h[1])
237 byteorder.BEPutUint32(digest[8:], d.h[2])
238 byteorder.BEPutUint32(digest[12:], d.h[3])
239 byteorder.BEPutUint32(digest[16:], d.h[4])
240 byteorder.BEPutUint32(digest[20:], d.h[5])
241 byteorder.BEPutUint32(digest[24:], d.h[6])
242 if !d.is224 {
243 byteorder.BEPutUint32(digest[28:], d.h[7])
244 }
245
246 return digest
247 }
248
View as plain text