ring/aead/chacha/
ffi.rs

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 AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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
15use 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]`.
21macro_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.
46pub(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, output, len| {
61        assert!(len >= MIN_LEN);
62        let key = key.words_less_safe();
63        let _: Cpu = cpu;
64        unsafe { f(output, input, len, key, &counter) }
65    });
66}