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::{convert::TryInto, 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]
parity(x: W32, y: W32, z: W32) -> W3229 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
block_data_order( state: &mut super::State, data: *const u8, num: c::size_t, )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 = 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]
block_data_order_(mut H: State, M: &[[<W32 as Word>::InputBytes; 16]]) -> State50 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 = H[0];
64 let b = H[1];
65 let c = H[2];
66 let d = H[3];
67 let e = H[4];
68
69 // FIPS 180-4 6.1.2 Step 3 with constants and functions from FIPS 180-4 {4.1.1, 4.2.1}
70 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 // FIPS 180-4 6.1.2 Step 4
76 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)]
step3( mut a: W32, mut b: W32, mut c: W32, mut d: W32, mut e: W32, W: [W32; 20], k: W32, f: impl Fn(W32, W32, W32) -> W32, ) -> (W32, W32, W32, W32, W32)87 fn 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)]
rotl(x: W32, n: u32) -> W32109 fn rotl(x: W32, n: u32) -> W32 {
110 Wrapping(x.0.rotate_left(n))
111 }
112