#![allow(unsafe_code)]
use core::{arch::global_asm, mem};
use super::KEY_SIZE;
#[cfg(target_os = "macos")]
global_asm!(include_str!("asm/rscrypto_chacha20_poly1305_aarch64_apple_darwin.s"));
#[cfg(target_os = "linux")]
global_asm!(include_str!("asm/rscrypto_chacha20_poly1305_aarch64_linux.s"));
#[repr(C, align(16))]
#[derive(Clone, Copy)]
struct SealDataIn {
key: [u8; KEY_SIZE],
counter: u32,
nonce: [u8; 12],
extra_ciphertext: *const u8,
extra_ciphertext_len: usize,
}
#[repr(C)]
union SealData {
input: SealDataIn,
out: TagOut,
}
#[repr(C, align(16))]
#[derive(Clone, Copy)]
struct OpenDataIn {
key: [u8; KEY_SIZE],
counter: u32,
nonce: [u8; 12],
}
#[repr(C)]
union OpenData {
input: OpenDataIn,
out: TagOut,
}
#[repr(C, align(16))]
#[derive(Clone, Copy)]
struct TagOut {
tag: [u8; 16],
}
const _: () = assert!(mem::size_of::<OpenData>() == 48);
const _: () = assert!(mem::align_of::<OpenData>() == 16);
const _: () = assert!(mem::size_of::<SealData>() == 64);
const _: () = assert!(mem::align_of::<SealData>() == 16);
unsafe extern "C" {
#[cfg(target_os = "macos")]
fn rscrypto_chacha20_poly1305_seal_aarch64_apple_darwin(
out_ciphertext: *mut u8,
plaintext: *const u8,
plaintext_len: usize,
aad: *const u8,
aad_len: usize,
data: *mut SealData,
);
#[cfg(target_os = "linux")]
fn rscrypto_chacha20_poly1305_seal_aarch64(
out_ciphertext: *mut u8,
plaintext: *const u8,
plaintext_len: usize,
aad: *const u8,
aad_len: usize,
data: *mut SealData,
);
#[cfg(target_os = "macos")]
fn rscrypto_chacha20_poly1305_open_aarch64_apple_darwin(
out_plaintext: *mut u8,
ciphertext: *const u8,
plaintext_len: usize,
aad: *const u8,
aad_len: usize,
data: *mut OpenData,
);
#[cfg(target_os = "linux")]
fn rscrypto_chacha20_poly1305_open_aarch64(
out_plaintext: *mut u8,
ciphertext: *const u8,
plaintext_len: usize,
aad: *const u8,
aad_len: usize,
data: *mut OpenData,
);
}
#[inline]
pub(super) fn seal_in_place(key: &[u8; KEY_SIZE], nonce: &[u8; 12], aad: &[u8], buffer: &mut [u8]) -> [u8; 16] {
let extra_ciphertext = [0u8; 16];
let mut data = SealData {
input: SealDataIn {
key: *key,
counter: 0,
nonce: *nonce,
extra_ciphertext: extra_ciphertext.as_ptr(),
extra_ciphertext_len: 0,
},
};
unsafe {
#[cfg(target_os = "macos")]
rscrypto_chacha20_poly1305_seal_aarch64_apple_darwin(
buffer.as_mut_ptr(),
buffer.as_ptr(),
buffer.len(),
aad.as_ptr(),
aad.len(),
&mut data,
);
#[cfg(target_os = "linux")]
rscrypto_chacha20_poly1305_seal_aarch64(
buffer.as_mut_ptr(),
buffer.as_ptr(),
buffer.len(),
aad.as_ptr(),
aad.len(),
&mut data,
);
data.out.tag
}
}
#[inline]
pub(super) fn open_in_place(key: &[u8; KEY_SIZE], nonce: &[u8; 12], aad: &[u8], buffer: &mut [u8]) -> [u8; 16] {
let mut data = OpenData {
input: OpenDataIn {
key: *key,
counter: 0,
nonce: *nonce,
},
};
unsafe {
#[cfg(target_os = "macos")]
rscrypto_chacha20_poly1305_open_aarch64_apple_darwin(
buffer.as_mut_ptr(),
buffer.as_ptr(),
buffer.len(),
aad.as_ptr(),
aad.len(),
&mut data,
);
#[cfg(target_os = "linux")]
rscrypto_chacha20_poly1305_open_aarch64(
buffer.as_mut_ptr(),
buffer.as_ptr(),
buffer.len(),
aad.as_ptr(),
aad.len(),
&mut data,
);
data.out.tag
}
}