1use super::sha2::{ch, maj, Word};
17use crate::c;
18use core::{convert::TryInto, num::Wrapping};
19
20pub const BLOCK_LEN: usize = 512 / 8;
21pub const CHAINING_LEN: usize = 160 / 8;
22pub const OUTPUT_LEN: usize = 160 / 8;
23const CHAINING_WORDS: usize = CHAINING_LEN / 4;
24
25type W32 = Wrapping<u32>;
26
27#[inline]
29fn parity(x: W32, y: W32, z: W32) -> W32 {
30 x ^ y ^ z
31}
32
33type State = [W32; CHAINING_WORDS];
34const ROUNDS: usize = 80;
35
36pub(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 = unsafe { &mut state.as32 };
42 let state: &mut State = (&mut state[..CHAINING_WORDS]).try_into().unwrap();
43 let data = data as *const [<W32 as Word>::InputBytes; 16];
44 let blocks = unsafe { core::slice::from_raw_parts(data, num) };
45 *state = block_data_order_(*state, blocks)
46}
47
48#[inline]
49#[rustfmt::skip]
50fn block_data_order_(mut H: State, M: &[[<W32 as Word>::InputBytes; 16]]) -> State {
51 for M in M {
52 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 let a = H[0];
64 let b = H[1];
65 let c = H[2];
66 let d = H[3];
67 let e = H[4];
68
69 let (a, b, c, d, e) = step3(a, b, c, d, e, W[ 0..20].try_into().unwrap(), Wrapping(0x5a827999), ch);
71 let (a, b, c, d, e) = step3(a, b, c, d, e, W[20..40].try_into().unwrap(), Wrapping(0x6ed9eba1), parity);
72 let (a, b, c, d, e) = step3(a, b, c, d, e, W[40..60].try_into().unwrap(), Wrapping(0x8f1bbcdc), maj);
73 let (a, b, c, d, e) = step3(a, b, c, d, e, W[60..80].try_into().unwrap(), Wrapping(0xca62c1d6), parity);
74
75 H[0] += a;
77 H[1] += b;
78 H[2] += c;
79 H[3] += d;
80 H[4] += e;
81 }
82
83 H
84}
85
86#[inline(always)]
87fn step3(
88 mut a: W32,
89 mut b: W32,
90 mut c: W32,
91 mut d: W32,
92 mut e: W32,
93 W: [W32; 20],
94 k: W32,
95 f: impl Fn(W32, W32, W32) -> W32,
96) -> (W32, W32, W32, W32, W32) {
97 for W_t in W.iter() {
98 let T = rotl(a, 5) + f(b, c, d) + e + k + W_t;
99 e = d;
100 d = c;
101 c = rotl(b, 30);
102 b = a;
103 a = T;
104 }
105 (a, b, c, d, e)
106}
107
108#[inline(always)]
109fn rotl(x: W32, n: u32) -> W32 {
110 Wrapping(x.0.rotate_left(n))
111}