• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use crate::c;
16 use core::{
17     num::Wrapping,
18     ops::{Add, AddAssign, BitAnd, BitOr, BitXor, Not, Shr},
19 };
20 
21 #[cfg(not(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64")))]
GFp_sha256_block_data_order( state: &mut super::State, data: *const u8, num: c::size_t, )22 pub(super) extern "C" fn GFp_sha256_block_data_order(
23     state: &mut super::State,
24     data: *const u8,
25     num: c::size_t,
26 ) {
27     let state = unsafe { &mut state.as32 };
28     *state = block_data_order(*state, data, num)
29 }
30 
31 #[cfg(not(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64")))]
GFp_sha512_block_data_order( state: &mut super::State, data: *const u8, num: c::size_t, )32 pub(super) extern "C" fn GFp_sha512_block_data_order(
33     state: &mut super::State,
34     data: *const u8,
35     num: c::size_t,
36 ) {
37     let state = unsafe { &mut state.as64 };
38     *state = block_data_order(*state, data, num)
39 }
40 
41 #[cfg_attr(
42     any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64"),
43     allow(dead_code)
44 )]
45 #[inline]
block_data_order<S: Sha2>( mut H: [S; CHAINING_WORDS], M: *const u8, num: c::size_t, ) -> [S; CHAINING_WORDS]46 fn block_data_order<S: Sha2>(
47     mut H: [S; CHAINING_WORDS],
48     M: *const u8,
49     num: c::size_t,
50 ) -> [S; CHAINING_WORDS] {
51     let M = M as *const [S::InputBytes; 16];
52     let M: &[[S::InputBytes; 16]] = unsafe { core::slice::from_raw_parts(M, num) };
53 
54     for M in M {
55         // FIPS 180-4 {6.2.2, 6.4.2} Step 1
56         //
57         // TODO: Use `let W: [S::ZERO; S::ROUNDS]` instead of allocating
58         // `MAX_ROUNDS` items and then slicing to `K.len()`; depends on
59         // https://github.com/rust-lang/rust/issues/43408.
60         let mut W = [S::ZERO; MAX_ROUNDS];
61         let W: &[S] = {
62             let W = &mut W[..S::K.len()];
63             for (W, M) in W.iter_mut().zip(M) {
64                 *W = S::from_be_bytes(*M);
65             }
66             for t in M.len()..S::K.len() {
67                 W[t] = sigma_1(W[t - 2]) + W[t - 7] + sigma_0(W[t - 15]) + W[t - 16]
68             }
69 
70             W
71         };
72 
73         // FIPS 180-4 {6.2.2, 6.4.2} Step 2
74         let mut a = H[0];
75         let mut b = H[1];
76         let mut c = H[2];
77         let mut d = H[3];
78         let mut e = H[4];
79         let mut f = H[5];
80         let mut g = H[6];
81         let mut h = H[7];
82 
83         // FIPS 180-4 {6.2.2, 6.4.2} Step 3
84         for (Kt, Wt) in S::K.iter().zip(W.iter()) {
85             let T1 = h + SIGMA_1(e) + ch(e, f, g) + *Kt + *Wt;
86             let T2 = SIGMA_0(a) + maj(a, b, c);
87             h = g;
88             g = f;
89             f = e;
90             e = d + T1;
91             d = c;
92             c = b;
93             b = a;
94             a = T1 + T2;
95         }
96 
97         // FIPS 180-4 {6.2.2, 6.4.2} Step 4
98         H[0] += a;
99         H[1] += b;
100         H[2] += c;
101         H[3] += d;
102         H[4] += e;
103         H[5] += f;
104         H[6] += g;
105         H[7] += h;
106     }
107 
108     H
109 }
110 
111 // FIPS 180-4 {4.1.1, 4.1.2, 4.1.3}
112 #[inline(always)]
ch<W: Word>(x: W, y: W, z: W) -> W113 pub(super) fn ch<W: Word>(x: W, y: W, z: W) -> W {
114     (x & y) | (!x & z)
115 }
116 
117 // FIPS 180-4 {4.1.1, 4.1.2, 4.1.3}
118 #[inline(always)]
maj<W: Word>(x: W, y: W, z: W) -> W119 pub(super) fn maj<W: Word>(x: W, y: W, z: W) -> W {
120     (x & y) | (x & z) | (y & z)
121 }
122 
123 // FIPS 180-4 {4.1.2, 4.1.3}
124 #[inline(always)]
SIGMA_0<S: Sha2>(x: S) -> S125 fn SIGMA_0<S: Sha2>(x: S) -> S {
126     x.rotr(S::BIG_SIGMA_0.0) ^ x.rotr(S::BIG_SIGMA_0.1) ^ x.rotr(S::BIG_SIGMA_0.2)
127 }
128 
129 // FIPS 180-4 {4.1.2, 4.1.3}
130 #[inline(always)]
SIGMA_1<S: Sha2>(x: S) -> S131 fn SIGMA_1<S: Sha2>(x: S) -> S {
132     x.rotr(S::BIG_SIGMA_1.0) ^ x.rotr(S::BIG_SIGMA_1.1) ^ x.rotr(S::BIG_SIGMA_1.2)
133 }
134 
135 // FIPS 180-4 {4.1.2, 4.1.3}
136 #[inline(always)]
sigma_0<S: Sha2>(x: S) -> S137 fn sigma_0<S: Sha2>(x: S) -> S {
138     x.rotr(S::SMALL_SIGMA_0.0) ^ x.rotr(S::SMALL_SIGMA_0.1) ^ (x >> S::SMALL_SIGMA_0.2)
139 }
140 
141 // FIPS 180-4 {4.1.2, 4.1.3}
142 #[inline(always)]
sigma_1<S: Sha2>(x: S) -> S143 fn sigma_1<S: Sha2>(x: S) -> S {
144     x.rotr(S::SMALL_SIGMA_1.0) ^ x.rotr(S::SMALL_SIGMA_1.1) ^ (x >> S::SMALL_SIGMA_1.2)
145 }
146 
147 // Commonality between SHA-1 and SHA-2 words.
148 pub(super) trait Word:
149     'static
150     + Sized
151     + Copy
152     + Add<Output = Self>
153     + AddAssign
154     + BitAnd<Output = Self>
155     + BitOr<Output = Self>
156     + Not<Output = Self>
157 {
158     const ZERO: Self;
159 
160     type InputBytes: Copy;
161 
from_be_bytes(input: Self::InputBytes) -> Self162     fn from_be_bytes(input: Self::InputBytes) -> Self;
163 
rotr(self, count: u32) -> Self164     fn rotr(self, count: u32) -> Self;
165 }
166 
167 /// A SHA-2 input word.
168 trait Sha2: Word + BitXor<Output = Self> + Shr<usize, Output = Self> {
169     const BIG_SIGMA_0: (u32, u32, u32);
170     const BIG_SIGMA_1: (u32, u32, u32);
171     const SMALL_SIGMA_0: (u32, u32, usize);
172     const SMALL_SIGMA_1: (u32, u32, usize);
173 
174     const K: &'static [Self];
175 }
176 
177 const MAX_ROUNDS: usize = 80;
178 pub(super) const CHAINING_WORDS: usize = 8;
179 
180 impl Word for Wrapping<u32> {
181     const ZERO: Self = Wrapping(0);
182     type InputBytes = [u8; 4];
183 
184     #[inline(always)]
from_be_bytes(input: Self::InputBytes) -> Self185     fn from_be_bytes(input: Self::InputBytes) -> Self {
186         Wrapping(u32::from_be_bytes(input))
187     }
188 
189     #[inline(always)]
rotr(self, count: u32) -> Self190     fn rotr(self, count: u32) -> Self {
191         Wrapping(self.0.rotate_right(count))
192     }
193 }
194 
195 // SHA-256
196 impl Sha2 for Wrapping<u32> {
197     // FIPS 180-4 4.1.2
198     const BIG_SIGMA_0: (u32, u32, u32) = (2, 13, 22);
199     const BIG_SIGMA_1: (u32, u32, u32) = (6, 11, 25);
200     const SMALL_SIGMA_0: (u32, u32, usize) = (7, 18, 3);
201     const SMALL_SIGMA_1: (u32, u32, usize) = (17, 19, 10);
202 
203     // FIPS 180-4 4.2.2
204     const K: &'static [Self] = &[
205         Self(0x428a2f98),
206         Self(0x71374491),
207         Self(0xb5c0fbcf),
208         Self(0xe9b5dba5),
209         Self(0x3956c25b),
210         Self(0x59f111f1),
211         Self(0x923f82a4),
212         Self(0xab1c5ed5),
213         Self(0xd807aa98),
214         Self(0x12835b01),
215         Self(0x243185be),
216         Self(0x550c7dc3),
217         Self(0x72be5d74),
218         Self(0x80deb1fe),
219         Self(0x9bdc06a7),
220         Self(0xc19bf174),
221         Self(0xe49b69c1),
222         Self(0xefbe4786),
223         Self(0x0fc19dc6),
224         Self(0x240ca1cc),
225         Self(0x2de92c6f),
226         Self(0x4a7484aa),
227         Self(0x5cb0a9dc),
228         Self(0x76f988da),
229         Self(0x983e5152),
230         Self(0xa831c66d),
231         Self(0xb00327c8),
232         Self(0xbf597fc7),
233         Self(0xc6e00bf3),
234         Self(0xd5a79147),
235         Self(0x06ca6351),
236         Self(0x14292967),
237         Self(0x27b70a85),
238         Self(0x2e1b2138),
239         Self(0x4d2c6dfc),
240         Self(0x53380d13),
241         Self(0x650a7354),
242         Self(0x766a0abb),
243         Self(0x81c2c92e),
244         Self(0x92722c85),
245         Self(0xa2bfe8a1),
246         Self(0xa81a664b),
247         Self(0xc24b8b70),
248         Self(0xc76c51a3),
249         Self(0xd192e819),
250         Self(0xd6990624),
251         Self(0xf40e3585),
252         Self(0x106aa070),
253         Self(0x19a4c116),
254         Self(0x1e376c08),
255         Self(0x2748774c),
256         Self(0x34b0bcb5),
257         Self(0x391c0cb3),
258         Self(0x4ed8aa4a),
259         Self(0x5b9cca4f),
260         Self(0x682e6ff3),
261         Self(0x748f82ee),
262         Self(0x78a5636f),
263         Self(0x84c87814),
264         Self(0x8cc70208),
265         Self(0x90befffa),
266         Self(0xa4506ceb),
267         Self(0xbef9a3f7),
268         Self(0xc67178f2),
269     ];
270 }
271 
272 impl Word for Wrapping<u64> {
273     const ZERO: Self = Wrapping(0);
274     type InputBytes = [u8; 8];
275 
276     #[inline(always)]
from_be_bytes(input: Self::InputBytes) -> Self277     fn from_be_bytes(input: Self::InputBytes) -> Self {
278         Wrapping(u64::from_be_bytes(input))
279     }
280 
281     #[inline(always)]
rotr(self, count: u32) -> Self282     fn rotr(self, count: u32) -> Self {
283         Wrapping(self.0.rotate_right(count))
284     }
285 }
286 
287 // SHA-384 and SHA-512
288 impl Sha2 for Wrapping<u64> {
289     // FIPS 180-4 4.1.3
290     const BIG_SIGMA_0: (u32, u32, u32) = (28, 34, 39);
291     const BIG_SIGMA_1: (u32, u32, u32) = (14, 18, 41);
292     const SMALL_SIGMA_0: (u32, u32, usize) = (1, 8, 7);
293     const SMALL_SIGMA_1: (u32, u32, usize) = (19, 61, 6);
294 
295     // FIPS 180-4 4.2.3
296     const K: &'static [Self] = &[
297         Self(0x428a2f98d728ae22),
298         Self(0x7137449123ef65cd),
299         Self(0xb5c0fbcfec4d3b2f),
300         Self(0xe9b5dba58189dbbc),
301         Self(0x3956c25bf348b538),
302         Self(0x59f111f1b605d019),
303         Self(0x923f82a4af194f9b),
304         Self(0xab1c5ed5da6d8118),
305         Self(0xd807aa98a3030242),
306         Self(0x12835b0145706fbe),
307         Self(0x243185be4ee4b28c),
308         Self(0x550c7dc3d5ffb4e2),
309         Self(0x72be5d74f27b896f),
310         Self(0x80deb1fe3b1696b1),
311         Self(0x9bdc06a725c71235),
312         Self(0xc19bf174cf692694),
313         Self(0xe49b69c19ef14ad2),
314         Self(0xefbe4786384f25e3),
315         Self(0x0fc19dc68b8cd5b5),
316         Self(0x240ca1cc77ac9c65),
317         Self(0x2de92c6f592b0275),
318         Self(0x4a7484aa6ea6e483),
319         Self(0x5cb0a9dcbd41fbd4),
320         Self(0x76f988da831153b5),
321         Self(0x983e5152ee66dfab),
322         Self(0xa831c66d2db43210),
323         Self(0xb00327c898fb213f),
324         Self(0xbf597fc7beef0ee4),
325         Self(0xc6e00bf33da88fc2),
326         Self(0xd5a79147930aa725),
327         Self(0x06ca6351e003826f),
328         Self(0x142929670a0e6e70),
329         Self(0x27b70a8546d22ffc),
330         Self(0x2e1b21385c26c926),
331         Self(0x4d2c6dfc5ac42aed),
332         Self(0x53380d139d95b3df),
333         Self(0x650a73548baf63de),
334         Self(0x766a0abb3c77b2a8),
335         Self(0x81c2c92e47edaee6),
336         Self(0x92722c851482353b),
337         Self(0xa2bfe8a14cf10364),
338         Self(0xa81a664bbc423001),
339         Self(0xc24b8b70d0f89791),
340         Self(0xc76c51a30654be30),
341         Self(0xd192e819d6ef5218),
342         Self(0xd69906245565a910),
343         Self(0xf40e35855771202a),
344         Self(0x106aa07032bbd1b8),
345         Self(0x19a4c116b8d2d0c8),
346         Self(0x1e376c085141ab53),
347         Self(0x2748774cdf8eeb99),
348         Self(0x34b0bcb5e19b48a8),
349         Self(0x391c0cb3c5c95a63),
350         Self(0x4ed8aa4ae3418acb),
351         Self(0x5b9cca4f7763e373),
352         Self(0x682e6ff3d6b2b8a3),
353         Self(0x748f82ee5defb2fc),
354         Self(0x78a5636f43172f60),
355         Self(0x84c87814a1f0ab72),
356         Self(0x8cc702081a6439ec),
357         Self(0x90befffa23631e28),
358         Self(0xa4506cebde82bde9),
359         Self(0xbef9a3f7b2c67915),
360         Self(0xc67178f2e372532b),
361         Self(0xca273eceea26619c),
362         Self(0xd186b8c721c0c207),
363         Self(0xeada7dd6cde0eb1e),
364         Self(0xf57d4f7fee6ed178),
365         Self(0x06f067aa72176fba),
366         Self(0x0a637dc5a2c898a6),
367         Self(0x113f9804bef90dae),
368         Self(0x1b710b35131c471b),
369         Self(0x28db77f523047d84),
370         Self(0x32caab7b40c72493),
371         Self(0x3c9ebe0a15c9bebc),
372         Self(0x431d67c49c100d4c),
373         Self(0x4cc5d4becb3e42b6),
374         Self(0x597f299cfc657e2a),
375         Self(0x5fcb6fab3ad6faec),
376         Self(0x6c44198c4a475817),
377     ];
378 }
379 
380 #[cfg(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64"))]
381 extern "C" {
GFp_sha256_block_data_order( state: &mut super::State, data: *const u8, num: c::size_t, )382     pub(super) fn GFp_sha256_block_data_order(
383         state: &mut super::State,
384         data: *const u8,
385         num: c::size_t,
386     );
GFp_sha512_block_data_order( state: &mut super::State, data: *const u8, num: c::size_t, )387     pub(super) fn GFp_sha512_block_data_order(
388         state: &mut super::State,
389         data: *const u8,
390         num: c::size_t,
391     );
392 }
393