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