| 1 | // Copyright 2016-2025 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::{super::overlapping::Overlapping, Counter, Key}; |
| 16 | |
| 17 | // `unsafe { (N, C, InOut) => f }` means that the function `f` is safe to call |
| 18 | // iff the in/out length is at least `N`, the CPU features `C` are available, |
| 19 | // and the input type is `InOut`. If `f` supports overlapping input/output then |
| 20 | // `InOut` should be `Overlapping<'_, u8>`; otherwise it should be `&mut [u8]`. |
| 21 | macro_rules! chacha20_ctr32_ffi { |
| 22 | ( unsafe { ($MIN_LEN:expr, $Cpu:ty, $InOut:ty) => $f:ident }, |
| 23 | $key:expr, $counter:expr, $in_out:expr, $cpu:expr ) => {{ |
| 24 | prefixed_extern! { |
| 25 | fn $f( |
| 26 | out: *mut u8, |
| 27 | in_: *const u8, |
| 28 | in_len: crate::c::size_t, |
| 29 | key: &[u32; 8], |
| 30 | counter: &crate::aead::chacha::Counter, |
| 31 | ); |
| 32 | } |
| 33 | // SAFETY: The user asserts that $f has the signature above and is safe |
| 34 | // to call if additionally we have a value of type `$Cpu` and an in/out |
| 35 | // value of the indicated type, which we do. |
| 36 | unsafe { |
| 37 | crate::aead::chacha::ffi::chacha20_ctr32_ffi::<$InOut, $Cpu, $MIN_LEN>( |
| 38 | $key, $counter, $in_out, $cpu, $f, |
| 39 | ) |
| 40 | } |
| 41 | }}; |
| 42 | } |
| 43 | |
| 44 | // Panics if `in_out.len() < MIN_LEN`. The caller should have guarded against |
| 45 | // that so that the assertion gets optimized away. |
| 46 | pub(super) unsafe fn chacha20_ctr32_ffi< |
| 47 | 'o, |
| 48 | InOut: 'o + Into<Overlapping<'o, u8>>, |
| 49 | Cpu, |
| 50 | const MIN_LEN: usize, |
| 51 | >( |
| 52 | key: &Key, |
| 53 | counter: Counter, |
| 54 | in_out: InOut, |
| 55 | cpu: Cpu, |
| 56 | f: unsafe extern "C" fn(*mut u8, *const u8, crate::c::size_t, &[u32; 8], &Counter), |
| 57 | ) { |
| 58 | assert!(MIN_LEN > 0); |
| 59 | let in_out: Overlapping<'_, u8> = in_out.into(); |
| 60 | in_out.with_input_output_len(|input: *const u8, output: *mut u8, len: usize| { |
| 61 | assert!(len >= MIN_LEN); |
| 62 | let key: &[u32; _] = key.words_less_safe(); |
| 63 | let _: Cpu = cpu; |
| 64 | unsafe { f(output, input, len, key, &counter) } |
| 65 | }); |
| 66 | } |
| 67 | |