crypto/
sha2.rs

1// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11/*!
12An implementation of the SHA-2 cryptographic hash algorithms.
13
14There are 6 standard algorithms specified in the SHA-2 standard:
15
16 * `Sha224`, which is the 32-bit `Sha256` algorithm with the result truncated to 224 bits.
17 * `Sha256`, which is the 32-bit `Sha256` algorithm.
18 * `Sha384`, which is the 64-bit `Sha512` algorithm with the result truncated to 384 bits.
19 * `Sha512`, which is the 64-bit `Sha512` algorithm.
20 * `Sha512Trunc224`, which is the 64-bit `Sha512` algorithm with the result truncated to 224 bits.
21 * `Sha512Trunc256`, which is the 64-bit `Sha512` algorithm with the result truncated to 256 bits.
22
23Algorithmically, there are only 2 core algorithms: `Sha256` and `Sha512`.
24All other algorithms are just applications of these with different initial hash
25values, and truncated to different digest bit lengths.
26
27# Usage
28
29An example of using `Sha256` is:
30
31```rust
32use self::crypto::digest::Digest;
33use self::crypto::sha2::Sha256;
34
35// create a Sha256 object
36let mut hasher = Sha256::new();
37
38// write input message
39hasher.input_str("hello world");
40
41// read hash digest
42let hex = hasher.result_str();
43
44assert_eq!(hex,
45           concat!("b94d27b9934d3e08a52e52d7da7dabfa",
46                   "c484efe37a5380ee9088f7ace2efcde9"));
47```
48
49An example of using `Sha512` is:
50
51```rust
52use self::crypto::digest::Digest;
53use self::crypto::sha2::Sha512;
54
55// create a Sha512 object
56let mut hasher = Sha512::new();
57
58// write input message
59hasher.input_str("hello world");
60
61// read hash digest
62let hex = hasher.result_str();
63
64assert_eq!(hex,
65           concat!("309ecc489c12d6eb4cc40f50c902f2b4",
66                   "d0ed77ee511a7c7a9bcd3ca86d4cd86f",
67                   "989dd35bc5ff499670da34255b45b0cf",
68                   "d830e81f605dcf7dc5542e93ae9cd76f"));
69```
70
71 */
72
73use 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/// Not an intrinsic, but works like an unaligned load.
85#[inline]
86fn sha256load(v2: u32x4, v3: u32x4) -> u32x4 {
87    u32x4(v3.3, v2.0, v2.1, v2.2)
88}
89
90/// Not an intrinsic, but useful for swapping vectors.
91#[inline]
92fn sha256swap(v0: u32x4) -> u32x4 {
93    u32x4(v0.2, v0.3, v0.0, v0.1)
94}
95
96/// Emulates `llvm.x86.sha256msg1` intrinsic.
97//#[inline]
98fn sha256msg1(v0: u32x4, v1: u32x4) -> u32x4 {
99
100    // sigma 0 on vectors
101    #[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
111/// Emulates `llvm.x86.sha256msg2` intrinsic.
112//#[inline]
113fn 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
130/// Performs 4 rounds of the SHA-256 message schedule update.
131pub fn sha256_schedule_x4(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4 {
132    sha256msg2(sha256msg1(v0, v1) + sha256load(v2, v3), v3)
133}
134
135/// Emulates `llvm.x86.sha256rnds2` intrinsic.
136//#[inline]
137pub 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    } // Choose, MD5F, SHA1C
148    macro_rules! bool3ary_232 {
149        ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
150    } // Majority, SHA1M
151
152    let u32x4(_, _, wk1, wk0) = wk;
153    let u32x4(a0, b0, e0, f0) = abef;
154    let u32x4(c0, d0, g0, h0) = cdgh;
155
156    // a round
157    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    // a round
164    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
173/// Process a block with the SHA-256 algorithm.
174pub 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    // Rounds 0..64
202    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
260/// Process a block with the SHA-256 algorithm. (See more...)
261///
262/// Internally, this uses functions which resemble the new Intel SHA instruction sets,
263/// and so it's data locality properties may improve performance. However, to benefit
264/// the most from this implementation, replace these functions with x86 intrinsics to
265/// get a possible speed boost.
266///
267/// # Implementation
268///
269/// The `Sha256` algorithm is implemented with functions that resemble the new
270/// Intel SHA instruction set extensions. These intructions fall into two categories:
271/// message schedule calculation, and the message block 64-round digest calculation.
272/// The schedule-related instructions allow 4 rounds to be calculated as:
273///
274/// ```ignore
275/// use std::simd::u32x4;
276/// use self::crypto::sha2::{
277///     sha256msg1,
278///     sha256msg2,
279///     sha256load
280/// };
281///
282/// fn schedule4_data(work: &mut [u32x4], w: &[u32]) {
283///
284///     // this is to illustrate the data order
285///     work[0] = u32x4(w[3], w[2], w[1], w[0]);
286///     work[1] = u32x4(w[7], w[6], w[5], w[4]);
287///     work[2] = u32x4(w[11], w[10], w[9], w[8]);
288///     work[3] = u32x4(w[15], w[14], w[13], w[12]);
289/// }
290///
291/// fn schedule4_work(work: &mut [u32x4], t: usize) {
292///
293///     // this is the core expression
294///     work[t] = sha256msg2(sha256msg1(work[t - 4], work[t - 3]) +
295///                          sha256load(work[t - 2], work[t - 1]),
296///                          work[t - 1])
297/// }
298/// ```
299///
300/// instead of 4 rounds of:
301///
302/// ```ignore
303/// fn schedule_work(w: &mut [u32], t: usize) {
304///     w[t] = sigma1!(w[t - 2]) + w[t - 7] + sigma0!(w[t - 15]) + w[t - 16];
305/// }
306/// ```
307///
308/// and the digest-related instructions allow 4 rounds to be calculated as:
309///
310/// ```ignore
311/// use std::simd::u32x4;
312/// use self::crypto::sha2::{K32X4,
313///     sha256rnds2,
314///     sha256swap
315/// };
316///
317/// fn rounds4(state: &mut [u32; 8], work: &mut [u32x4], t: usize) {
318///     let [a, b, c, d, e, f, g, h]: [u32; 8] = *state;
319///
320///     // this is to illustrate the data order
321///     let mut abef = u32x4(a, b, e, f);
322///     let mut cdgh = u32x4(c, d, g, h);
323///     let temp = K32X4[t] + work[t];
324///
325///     // this is the core expression
326///     cdgh = sha256rnds2(cdgh, abef, temp);
327///     abef = sha256rnds2(abef, cdgh, sha256swap(temp));
328///
329///     *state = [abef.0, abef.1, cdgh.0, cdgh.1,
330///               abef.2, abef.3, cdgh.2, cdgh.3];
331/// }
332/// ```
333///
334/// instead of 4 rounds of:
335///
336/// ```ignore
337/// fn round(state: &mut [u32; 8], w: &mut [u32], t: usize) {
338///     let [a, b, c, mut d, e, f, g, mut h]: [u32; 8] = *state;
339///
340///     h += big_sigma1!(e) +   choose!(e, f, g) + K32[t] + w[t]; d += h;
341///     h += big_sigma0!(a) + majority!(a, b, c);
342///
343///     *state = [h, a, b, c, d, e, f, g];
344/// }
345/// ```
346///
347/// **NOTE**: It is important to note, however, that these instructions are not implemented
348/// by any CPU (at the time of this writing), and so they are emulated in this library
349/// until the instructions become more common, and gain support in LLVM (and GCC, etc.).
350///
351pub fn sha256_digest_block(state: &mut [u32; 8], block: &[u8/*; 64*/]) {
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/// Not an intrinsic, but works like an unaligned load.
359#[inline]
360fn sha512load(v0: u64x2, v1: u64x2) -> u64x2 {
361    u64x2(v1.1, v0.0)
362}
363
364/// Performs 2 rounds of the SHA-512 message schedule update.
365pub fn sha512_schedule_x2(v0: u64x2, v1: u64x2, v4to5: u64x2, v7: u64x2) -> u64x2 {
366
367    // sigma 0
368    fn sigma0(x: u64) -> u64 {
369        ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7)
370    }
371
372    // sigma 1
373    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
388/// Performs one round of the SHA-512 message block digest.
389pub 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    } // Choose, MD5F, SHA1C
400    macro_rules! bool3ary_232 {
401        ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
402    } // Majority, SHA1M
403
404    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    // a round
410    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
419/// Process a block with the SHA-512 algorithm.
420pub 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    // Rounds 0..20
453    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    // Rounds 20..40
478    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    // Rounds 40..60
495    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    // Rounds 60..80
512    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
543/// Process a block with the SHA-512 algorithm. (See more...)
544///
545/// Internally, this uses functions that resemble the new Intel SHA
546/// instruction set extensions, but since no architecture seems to
547/// have any designs, these may not be the final designs if and/or when
548/// there are instruction set extensions with SHA-512. So to summarize:
549/// SHA-1 and SHA-256 are being implemented in hardware soon (at the time
550/// of this writing), but it doesn't look like SHA-512 will be hardware
551/// accelerated any time soon.
552///
553/// # Implementation
554///
555/// These functions fall into two categories:
556/// message schedule calculation, and the message block 64-round digest calculation.
557/// The schedule-related functions allow 4 rounds to be calculated as:
558///
559/// ```ignore
560/// use std::simd::u64x2;
561/// use self::crypto::sha2::{
562///     sha512msg,
563///     sha512load
564/// };
565///
566/// fn schedule4_data(work: &mut [u64x2], w: &[u64]) {
567///
568///     // this is to illustrate the data order
569///     work[0] = u64x2(w[1], w[0]);
570///     work[1] = u64x2(w[3], w[2]);
571///     work[2] = u64x2(w[5], w[4]);
572///     work[3] = u64x2(w[7], w[6]);
573///     work[4] = u64x2(w[9], w[8]);
574///     work[5] = u64x2(w[11], w[10]);
575///     work[6] = u64x2(w[13], w[12]);
576///     work[7] = u64x2(w[15], w[14]);
577/// }
578///
579/// fn schedule4_work(work: &mut [u64x2], t: usize) {
580///
581///     // this is the core expression
582///     work[t] = sha512msg(work[t - 8],
583///                         work[t - 7],
584///                         sha512load(work[t - 4], work[t - 3]),
585///                         work[t - 1]);
586/// }
587/// ```
588///
589/// instead of 4 rounds of:
590///
591/// ```ignore
592/// fn schedule_work(w: &mut [u64], t: usize) {
593///     w[t] = sigma1!(w[t - 2]) + w[t - 7] + sigma0!(w[t - 15]) + w[t - 16];
594/// }
595/// ```
596///
597/// and the digest-related functions allow 4 rounds to be calculated as:
598///
599/// ```ignore
600/// use std::simd::u64x2;
601/// use self::crypto::sha2::{K64X2, sha512rnd};
602///
603/// fn rounds4(state: &mut [u64; 8], work: &mut [u64x2], t: usize) {
604///     let [a, b, c, d, e, f, g, h]: [u64; 8] = *state;
605///
606///     // this is to illustrate the data order
607///     let mut ae = u64x2(a, e);
608///     let mut bf = u64x2(b, f);
609///     let mut cg = u64x2(c, g);
610///     let mut dh = u64x2(d, h);
611///     let u64x2(w1, w0) = K64X2[2*t]     + work[2*t];
612///     let u64x2(w3, w2) = K64X2[2*t + 1] + work[2*t + 1];
613///
614///     // this is the core expression
615///     dh = sha512rnd(ae, bf, cg, dh, w0);
616///     cg = sha512rnd(dh, ae, bf, cg, w1);
617///     bf = sha512rnd(cg, dh, ae, bf, w2);
618///     ae = sha512rnd(bf, cg, dh, ae, w3);
619///
620///     *state = [ae.0, bf.0, cg.0, dh.0,
621///               ae.1, bf.1, cg.1, dh.1];
622/// }
623/// ```
624///
625/// instead of 4 rounds of:
626///
627/// ```ignore
628/// fn round(state: &mut [u64; 8], w: &mut [u64], t: usize) {
629///     let [a, b, c, mut d, e, f, g, mut h]: [u64; 8] = *state;
630///
631///     h += big_sigma1!(e) +   choose!(e, f, g) + K64[t] + w[t]; d += h;
632///     h += big_sigma0!(a) + majority!(a, b, c);
633///
634///     *state = [h, a, b, c, d, e, f, g];
635/// }
636/// ```
637///
638pub fn sha512_digest_block(state: &mut [u64; 8], block: &[u8/*; 128*/]) {
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// A structure that represents that state of a digest computation for the SHA-2 512 family
646// of digest functions
647#[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
668/// Constants necessary for SHA-512 family of digests.
669pub 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
692/// Constants necessary for SHA-512 family of digests.
693pub 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// A structure that keeps track of the state of the Sha-512 operation and contains the logic
707// necessary to perform the final calculations.
708#[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        // Assumes that input.len() can be converted to u64 without overflow
736        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/// The SHA-512 hash algorithm with the SHA-512 initial hash value.
762#[derive(Copy, Clone)]
763pub struct Sha512 {
764    engine: Engine512
765}
766
767impl Sha512 {
768    /**
769     * Construct an new instance of a SHA-512 digest.
770     */
771    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/// The SHA-512 hash algorithm with the SHA-384 initial hash value. The result is truncated to 384 bits.
818#[derive(Copy, Clone)]
819pub struct Sha384 {
820    engine: Engine512
821}
822
823impl Sha384 {
824    /**
825     * Construct an new instance of a SHA-384 digest.
826     */
827    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/// The SHA-512 hash algorithm with the SHA-512/256 initial hash value. The result is truncated to 256 bits.
872#[derive(Clone, Copy)]
873pub struct Sha512Trunc256 {
874    engine: Engine512
875}
876
877impl Sha512Trunc256 {
878    /**
879     * Construct an new instance of a SHA-512/256 digest.
880     */
881    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/// The SHA-512 hash algorithm with the SHA-512/224 initial hash value. The result is truncated to 224 bits.
924#[derive(Clone, Copy)]
925pub struct Sha512Trunc224 {
926    engine: Engine512
927}
928
929impl Sha512Trunc224 {
930    /**
931     * Construct an new instance of a SHA-512/224 digest.
932     */
933    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// A structure that represents that state of a digest computation for the SHA-2 512 family of digest
976// functions
977#[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
998/// Constants necessary for SHA-256 family of digests.
999pub 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
1018/// Constants necessary for SHA-256 family of digests.
1019pub 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// A structure that keeps track of the state of the Sha-256 operation and contains the logic
1039// necessary to perform the final calculations.
1040#[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        // Assumes that input.len() can be converted to u64 without overflow
1068        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/// The SHA-256 hash algorithm with the SHA-256 initial hash value.
1090#[derive(Clone, Copy)]
1091pub struct Sha256 {
1092    engine: Engine256
1093}
1094
1095impl Sha256 {
1096    /**
1097     * Construct an new instance of a SHA-256 digest.
1098     */
1099    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/// The SHA-256 hash algorithm with the SHA-224 initial hash value. The result is truncated to 224 bits.
1146#[derive(Clone, Copy)]
1147pub struct Sha224 {
1148    engine: Engine256
1149}
1150
1151impl Sha224 {
1152    /**
1153     * Construct an new instance of a SHA-224 digest.
1154     */
1155    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        // Test that it works when accepting the message all at once
1212        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        // Test that it works when accepting the message in pieces
1222        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        // Examples from wikipedia
1241        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        // Examples from wikipedia
1266        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        // Examples from wikipedia
1291        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        // Examples from wikipedia
1316        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        // Examples from wikipedia
1341        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        // Examples from wikipedia
1366        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}