1
2
3
4
5
6
7 package sha512
8
9 import (
10 "crypto/internal/fips140"
11 "crypto/internal/fips140deps/byteorder"
12 "errors"
13 "hash"
14 )
15
16 const (
17
18 size512 = 64
19
20
21 size224 = 28
22
23
24 size256 = 32
25
26
27 size384 = 48
28
29
30
31 blockSize = 128
32 )
33
34
35
36 const maxAsmIters = 512
37 const maxAsmSize = chunk * maxAsmIters
38
39 const (
40 chunk = 128
41 init0 = 0x6a09e667f3bcc908
42 init1 = 0xbb67ae8584caa73b
43 init2 = 0x3c6ef372fe94f82b
44 init3 = 0xa54ff53a5f1d36f1
45 init4 = 0x510e527fade682d1
46 init5 = 0x9b05688c2b3e6c1f
47 init6 = 0x1f83d9abfb41bd6b
48 init7 = 0x5be0cd19137e2179
49 init0_224 = 0x8c3d37c819544da2
50 init1_224 = 0x73e1996689dcd4d6
51 init2_224 = 0x1dfab7ae32ff9c82
52 init3_224 = 0x679dd514582f9fcf
53 init4_224 = 0x0f6d2b697bd44da8
54 init5_224 = 0x77e36f7304c48942
55 init6_224 = 0x3f9d85a86a1d36c8
56 init7_224 = 0x1112e6ad91d692a1
57 init0_256 = 0x22312194fc2bf72c
58 init1_256 = 0x9f555fa3c84c64c2
59 init2_256 = 0x2393b86b6f53b151
60 init3_256 = 0x963877195940eabd
61 init4_256 = 0x96283ee2a88effe3
62 init5_256 = 0xbe5e1e2553863992
63 init6_256 = 0x2b0199fc2c85b8aa
64 init7_256 = 0x0eb72ddc81c52ca2
65 init0_384 = 0xcbbb9d5dc1059ed8
66 init1_384 = 0x629a292a367cd507
67 init2_384 = 0x9159015a3070dd17
68 init3_384 = 0x152fecd8f70e5939
69 init4_384 = 0x67332667ffc00b31
70 init5_384 = 0x8eb44a8768581511
71 init6_384 = 0xdb0c2e0d64f98fa7
72 init7_384 = 0x47b5481dbefa4fa4
73 )
74
75
76
77 type Digest struct {
78 h [8]uint64
79 x [chunk]byte
80 nx int
81 len uint64
82 size int
83 }
84
85 func (d *Digest) Reset() {
86 switch d.size {
87 case size384:
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 size224:
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 size256:
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 case size512:
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 default:
124 panic("unknown size")
125 }
126 d.nx = 0
127 d.len = 0
128 }
129
130 const (
131 magic384 = "sha\x04"
132 magic512_224 = "sha\x05"
133 magic512_256 = "sha\x06"
134 magic512 = "sha\x07"
135 marshaledSize = len(magic512) + 8*8 + chunk + 8
136 )
137
138 func (d *Digest) MarshalBinary() ([]byte, error) {
139 return d.AppendBinary(make([]byte, 0, marshaledSize))
140 }
141
142 func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
143 switch d.size {
144 case size384:
145 b = append(b, magic384...)
146 case size224:
147 b = append(b, magic512_224...)
148 case size256:
149 b = append(b, magic512_256...)
150 case size512:
151 b = append(b, magic512...)
152 default:
153 panic("unknown size")
154 }
155 b = byteorder.BEAppendUint64(b, d.h[0])
156 b = byteorder.BEAppendUint64(b, d.h[1])
157 b = byteorder.BEAppendUint64(b, d.h[2])
158 b = byteorder.BEAppendUint64(b, d.h[3])
159 b = byteorder.BEAppendUint64(b, d.h[4])
160 b = byteorder.BEAppendUint64(b, d.h[5])
161 b = byteorder.BEAppendUint64(b, d.h[6])
162 b = byteorder.BEAppendUint64(b, d.h[7])
163 b = append(b, d.x[:d.nx]...)
164 b = append(b, make([]byte, len(d.x)-d.nx)...)
165 b = byteorder.BEAppendUint64(b, d.len)
166 return b, nil
167 }
168
169 func (d *Digest) UnmarshalBinary(b []byte) error {
170 if len(b) < len(magic512) {
171 return errors.New("crypto/sha512: invalid hash state identifier")
172 }
173 switch {
174 case d.size == size384 && string(b[:len(magic384)]) == magic384:
175 case d.size == size224 && string(b[:len(magic512_224)]) == magic512_224:
176 case d.size == size256 && string(b[:len(magic512_256)]) == magic512_256:
177 case d.size == size512 && string(b[:len(magic512)]) == magic512:
178 default:
179 return errors.New("crypto/sha512: invalid hash state identifier")
180 }
181 if len(b) != marshaledSize {
182 return errors.New("crypto/sha512: invalid hash state size")
183 }
184 b = b[len(magic512):]
185 b, d.h[0] = consumeUint64(b)
186 b, d.h[1] = consumeUint64(b)
187 b, d.h[2] = consumeUint64(b)
188 b, d.h[3] = consumeUint64(b)
189 b, d.h[4] = consumeUint64(b)
190 b, d.h[5] = consumeUint64(b)
191 b, d.h[6] = consumeUint64(b)
192 b, d.h[7] = consumeUint64(b)
193 b = b[copy(d.x[:], b):]
194 b, d.len = consumeUint64(b)
195 d.nx = int(d.len % chunk)
196 return nil
197 }
198
199 func consumeUint64(b []byte) ([]byte, uint64) {
200 return b[8:], byteorder.BEUint64(b)
201 }
202
203 func (d *Digest) Clone() (hash.Cloner, error) {
204 r := *d
205 return &r, nil
206 }
207
208
209 func New() *Digest {
210 d := &Digest{size: size512}
211 d.Reset()
212 return d
213 }
214
215
216 func New512_224() *Digest {
217 d := &Digest{size: size224}
218 d.Reset()
219 return d
220 }
221
222
223 func New512_256() *Digest {
224 d := &Digest{size: size256}
225 d.Reset()
226 return d
227 }
228
229
230 func New384() *Digest {
231 d := &Digest{size: size384}
232 d.Reset()
233 return d
234 }
235
236 func (d *Digest) Size() int {
237 return d.size
238 }
239
240 func (d *Digest) BlockSize() int { return blockSize }
241
242 func (d *Digest) Write(p []byte) (nn int, err error) {
243 nn = len(p)
244 d.len += uint64(nn)
245 if d.nx > 0 {
246 n := copy(d.x[d.nx:], p)
247 d.nx += n
248 if d.nx == chunk {
249 block(d, d.x[:])
250 d.nx = 0
251 }
252 p = p[n:]
253 }
254 if len(p) >= chunk {
255 n := len(p) &^ (chunk - 1)
256 for n > maxAsmSize {
257 block(d, p[:maxAsmSize])
258 p = p[maxAsmSize:]
259 n -= maxAsmSize
260 }
261 block(d, p[:n])
262 p = p[n:]
263 }
264 if len(p) > 0 {
265 d.nx = copy(d.x[:], p)
266 }
267 return
268 }
269
270 func (d *Digest) Sum(in []byte) []byte {
271 fips140.RecordApproved()
272
273 d0 := new(Digest)
274 *d0 = *d
275 hash := d0.checkSum()
276 return append(in, hash[:d.size]...)
277 }
278
279 func (d *Digest) checkSum() [size512]byte {
280
281 len := d.len
282 var tmp [128 + 16]byte
283 tmp[0] = 0x80
284 var t uint64
285 if len%128 < 112 {
286 t = 112 - len%128
287 } else {
288 t = 128 + 112 - len%128
289 }
290
291
292 len <<= 3
293 padlen := tmp[:t+16]
294
295
296
297 byteorder.BEPutUint64(padlen[t+8:], len)
298 d.Write(padlen)
299
300 if d.nx != 0 {
301 panic("d.nx != 0")
302 }
303
304 var digest [size512]byte
305 byteorder.BEPutUint64(digest[0:], d.h[0])
306 byteorder.BEPutUint64(digest[8:], d.h[1])
307 byteorder.BEPutUint64(digest[16:], d.h[2])
308 byteorder.BEPutUint64(digest[24:], d.h[3])
309 byteorder.BEPutUint64(digest[32:], d.h[4])
310 byteorder.BEPutUint64(digest[40:], d.h[5])
311 if d.size != size384 {
312 byteorder.BEPutUint64(digest[48:], d.h[6])
313 byteorder.BEPutUint64(digest[56:], d.h[7])
314 }
315
316 return digest
317 }
318
View as plain text