• 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, polyfill::ChunksFixed};
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, 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 W: &[[W32; 20]; 4] = W.chunks_fixed();
67         let (a, b, c, d, e) = step3(a, b, c, d, e, W[0], Wrapping(0x5a827999), ch);
68         let (a, b, c, d, e) = step3(a, b, c, d, e, W[1], Wrapping(0x6ed9eba1), parity);
69         let (a, b, c, d, e) = step3(a, b, c, d, e, W[2], Wrapping(0x8f1bbcdc), maj);
70         let (a, b, c, d, e) = step3(a, b, c, d, e, W[3], Wrapping(0xca62c1d6), parity);
71 
72         // FIPS 180-4 6.1.2 Step 4
73         H[0] += a;
74         H[1] += b;
75         H[2] += c;
76         H[3] += d;
77         H[4] += e;
78     }
79 
80     H
81 }
82 
83 #[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)84 fn step3(
85     mut a: W32,
86     mut b: W32,
87     mut c: W32,
88     mut d: W32,
89     mut e: W32,
90     W: [W32; 20],
91     k: W32,
92     f: impl Fn(W32, W32, W32) -> W32,
93 ) -> (W32, W32, W32, W32, W32) {
94     for W_t in W.iter() {
95         let T = rotl(a, 5) + f(b, c, d) + e + k + W_t;
96         e = d;
97         d = c;
98         c = rotl(b, 30);
99         b = a;
100         a = T;
101     }
102     (a, b, c, d, e)
103 }
104 
105 #[inline(always)]
rotl(x: W32, n: u32) -> W32106 fn rotl(x: W32, n: u32) -> W32 {
107     Wrapping(x.0.rotate_left(n))
108 }
109