1 | // Copyright 2024 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 super::CHAINING_WORDS; |
16 | use crate::polyfill::slice::AsChunks; |
17 | use core::num::{NonZeroUsize, Wrapping}; |
18 | |
19 | /// `unsafe { T => f }` means it is safe to call `f` iff we can construct |
20 | /// a value of type `T`. |
21 | macro_rules! sha2_ffi { |
22 | ( $U:ty, $BLOCK_LEN:expr, unsafe { $Cpu:ty => $f:ident }, |
23 | $state:expr, $data:expr, $cpu:expr $(,)? ) => {{ |
24 | prefixed_extern! { |
25 | fn $f( |
26 | state: *mut [core::num::Wrapping<$U>; crate::digest::sha2::CHAINING_WORDS], |
27 | data: *const [u8; $BLOCK_LEN], |
28 | num: crate::c::NonZero_size_t); |
29 | } |
30 | // SAFETY: The user asserts that $f has the signature above and is safe |
31 | // to call if additionally we have a value of type `$Cpu`, which we do. |
32 | unsafe { |
33 | crate::digest::sha2::ffi::sha2_ffi::<$U, $Cpu, { $BLOCK_LEN }>($state, $data, $cpu, $f) |
34 | } |
35 | }}; |
36 | } |
37 | |
38 | macro_rules! sha2_32_ffi { |
39 | ( unsafe { $Cpu:ty => $f:ident }, $state:expr, $data:expr, $cpu:expr $(,)? ) => { |
40 | sha2_ffi!(u32, crate::digest::sha2::SHA256_BLOCK_LEN.into(), |
41 | unsafe { $Cpu => $f }, $state, $data, $cpu) |
42 | } |
43 | } |
44 | |
45 | macro_rules! sha2_64_ffi { |
46 | ( unsafe { $Cpu:ty => $f:ident }, $state:expr, $data:expr, $cpu:expr $(,)? ) => { |
47 | sha2_ffi!(u64, SHA512_BLOCK_LEN.into(), unsafe { $Cpu => $f }, $state, $data, $cpu) |
48 | } |
49 | } |
50 | |
51 | pub(super) unsafe fn sha2_ffi<U, Cpu, const BLOCK_LEN: usize>( |
52 | state: &mut [Wrapping<U>; CHAINING_WORDS], |
53 | data: AsChunks<u8, BLOCK_LEN>, |
54 | cpu: Cpu, |
55 | f: unsafe extern "C"fn( |
56 | *mut [Wrapping<U>; CHAINING_WORDS], |
57 | *const [u8; BLOCK_LEN], |
58 | crate::c::NonZero_size_t, |
59 | ), |
60 | ) { |
61 | if let Some(blocks: NonZero |
62 | let data: *const [u8; BLOCK_LEN] = data.as_ptr(); |
63 | let _: Cpu = cpu; |
64 | // SAFETY: |
65 | // * `blocks` is non-zero. |
66 | // * `data` is non-NULL and points to `blocks` blocks. |
67 | // * The caller asserted that `f` meets this contract if we have |
68 | // an instance of `Cpu`. |
69 | unsafe { f(state, data, blocks) } |
70 | } |
71 | } |
72 |