1 | // Copyright 2015-2016 Brian Smith. |
2 | // Copyright 2016 Simon Sapin. |
3 | // |
4 | // Permission to use, copy, modify, and/or distribute this software for any |
5 | // purpose with or without fee is hereby granted, provided that the above |
6 | // copyright notice and this permission notice appear in all copies. |
7 | // |
8 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
9 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
11 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
13 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
14 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | |
16 | use super::sha2::{ch, maj, Word}; |
17 | use crate::c; |
18 | use core::num::Wrapping; |
19 | |
20 | pub const BLOCK_LEN: usize = 512 / 8; |
21 | pub const CHAINING_LEN: usize = 160 / 8; |
22 | pub const OUTPUT_LEN: usize = 160 / 8; |
23 | const CHAINING_WORDS: usize = CHAINING_LEN / 4; |
24 | |
25 | type W32 = Wrapping<u32>; |
26 | |
27 | // FIPS 180-4 4.1.1 |
28 | #[inline ] |
29 | fn parity(x: W32, y: W32, z: W32) -> W32 { |
30 | x ^ y ^ z |
31 | } |
32 | |
33 | type State = [W32; CHAINING_WORDS]; |
34 | const ROUNDS: usize = 80; |
35 | |
36 | pub(super) extern "C" fn block_data_order( |
37 | state: &mut super::State, |
38 | data: *const u8, |
39 | num: c::size_t, |
40 | ) { |
41 | let state: &mut [Wrapping; 8] = unsafe { &mut state.as32 }; |
42 | let state: &mut State = (&mut state[..CHAINING_WORDS]).try_into().unwrap(); |
43 | let data: *const [[u8; 4]; 16] = data.cast::<[<W32 as Word>::InputBytes; 16]>(); |
44 | let blocks: &[[[u8; 4]; 16]] = unsafe { core::slice::from_raw_parts(data, len:num) }; |
45 | *state = block_data_order_(*state, M:blocks) |
46 | } |
47 | |
48 | #[inline ] |
49 | #[rustfmt::skip] |
50 | fn block_data_order_(mut H: State, M: &[[<W32 as Word>::InputBytes; 16]]) -> State { |
51 | for M in M { |
52 | // FIPS 180-4 6.1.2 Step 1 |
53 | let mut W: [W32; ROUNDS] = [W32::ZERO; ROUNDS]; |
54 | for t in 0..16 { |
55 | W[t] = W32::from_be_bytes(M[t]); |
56 | } |
57 | for t in 16..ROUNDS { |
58 | let wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; |
59 | W[t] = rotl(wt, 1); |
60 | } |
61 | |
62 | // FIPS 180-4 6.1.2 Step 2 |
63 | let [a, b, c, d, e] = H; |
64 | |
65 | // FIPS 180-4 6.1.2 Step 3 with constants and functions from FIPS 180-4 {4.1.1, 4.2.1} |
66 | let (a, b, c, d, e) = step3(a, b, c, d, e, &W, 0, Wrapping(0x5a827999), ch); |
67 | let (a, b, c, d, e) = step3(a, b, c, d, e, &W, 20, Wrapping(0x6ed9eba1), parity); |
68 | let (a, b, c, d, e) = step3(a, b, c, d, e, &W, 40, Wrapping(0x8f1bbcdc), maj); |
69 | let (a, b, c, d, e) = step3(a, b, c, d, e, &W, 60, Wrapping(0xca62c1d6), parity); |
70 | |
71 | // FIPS 180-4 6.1.2 Step 4 |
72 | H[0] += a; |
73 | H[1] += b; |
74 | H[2] += c; |
75 | H[3] += d; |
76 | H[4] += e; |
77 | } |
78 | |
79 | H |
80 | } |
81 | |
82 | #[inline (always)] |
83 | fn step3( |
84 | mut a: W32, |
85 | mut b: W32, |
86 | mut c: W32, |
87 | mut d: W32, |
88 | mut e: W32, |
89 | W: &[W32; 80], |
90 | t: usize, |
91 | k: W32, |
92 | f: impl Fn(W32, W32, W32) -> W32, |
93 | ) -> (W32, W32, W32, W32, W32) { |
94 | let W: &[Wrapping] = &W[t..(t + 20)]; |
95 | for W_t: &Wrapping in W.iter() { |
96 | let T: Wrapping = rotl(x:a, n:5) + f(b, c, d) + e + k + W_t; |
97 | e = d; |
98 | d = c; |
99 | c = rotl(x:b, n:30); |
100 | b = a; |
101 | a = T; |
102 | } |
103 | (a, b, c, d, e) |
104 | } |
105 | |
106 | #[inline (always)] |
107 | fn rotl(x: W32, n: u32) -> W32 { |
108 | Wrapping(x.0.rotate_left(n)) |
109 | } |
110 | |