• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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