1use digest::Digest;
74use cryptoutil::{write_u32_be, read_u32v_be,
75 write_u64_be, read_u64v_be,
76 add_bytes_to_bits, add_bytes_to_bits_tuple,
77 FixedBuffer, FixedBuffer128, FixedBuffer64, StandardPadding};
78
79use simd::{u32x4, u64x2};
80
81const STATE_LEN: usize = 8;
82const BLOCK_LEN: usize = 16;
83
84#[inline]
86fn sha256load(v2: u32x4, v3: u32x4) -> u32x4 {
87 u32x4(v3.3, v2.0, v2.1, v2.2)
88}
89
90#[inline]
92fn sha256swap(v0: u32x4) -> u32x4 {
93 u32x4(v0.2, v0.3, v0.0, v0.1)
94}
95
96fn sha256msg1(v0: u32x4, v1: u32x4) -> u32x4 {
99
100 #[inline]
102 fn sigma0x4(x: u32x4) -> u32x4 {
103 ((x >> u32x4( 7, 7, 7, 7)) | (x << u32x4(25, 25, 25, 25))) ^
104 ((x >> u32x4(18, 18, 18, 18)) | (x << u32x4(14, 14, 14, 14))) ^
105 (x >> u32x4( 3, 3, 3, 3))
106 }
107
108 v0 + sigma0x4(sha256load(v0, v1))
109}
110
111fn sha256msg2(v4: u32x4, v3: u32x4) -> u32x4 {
114
115 macro_rules! sigma1 {
116 ($a:expr) => (($a.rotate_right(17) ^ $a.rotate_right(19) ^ ($a >> 10)))
117 }
118
119 let u32x4(x3, x2, x1, x0) = v4;
120 let u32x4(w15, w14, _, _) = v3;
121
122 let w16 = x0.wrapping_add(sigma1!(w14));
123 let w17 = x1.wrapping_add(sigma1!(w15));
124 let w18 = x2.wrapping_add(sigma1!(w16));
125 let w19 = x3.wrapping_add(sigma1!(w17));
126
127 u32x4(w19, w18, w17, w16)
128}
129
130pub fn sha256_schedule_x4(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4 {
132 sha256msg2(sha256msg1(v0, v1) + sha256load(v2, v3), v3)
133}
134
135pub fn sha256_digest_round_x2(cdgh: u32x4, abef: u32x4, wk: u32x4) -> u32x4 {
138
139 macro_rules! big_sigma0 {
140 ($a:expr) => (($a.rotate_right(2) ^ $a.rotate_right(13) ^ $a.rotate_right(22)))
141 }
142 macro_rules! big_sigma1 {
143 ($a:expr) => (($a.rotate_right(6) ^ $a.rotate_right(11) ^ $a.rotate_right(25)))
144 }
145 macro_rules! bool3ary_202 {
146 ($a:expr, $b:expr, $c:expr) => (($c ^ ($a & ($b ^ $c))))
147 } macro_rules! bool3ary_232 {
149 ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
150 } let u32x4(_, _, wk1, wk0) = wk;
153 let u32x4(a0, b0, e0, f0) = abef;
154 let u32x4(c0, d0, g0, h0) = cdgh;
155
156 let x0 = big_sigma1!(e0).wrapping_add(bool3ary_202!(e0, f0, g0)).wrapping_add(wk0).wrapping_add(h0);
158 let y0 = big_sigma0!(a0).wrapping_add(bool3ary_232!(a0, b0, c0));
159 let (a1, b1, c1, d1, e1, f1, g1, h1) = (
160 x0.wrapping_add(y0), a0, b0, c0,
161 x0.wrapping_add(d0), e0, f0, g0);
162
163 let x1 = big_sigma1!(e1).wrapping_add(bool3ary_202!(e1, f1, g1)).wrapping_add(wk1).wrapping_add(h1);
165 let y1 = big_sigma0!(a1).wrapping_add(bool3ary_232!(a1, b1, c1));
166 let (a2, b2, _, _, e2, f2, _, _) = (
167 x1.wrapping_add(y1), a1, b1, c1,
168 x1.wrapping_add(d1), e1, f1, g1);
169
170 u32x4(a2, b2, e2, f2)
171}
172
173pub fn sha256_digest_block_u32(state: &mut [u32; 8], block: &[u32; 16]) {
175 let k = &K32X4;
176
177 macro_rules! schedule {
178 ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => (
179 sha256msg2(sha256msg1($v0, $v1) + sha256load($v2, $v3), $v3)
180 )
181 }
182
183 macro_rules! rounds4 {
184 ($abef:ident, $cdgh:ident, $rest:expr) => {
185 {
186 $cdgh = sha256_digest_round_x2($cdgh, $abef, $rest);
187 $abef = sha256_digest_round_x2($abef, $cdgh, sha256swap($rest));
188 }
189 }
190 }
191
192 let mut abef = u32x4(state[0],
193 state[1],
194 state[4],
195 state[5]);
196 let mut cdgh = u32x4(state[2],
197 state[3],
198 state[6],
199 state[7]);
200
201 let mut w0 = u32x4(block[3],
203 block[2],
204 block[1],
205 block[0]);
206 rounds4!(abef, cdgh, k[0] + w0);
207 let mut w1 = u32x4(block[7],
208 block[6],
209 block[5],
210 block[4]);
211 rounds4!(abef, cdgh, k[1] + w1);
212 let mut w2 = u32x4(block[11],
213 block[10],
214 block[9],
215 block[8]);
216 rounds4!(abef, cdgh, k[2] + w2);
217 let mut w3 = u32x4(block[15],
218 block[14],
219 block[13],
220 block[12]);
221 rounds4!(abef, cdgh, k[3] + w3);
222 let mut w4 = schedule!(w0, w1, w2, w3);
223 rounds4!(abef, cdgh, k[4] + w4);
224 w0 = schedule!(w1, w2, w3, w4);
225 rounds4!(abef, cdgh, k[5] + w0);
226 w1 = schedule!(w2, w3, w4, w0);
227 rounds4!(abef, cdgh, k[6] + w1);
228 w2 = schedule!(w3, w4, w0, w1);
229 rounds4!(abef, cdgh, k[7] + w2);
230 w3 = schedule!(w4, w0, w1, w2);
231 rounds4!(abef, cdgh, k[8] + w3);
232 w4 = schedule!(w0, w1, w2, w3);
233 rounds4!(abef, cdgh, k[9] + w4);
234 w0 = schedule!(w1, w2, w3, w4);
235 rounds4!(abef, cdgh, k[10] + w0);
236 w1 = schedule!(w2, w3, w4, w0);
237 rounds4!(abef, cdgh, k[11] + w1);
238 w2 = schedule!(w3, w4, w0, w1);
239 rounds4!(abef, cdgh, k[12] + w2);
240 w3 = schedule!(w4, w0, w1, w2);
241 rounds4!(abef, cdgh, k[13] + w3);
242 w4 = schedule!(w0, w1, w2, w3);
243 rounds4!(abef, cdgh, k[14] + w4);
244 w0 = schedule!(w1, w2, w3, w4);
245 rounds4!(abef, cdgh, k[15] + w0);
246
247 let u32x4(a, b, e, f) = abef;
248 let u32x4(c, d, g, h) = cdgh;
249
250 state[0] = state[0].wrapping_add(a);
251 state[1] = state[1].wrapping_add(b);
252 state[2] = state[2].wrapping_add(c);
253 state[3] = state[3].wrapping_add(d);
254 state[4] = state[4].wrapping_add(e);
255 state[5] = state[5].wrapping_add(f);
256 state[6] = state[6].wrapping_add(g);
257 state[7] = state[7].wrapping_add(h);
258}
259
260pub fn sha256_digest_block(state: &mut [u32; 8], block: &[u8]) {
352 assert_eq!(block.len(), BLOCK_LEN*4);
353 let mut block2 = [0u32; BLOCK_LEN];
354 read_u32v_be(&mut block2[..], block);
355 sha256_digest_block_u32(state, &block2);
356}
357
358#[inline]
360fn sha512load(v0: u64x2, v1: u64x2) -> u64x2 {
361 u64x2(v1.1, v0.0)
362}
363
364pub fn sha512_schedule_x2(v0: u64x2, v1: u64x2, v4to5: u64x2, v7: u64x2) -> u64x2 {
366
367 fn sigma0(x: u64) -> u64 {
369 ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7)
370 }
371
372 fn sigma1(x: u64) -> u64 {
374 ((x << 45) | (x >> 19)) ^ ((x << 3) | (x >> 61)) ^ (x >> 6)
375 }
376
377 let u64x2(w1, w0) = v0;
378 let u64x2(_, w2) = v1;
379 let u64x2(w10, w9) = v4to5;
380 let u64x2(w15, w14) = v7;
381
382 let w16 = sigma1(w14).wrapping_add(w9).wrapping_add(sigma0(w1)).wrapping_add(w0);
383 let w17 = sigma1(w15).wrapping_add(w10).wrapping_add(sigma0(w2)).wrapping_add(w1);
384
385 u64x2(w17, w16)
386}
387
388pub fn sha512_digest_round(ae: u64x2, bf: u64x2, cg: u64x2, dh: u64x2, wk0: u64) -> u64x2 {
390
391 macro_rules! big_sigma0 {
392 ($a:expr) => (($a.rotate_right(28) ^ $a.rotate_right(34) ^ $a.rotate_right(39)))
393 }
394 macro_rules! big_sigma1 {
395 ($a:expr) => (($a.rotate_right(14) ^ $a.rotate_right(18) ^ $a.rotate_right(41)))
396 }
397 macro_rules! bool3ary_202 {
398 ($a:expr, $b:expr, $c:expr) => (($c ^ ($a & ($b ^ $c))))
399 } macro_rules! bool3ary_232 {
401 ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
402 } let u64x2(a0, e0) = ae;
405 let u64x2(b0, f0) = bf;
406 let u64x2(c0, g0) = cg;
407 let u64x2(d0, h0) = dh;
408
409 let x0 = big_sigma1!(e0).wrapping_add(bool3ary_202!(e0, f0, g0)).wrapping_add(wk0).wrapping_add(h0);
411 let y0 = big_sigma0!(a0).wrapping_add(bool3ary_232!(a0, b0, c0));
412 let (a1, _, _, _, e1, _, _, _) = (
413 x0.wrapping_add(y0), a0, b0, c0,
414 x0.wrapping_add(d0), e0, f0, g0);
415
416 u64x2(a1, e1)
417}
418
419pub fn sha512_digest_block_u64(state: &mut [u64; 8], block: &[u64; 16]) {
421 let k = &K64X2;
422
423 macro_rules! schedule {
424 ($v0:expr, $v1:expr, $v4:expr, $v5:expr, $v7:expr) => (
425 sha512_schedule_x2($v0, $v1, sha512load($v4, $v5), $v7)
426 )
427 }
428
429 macro_rules! rounds4 {
430 ($ae:ident, $bf:ident, $cg:ident, $dh:ident, $wk0:expr, $wk1:expr) => {
431 {
432 let u64x2(u, t) = $wk0;
433 let u64x2(w, v) = $wk1;
434
435 $dh = sha512_digest_round($ae, $bf, $cg, $dh, t);
436 $cg = sha512_digest_round($dh, $ae, $bf, $cg, u);
437 $bf = sha512_digest_round($cg, $dh, $ae, $bf, v);
438 $ae = sha512_digest_round($bf, $cg, $dh, $ae, w);
439 }
440 }
441 }
442
443 let mut ae = u64x2(state[0],
444 state[4]);
445 let mut bf = u64x2(state[1],
446 state[5]);
447 let mut cg = u64x2(state[2],
448 state[6]);
449 let mut dh = u64x2(state[3],
450 state[7]);
451
452 let (mut w1, mut w0) = (u64x2(block[3],
454 block[2]),
455 u64x2(block[1],
456 block[0]));
457 rounds4!(ae, bf, cg, dh, k[0] + w0, k[1] + w1);
458 let (mut w3, mut w2) = (u64x2(block[7],
459 block[6]),
460 u64x2(block[5],
461 block[4]));
462 rounds4!(ae, bf, cg, dh, k[2] + w2, k[3] + w3);
463 let (mut w5, mut w4) = (u64x2(block[11],
464 block[10]),
465 u64x2(block[9],
466 block[8]));
467 rounds4!(ae, bf, cg, dh, k[4] + w4, k[5] + w5);
468 let (mut w7, mut w6) = (u64x2(block[15],
469 block[14]),
470 u64x2(block[13],
471 block[12]));
472 rounds4!(ae, bf, cg, dh, k[6] + w6, k[7] + w7);
473 let mut w8 = schedule!(w0, w1, w4, w5, w7);
474 let mut w9 = schedule!(w1, w2, w5, w6, w8);
475 rounds4!(ae, bf, cg, dh, k[8] + w8, k[9] + w9);
476
477 w0 = schedule!(w2, w3, w6, w7, w9);
479 w1 = schedule!(w3, w4, w7, w8, w0);
480 rounds4!(ae, bf, cg, dh, k[10] + w0, k[11] + w1);
481 w2 = schedule!(w4, w5, w8, w9, w1);
482 w3 = schedule!(w5, w6, w9, w0, w2);
483 rounds4!(ae, bf, cg, dh, k[12] + w2, k[13] + w3);
484 w4 = schedule!(w6, w7, w0, w1, w3);
485 w5 = schedule!(w7, w8, w1, w2, w4);
486 rounds4!(ae, bf, cg, dh, k[14] + w4, k[15] + w5);
487 w6 = schedule!(w8, w9, w2, w3, w5);
488 w7 = schedule!(w9, w0, w3, w4, w6);
489 rounds4!(ae, bf, cg, dh, k[16] + w6, k[17] + w7);
490 w8 = schedule!(w0, w1, w4, w5, w7);
491 w9 = schedule!(w1, w2, w5, w6, w8);
492 rounds4!(ae, bf, cg, dh, k[18] + w8, k[19] + w9);
493
494 w0 = schedule!(w2, w3, w6, w7, w9);
496 w1 = schedule!(w3, w4, w7, w8, w0);
497 rounds4!(ae, bf, cg, dh, k[20] + w0, k[21] + w1);
498 w2 = schedule!(w4, w5, w8, w9, w1);
499 w3 = schedule!(w5, w6, w9, w0, w2);
500 rounds4!(ae, bf, cg, dh, k[22] + w2, k[23] + w3);
501 w4 = schedule!(w6, w7, w0, w1, w3);
502 w5 = schedule!(w7, w8, w1, w2, w4);
503 rounds4!(ae, bf, cg, dh, k[24] + w4, k[25] + w5);
504 w6 = schedule!(w8, w9, w2, w3, w5);
505 w7 = schedule!(w9, w0, w3, w4, w6);
506 rounds4!(ae, bf, cg, dh, k[26] + w6, k[27] + w7);
507 w8 = schedule!(w0, w1, w4, w5, w7);
508 w9 = schedule!(w1, w2, w5, w6, w8);
509 rounds4!(ae, bf, cg, dh, k[28] + w8, k[29] + w9);
510
511 w0 = schedule!(w2, w3, w6, w7, w9);
513 w1 = schedule!(w3, w4, w7, w8, w0);
514 rounds4!(ae, bf, cg, dh, k[30] + w0, k[31] + w1);
515 w2 = schedule!(w4, w5, w8, w9, w1);
516 w3 = schedule!(w5, w6, w9, w0, w2);
517 rounds4!(ae, bf, cg, dh, k[32] + w2, k[33] + w3);
518 w4 = schedule!(w6, w7, w0, w1, w3);
519 w5 = schedule!(w7, w8, w1, w2, w4);
520 rounds4!(ae, bf, cg, dh, k[34] + w4, k[35] + w5);
521 w6 = schedule!(w8, w9, w2, w3, w5);
522 w7 = schedule!(w9, w0, w3, w4, w6);
523 rounds4!(ae, bf, cg, dh, k[36] + w6, k[37] + w7);
524 w8 = schedule!(w0, w1, w4, w5, w7);
525 w9 = schedule!(w1, w2, w5, w6, w8);
526 rounds4!(ae, bf, cg, dh, k[38] + w8, k[39] + w9);
527
528 let u64x2(a, e) = ae;
529 let u64x2(b, f) = bf;
530 let u64x2(c, g) = cg;
531 let u64x2(d, h) = dh;
532
533 state[0] = state[0].wrapping_add(a);
534 state[1] = state[1].wrapping_add(b);
535 state[2] = state[2].wrapping_add(c);
536 state[3] = state[3].wrapping_add(d);
537 state[4] = state[4].wrapping_add(e);
538 state[5] = state[5].wrapping_add(f);
539 state[6] = state[6].wrapping_add(g);
540 state[7] = state[7].wrapping_add(h);
541}
542
543pub fn sha512_digest_block(state: &mut [u64; 8], block: &[u8]) {
639 assert_eq!(block.len(), BLOCK_LEN*8);
640 let mut block2 = [0u64; BLOCK_LEN];
641 read_u64v_be(&mut block2[..], block);
642 sha512_digest_block_u64(state, &block2);
643}
644
645#[derive(Copy, Clone)]
648struct Engine512State {
649 h: [u64; 8]
650}
651
652impl Engine512State {
653 fn new(h: &[u64; 8]) -> Engine512State {
654 Engine512State {
655 h: *h
656 }
657 }
658
659 fn reset(&mut self, h: &[u64; STATE_LEN]) {
660 self.h = *h;
661 }
662
663 pub fn process_block(&mut self, data: &[u8]) {
664 sha512_digest_block(&mut self.h, data);
665 }
666}
667
668pub const K64: [u64; 80] = [
670 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
671 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
672 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
673 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
674 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
675 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
676 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
677 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
678 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
679 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
680 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
681 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
682 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
683 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
684 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
685 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
686 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
687 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
688 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
689 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
690];
691
692pub const K64X2: [u64x2; 40] = [
694 u64x2(K64[1], K64[0]), u64x2(K64[3], K64[2]), u64x2(K64[5], K64[4]), u64x2(K64[7], K64[6]),
695 u64x2(K64[9], K64[8]), u64x2(K64[11], K64[10]), u64x2(K64[13], K64[12]), u64x2(K64[15], K64[14]),
696 u64x2(K64[17], K64[16]), u64x2(K64[19], K64[18]), u64x2(K64[21], K64[20]), u64x2(K64[23], K64[22]),
697 u64x2(K64[25], K64[24]), u64x2(K64[27], K64[26]), u64x2(K64[29], K64[28]), u64x2(K64[31], K64[30]),
698 u64x2(K64[33], K64[32]), u64x2(K64[35], K64[34]), u64x2(K64[37], K64[36]), u64x2(K64[39], K64[38]),
699 u64x2(K64[41], K64[40]), u64x2(K64[43], K64[42]), u64x2(K64[45], K64[44]), u64x2(K64[47], K64[46]),
700 u64x2(K64[49], K64[48]), u64x2(K64[51], K64[50]), u64x2(K64[53], K64[52]), u64x2(K64[55], K64[54]),
701 u64x2(K64[57], K64[56]), u64x2(K64[59], K64[58]), u64x2(K64[61], K64[60]), u64x2(K64[63], K64[62]),
702 u64x2(K64[65], K64[64]), u64x2(K64[67], K64[66]), u64x2(K64[69], K64[68]), u64x2(K64[71], K64[70]),
703 u64x2(K64[73], K64[72]), u64x2(K64[75], K64[74]), u64x2(K64[77], K64[76]), u64x2(K64[79], K64[78])
704];
705
706#[derive(Copy, Clone)]
709struct Engine512 {
710 length_bits: (u64, u64),
711 buffer: FixedBuffer128,
712 state: Engine512State,
713 finished: bool,
714}
715
716impl Engine512 {
717 fn new(h: &[u64; STATE_LEN]) -> Engine512 {
718 Engine512 {
719 length_bits: (0, 0),
720 buffer: FixedBuffer128::new(),
721 state: Engine512State::new(h),
722 finished: false
723 }
724 }
725
726 fn reset(&mut self, h: &[u64; STATE_LEN]) {
727 self.length_bits = (0, 0);
728 self.buffer.reset();
729 self.state.reset(h);
730 self.finished = false;
731 }
732
733 fn input(&mut self, input: &[u8]) {
734 assert!(!self.finished);
735 self.length_bits = add_bytes_to_bits_tuple(self.length_bits, input.len() as u64);
737 let self_state = &mut self.state;
738 self.buffer.input(input, |input: &[u8]| { self_state.process_block(input) });
739 }
740
741 fn finish(&mut self) {
742 if self.finished {
743 return;
744 }
745
746 let self_state = &mut self.state;
747 self.buffer.standard_padding(16, |input: &[u8]| { self_state.process_block(input) });
748 match self.length_bits {
749 (hi, low) => {
750 write_u64_be(self.buffer.next(8), hi);
751 write_u64_be(self.buffer.next(8), low);
752 }
753 }
754 self_state.process_block(self.buffer.full_buffer());
755
756 self.finished = true;
757 }
758}
759
760
761#[derive(Copy, Clone)]
763pub struct Sha512 {
764 engine: Engine512
765}
766
767impl Sha512 {
768 pub fn new() -> Sha512 {
772 Sha512 {
773 engine: Engine512::new(&H512)
774 }
775 }
776}
777
778impl Digest for Sha512 {
779 fn input(&mut self, d: &[u8]) {
780 self.engine.input(d);
781 }
782
783 fn result(&mut self, out: &mut [u8]) {
784 self.engine.finish();
785
786 write_u64_be(&mut out[0..8], self.engine.state.h[0]);
787 write_u64_be(&mut out[8..16], self.engine.state.h[1]);
788 write_u64_be(&mut out[16..24], self.engine.state.h[2]);
789 write_u64_be(&mut out[24..32], self.engine.state.h[3]);
790 write_u64_be(&mut out[32..40], self.engine.state.h[4]);
791 write_u64_be(&mut out[40..48], self.engine.state.h[5]);
792 write_u64_be(&mut out[48..56], self.engine.state.h[6]);
793 write_u64_be(&mut out[56..64], self.engine.state.h[7]);
794 }
795
796 fn reset(&mut self) {
797 self.engine.reset(&H512);
798 }
799
800 fn output_bits(&self) -> usize { 512 }
801
802 fn block_size(&self) -> usize { 128 }
803}
804
805static H512: [u64; STATE_LEN] = [
806 0x6a09e667f3bcc908,
807 0xbb67ae8584caa73b,
808 0x3c6ef372fe94f82b,
809 0xa54ff53a5f1d36f1,
810 0x510e527fade682d1,
811 0x9b05688c2b3e6c1f,
812 0x1f83d9abfb41bd6b,
813 0x5be0cd19137e2179
814];
815
816
817#[derive(Copy, Clone)]
819pub struct Sha384 {
820 engine: Engine512
821}
822
823impl Sha384 {
824 pub fn new() -> Sha384 {
828 Sha384 {
829 engine: Engine512::new(&H384)
830 }
831 }
832}
833
834impl Digest for Sha384 {
835 fn input(&mut self, d: &[u8]) {
836 self.engine.input(d);
837 }
838
839 fn result(&mut self, out: &mut [u8]) {
840 self.engine.finish();
841
842 write_u64_be(&mut out[0..8], self.engine.state.h[0]);
843 write_u64_be(&mut out[8..16], self.engine.state.h[1]);
844 write_u64_be(&mut out[16..24], self.engine.state.h[2]);
845 write_u64_be(&mut out[24..32], self.engine.state.h[3]);
846 write_u64_be(&mut out[32..40], self.engine.state.h[4]);
847 write_u64_be(&mut out[40..48], self.engine.state.h[5]);
848 }
849
850 fn reset(&mut self) {
851 self.engine.reset(&H384);
852 }
853
854 fn output_bits(&self) -> usize { 384 }
855
856 fn block_size(&self) -> usize { 128 }
857}
858
859static H384: [u64; STATE_LEN] = [
860 0xcbbb9d5dc1059ed8,
861 0x629a292a367cd507,
862 0x9159015a3070dd17,
863 0x152fecd8f70e5939,
864 0x67332667ffc00b31,
865 0x8eb44a8768581511,
866 0xdb0c2e0d64f98fa7,
867 0x47b5481dbefa4fa4
868];
869
870
871#[derive(Clone, Copy)]
873pub struct Sha512Trunc256 {
874 engine: Engine512
875}
876
877impl Sha512Trunc256 {
878 pub fn new() -> Sha512Trunc256 {
882 Sha512Trunc256 {
883 engine: Engine512::new(&H512_TRUNC_256)
884 }
885 }
886}
887
888impl Digest for Sha512Trunc256 {
889 fn input(&mut self, d: &[u8]) {
890 self.engine.input(d);
891 }
892
893 fn result(&mut self, out: &mut [u8]) {
894 self.engine.finish();
895
896 write_u64_be(&mut out[0..8], self.engine.state.h[0]);
897 write_u64_be(&mut out[8..16], self.engine.state.h[1]);
898 write_u64_be(&mut out[16..24], self.engine.state.h[2]);
899 write_u64_be(&mut out[24..32], self.engine.state.h[3]);
900 }
901
902 fn reset(&mut self) {
903 self.engine.reset(&H512_TRUNC_256);
904 }
905
906 fn output_bits(&self) -> usize { 256 }
907
908 fn block_size(&self) -> usize { 128 }
909}
910
911static H512_TRUNC_256: [u64; STATE_LEN] = [
912 0x22312194fc2bf72c,
913 0x9f555fa3c84c64c2,
914 0x2393b86b6f53b151,
915 0x963877195940eabd,
916 0x96283ee2a88effe3,
917 0xbe5e1e2553863992,
918 0x2b0199fc2c85b8aa,
919 0x0eb72ddc81c52ca2
920];
921
922
923#[derive(Clone, Copy)]
925pub struct Sha512Trunc224 {
926 engine: Engine512
927}
928
929impl Sha512Trunc224 {
930 pub fn new() -> Sha512Trunc224 {
934 Sha512Trunc224 {
935 engine: Engine512::new(&H512_TRUNC_224)
936 }
937 }
938}
939
940impl Digest for Sha512Trunc224 {
941 fn input(&mut self, d: &[u8]) {
942 self.engine.input(d);
943 }
944
945 fn result(&mut self, out: &mut [u8]) {
946 self.engine.finish();
947
948 write_u64_be(&mut out[0..8], self.engine.state.h[0]);
949 write_u64_be(&mut out[8..16], self.engine.state.h[1]);
950 write_u64_be(&mut out[16..24], self.engine.state.h[2]);
951 write_u32_be(&mut out[24..28], (self.engine.state.h[3] >> 32) as u32);
952 }
953
954 fn reset(&mut self) {
955 self.engine.reset(&H512_TRUNC_224);
956 }
957
958 fn output_bits(&self) -> usize { 224 }
959
960 fn block_size(&self) -> usize { 128 }
961}
962
963static H512_TRUNC_224: [u64; STATE_LEN] = [
964 0x8c3d37c819544da2,
965 0x73e1996689dcd4d6,
966 0x1dfab7ae32ff9c82,
967 0x679dd514582f9fcf,
968 0x0f6d2b697bd44da8,
969 0x77e36f7304c48942,
970 0x3f9d85a86a1d36c8,
971 0x1112e6ad91d692a1,
972];
973
974
975#[derive(Clone, Copy)]
978struct Engine256State {
979 h: [u32; 8],
980}
981
982impl Engine256State {
983 fn new(h: &[u32; STATE_LEN]) -> Engine256State {
984 Engine256State {
985 h: *h
986 }
987 }
988
989 fn reset(&mut self, h: &[u32; STATE_LEN]) {
990 self.h = *h;
991 }
992
993 pub fn process_block(&mut self, data: &[u8]) {
994 sha256_digest_block(&mut self.h, data);
995 }
996}
997
998pub const K32: [u32; 64] = [
1000 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
1001 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1002 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
1003 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1004 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
1005 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1006 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
1007 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1008 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
1009 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1010 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
1011 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1012 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
1013 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1014 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
1015 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1016];
1017
1018pub const K32X4: [u32x4; 16] = [
1020 u32x4(K32[3], K32[2], K32[1], K32[0]),
1021 u32x4(K32[7], K32[6], K32[5], K32[4]),
1022 u32x4(K32[11], K32[10], K32[9], K32[8]),
1023 u32x4(K32[15], K32[14], K32[13], K32[12]),
1024 u32x4(K32[19], K32[18], K32[17], K32[16]),
1025 u32x4(K32[23], K32[22], K32[21], K32[20]),
1026 u32x4(K32[27], K32[26], K32[25], K32[24]),
1027 u32x4(K32[31], K32[30], K32[29], K32[28]),
1028 u32x4(K32[35], K32[34], K32[33], K32[32]),
1029 u32x4(K32[39], K32[38], K32[37], K32[36]),
1030 u32x4(K32[43], K32[42], K32[41], K32[40]),
1031 u32x4(K32[47], K32[46], K32[45], K32[44]),
1032 u32x4(K32[51], K32[50], K32[49], K32[48]),
1033 u32x4(K32[55], K32[54], K32[53], K32[52]),
1034 u32x4(K32[59], K32[58], K32[57], K32[56]),
1035 u32x4(K32[63], K32[62], K32[61], K32[60]),
1036];
1037
1038#[derive(Clone, Copy)]
1041struct Engine256 {
1042 length_bits: u64,
1043 buffer: FixedBuffer64,
1044 state: Engine256State,
1045 finished: bool,
1046}
1047
1048impl Engine256 {
1049 fn new(h: &[u32; STATE_LEN]) -> Engine256 {
1050 Engine256 {
1051 length_bits: 0,
1052 buffer: FixedBuffer64::new(),
1053 state: Engine256State::new(h),
1054 finished: false
1055 }
1056 }
1057
1058 fn reset(&mut self, h: &[u32; STATE_LEN]) {
1059 self.length_bits = 0;
1060 self.buffer.reset();
1061 self.state.reset(h);
1062 self.finished = false;
1063 }
1064
1065 fn input(&mut self, input: &[u8]) {
1066 assert!(!self.finished);
1067 self.length_bits = add_bytes_to_bits(self.length_bits, input.len() as u64);
1069 let self_state = &mut self.state;
1070 self.buffer.input(input, |input: &[u8]| { self_state.process_block(input) });
1071 }
1072
1073 fn finish(&mut self) {
1074 if self.finished {
1075 return;
1076 }
1077
1078 let self_state = &mut self.state;
1079 self.buffer.standard_padding(8, |input: &[u8]| { self_state.process_block(input) });
1080 write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 );
1081 write_u32_be(self.buffer.next(4), self.length_bits as u32);
1082 self_state.process_block(self.buffer.full_buffer());
1083
1084 self.finished = true;
1085 }
1086}
1087
1088
1089#[derive(Clone, Copy)]
1091pub struct Sha256 {
1092 engine: Engine256
1093}
1094
1095impl Sha256 {
1096 pub fn new() -> Sha256 {
1100 Sha256 {
1101 engine: Engine256::new(&H256)
1102 }
1103 }
1104}
1105
1106impl Digest for Sha256 {
1107 fn input(&mut self, d: &[u8]) {
1108 self.engine.input(d);
1109 }
1110
1111 fn result(&mut self, out: &mut [u8]) {
1112 self.engine.finish();
1113
1114 write_u32_be(&mut out[0..4], self.engine.state.h[0]);
1115 write_u32_be(&mut out[4..8], self.engine.state.h[1]);
1116 write_u32_be(&mut out[8..12], self.engine.state.h[2]);
1117 write_u32_be(&mut out[12..16], self.engine.state.h[3]);
1118 write_u32_be(&mut out[16..20], self.engine.state.h[4]);
1119 write_u32_be(&mut out[20..24], self.engine.state.h[5]);
1120 write_u32_be(&mut out[24..28], self.engine.state.h[6]);
1121 write_u32_be(&mut out[28..32], self.engine.state.h[7]);
1122 }
1123
1124 fn reset(&mut self) {
1125 self.engine.reset(&H256);
1126 }
1127
1128 fn output_bits(&self) -> usize { 256 }
1129
1130 fn block_size(&self) -> usize { 64 }
1131}
1132
1133static H256: [u32; STATE_LEN] = [
1134 0x6a09e667,
1135 0xbb67ae85,
1136 0x3c6ef372,
1137 0xa54ff53a,
1138 0x510e527f,
1139 0x9b05688c,
1140 0x1f83d9ab,
1141 0x5be0cd19
1142];
1143
1144
1145#[derive(Clone, Copy)]
1147pub struct Sha224 {
1148 engine: Engine256
1149}
1150
1151impl Sha224 {
1152 pub fn new() -> Sha224 {
1156 Sha224 {
1157 engine: Engine256::new(&H224)
1158 }
1159 }
1160}
1161
1162impl Digest for Sha224 {
1163 fn input(&mut self, d: &[u8]) {
1164 self.engine.input(d);
1165 }
1166
1167 fn result(&mut self, out: &mut [u8]) {
1168 self.engine.finish();
1169 write_u32_be(&mut out[0..4], self.engine.state.h[0]);
1170 write_u32_be(&mut out[4..8], self.engine.state.h[1]);
1171 write_u32_be(&mut out[8..12], self.engine.state.h[2]);
1172 write_u32_be(&mut out[12..16], self.engine.state.h[3]);
1173 write_u32_be(&mut out[16..20], self.engine.state.h[4]);
1174 write_u32_be(&mut out[20..24], self.engine.state.h[5]);
1175 write_u32_be(&mut out[24..28], self.engine.state.h[6]);
1176 }
1177
1178 fn reset(&mut self) {
1179 self.engine.reset(&H224);
1180 }
1181
1182 fn output_bits(&self) -> usize { 224 }
1183
1184 fn block_size(&self) -> usize { 64 }
1185}
1186
1187static H224: [u32; STATE_LEN] = [
1188 0xc1059ed8,
1189 0x367cd507,
1190 0x3070dd17,
1191 0xf70e5939,
1192 0xffc00b31,
1193 0x68581511,
1194 0x64f98fa7,
1195 0xbefa4fa4
1196];
1197
1198
1199#[cfg(test)]
1200mod tests {
1201 use cryptoutil::test::test_digest_1million_random;
1202 use digest::Digest;
1203 use sha2::{Sha512, Sha384, Sha512Trunc256, Sha512Trunc224, Sha256, Sha224};
1204
1205 struct Test {
1206 input: &'static str,
1207 output_str: &'static str,
1208 }
1209
1210 fn test_hash<D: Digest>(sh: &mut D, tests: &[Test]) {
1211 for t in tests.iter() {
1213 sh.input_str(t.input);
1214
1215 let out_str = sh.result_str();
1216 assert!(&out_str[..] == t.output_str);
1217
1218 sh.reset();
1219 }
1220
1221 for t in tests.iter() {
1223 let len = t.input.len();
1224 let mut left = len;
1225 while left > 0 {
1226 let take = (left + 1) / 2;
1227 sh.input_str(&t.input[len - left..take + len - left]);
1228 left = left - take;
1229 }
1230
1231 let out_str = sh.result_str();
1232 assert!(&out_str[..] == t.output_str);
1233
1234 sh.reset();
1235 }
1236 }
1237
1238 #[test]
1239 fn test_sha512() {
1240 let wikipedia_tests = vec![
1242 Test {
1243 input: "",
1244 output_str: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
1245 },
1246 Test {
1247 input: "The quick brown fox jumps over the lazy dog",
1248 output_str: "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"
1249 },
1250 Test {
1251 input: "The quick brown fox jumps over the lazy dog.",
1252 output_str: "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed"
1253 },
1254 ];
1255
1256 let tests = wikipedia_tests;
1257
1258 let mut sh = Box::new(Sha512::new());
1259
1260 test_hash(&mut *sh, &tests[..]);
1261 }
1262
1263 #[test]
1264 fn test_sha384() {
1265 let wikipedia_tests = vec![
1267 Test {
1268 input: "",
1269 output_str: "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
1270 },
1271 Test {
1272 input: "The quick brown fox jumps over the lazy dog",
1273 output_str: "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1"
1274 },
1275 Test {
1276 input: "The quick brown fox jumps over the lazy dog.",
1277 output_str: "ed892481d8272ca6df370bf706e4d7bc1b5739fa2177aae6c50e946678718fc67a7af2819a021c2fc34e91bdb63409d7"
1278 },
1279 ];
1280
1281 let tests = wikipedia_tests;
1282
1283 let mut sh = Box::new(Sha384::new());
1284
1285 test_hash(&mut *sh, &tests[..]);
1286 }
1287
1288 #[test]
1289 fn test_sha512_256() {
1290 let wikipedia_tests = vec![
1292 Test {
1293 input: "",
1294 output_str: "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"
1295 },
1296 Test {
1297 input: "The quick brown fox jumps over the lazy dog",
1298 output_str: "dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d"
1299 },
1300 Test {
1301 input: "The quick brown fox jumps over the lazy dog.",
1302 output_str: "1546741840f8a492b959d9b8b2344b9b0eb51b004bba35c0aebaac86d45264c3"
1303 },
1304 ];
1305
1306 let tests = wikipedia_tests;
1307
1308 let mut sh = Box::new(Sha512Trunc256::new());
1309
1310 test_hash(&mut *sh, &tests[..]);
1311 }
1312
1313 #[test]
1314 fn test_sha512_224() {
1315 let wikipedia_tests = vec![
1317 Test {
1318 input: "",
1319 output_str: "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4"
1320 },
1321 Test {
1322 input: "The quick brown fox jumps over the lazy dog",
1323 output_str: "944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37"
1324 },
1325 Test {
1326 input: "The quick brown fox jumps over the lazy dog.",
1327 output_str: "6d6a9279495ec4061769752e7ff9c68b6b0b3c5a281b7917ce0572de"
1328 },
1329 ];
1330
1331 let tests = wikipedia_tests;
1332
1333 let mut sh = Box::new(Sha512Trunc224::new());
1334
1335 test_hash(&mut *sh, &tests[..]);
1336 }
1337
1338 #[test]
1339 fn test_sha256() {
1340 let wikipedia_tests = vec![
1342 Test {
1343 input: "",
1344 output_str: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
1345 },
1346 Test {
1347 input: "The quick brown fox jumps over the lazy dog",
1348 output_str: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
1349 },
1350 Test {
1351 input: "The quick brown fox jumps over the lazy dog.",
1352 output_str: "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c"
1353 },
1354 ];
1355
1356 let tests = wikipedia_tests;
1357
1358 let mut sh = Box::new(Sha256::new());
1359
1360 test_hash(&mut *sh, &tests[..]);
1361 }
1362
1363 #[test]
1364 fn test_sha224() {
1365 let wikipedia_tests = vec![
1367 Test {
1368 input: "",
1369 output_str: "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
1370 },
1371 Test {
1372 input: "The quick brown fox jumps over the lazy dog",
1373 output_str: "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525"
1374 },
1375 Test {
1376 input: "The quick brown fox jumps over the lazy dog.",
1377 output_str: "619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4c"
1378 },
1379 ];
1380
1381 let tests = wikipedia_tests;
1382
1383 let mut sh = Box::new(Sha224::new());
1384
1385 test_hash(&mut *sh, &tests[..]);
1386 }
1387
1388 #[test]
1389 fn test_1million_random_sha512() {
1390 let mut sh = Sha512::new();
1391 test_digest_1million_random(
1392 &mut sh,
1393 128,
1394 "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b");
1395 }
1396
1397 #[test]
1398 fn test_1million_random_sha256() {
1399 let mut sh = Sha256::new();
1400 test_digest_1million_random(
1401 &mut sh,
1402 64,
1403 "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
1404 }
1405}
1406
1407
1408
1409#[cfg(all(test, feature = "with-bench"))]
1410mod bench {
1411 use test::Bencher;
1412 use digest::Digest;
1413 use sha2::{STATE_LEN, BLOCK_LEN};
1414 use sha2::{Sha256, Sha512, sha256_digest_block_u32, sha512_digest_block_u64};
1415
1416 #[bench]
1417 pub fn sha256_block(bh: & mut Bencher) {
1418 let mut state = [0u32; STATE_LEN];
1419 let words = [1u32; BLOCK_LEN];
1420 bh.iter( || {
1421 sha256_digest_block_u32(&mut state, &words);
1422 });
1423 bh.bytes = 64u64;
1424 }
1425
1426 #[bench]
1427 pub fn sha512_block(bh: & mut Bencher) {
1428 let mut state = [0u64; STATE_LEN];
1429 let words = [1u64; BLOCK_LEN];
1430 bh.iter( || {
1431 sha512_digest_block_u64(&mut state, &words);
1432 });
1433 bh.bytes = 128u64;
1434 }
1435
1436 #[bench]
1437 pub fn sha256_10(bh: & mut Bencher) {
1438 let mut sh = Sha256::new();
1439 let bytes = [1u8; 10];
1440 bh.iter( || {
1441 sh.input(&bytes);
1442 });
1443 bh.bytes = bytes.len() as u64;
1444 }
1445
1446 #[bench]
1447 pub fn sha256_1k(bh: & mut Bencher) {
1448 let mut sh = Sha256::new();
1449 let bytes = [1u8; 1024];
1450 bh.iter( || {
1451 sh.input(&bytes);
1452 });
1453 bh.bytes = bytes.len() as u64;
1454 }
1455
1456 #[bench]
1457 pub fn sha256_64k(bh: & mut Bencher) {
1458 let mut sh = Sha256::new();
1459 let bytes = [1u8; 65536];
1460 bh.iter( || {
1461 sh.input(&bytes);
1462 });
1463 bh.bytes = bytes.len() as u64;
1464 }
1465
1466 #[bench]
1467 pub fn sha512_10(bh: & mut Bencher) {
1468 let mut sh = Sha512::new();
1469 let bytes = [1u8; 10];
1470 bh.iter( || {
1471 sh.input(&bytes);
1472 });
1473 bh.bytes = bytes.len() as u64;
1474 }
1475
1476 #[bench]
1477 pub fn sha512_1k(bh: & mut Bencher) {
1478 let mut sh = Sha512::new();
1479 let bytes = [1u8; 1024];
1480 bh.iter( || {
1481 sh.input(&bytes);
1482 });
1483 bh.bytes = bytes.len() as u64;
1484 }
1485
1486 #[bench]
1487 pub fn sha512_64k(bh: & mut Bencher) {
1488 let mut sh = Sha512::new();
1489 let bytes = [1u8; 65536];
1490 bh.iter( || {
1491 sh.input(&bytes);
1492 });
1493 bh.bytes = bytes.len() as u64;
1494 }
1495
1496}