use crate::low::chacha20::ChaCha20;
use crate::low::poly1305::Poly1305;
pub(crate) fn seal(key: &[u8; 32], nonce: &[u8; 12], aad: &[u8], inout: &mut [u8]) -> [u8; 16] {
cipher(key, nonce, aad, inout, true)
}
#[cfg(any(target_arch = "arm", target_arch = "x86_64"))]
pub(crate) fn open(key: &[u8; 32], nonce: &[u8; 12], aad: &[u8], inout: &mut [u8]) -> [u8; 16] {
cipher(key, nonce, aad, inout, false)
}
fn cipher(key: &[u8; 32], nonce: &[u8; 12], aad: &[u8], inout: &mut [u8], seal: bool) -> [u8; 16] {
let mut counter_nonce = [0u8; 16];
counter_nonce[4..].copy_from_slice(nonce);
let mut chacha = ChaCha20::new(key, &counter_nonce);
let mut poly_key = [0u8; 32];
chacha.cipher(&mut poly_key);
let mut poly = Poly1305::new(&poly_key);
let pad = |poly: &mut Poly1305, len: usize| poly.add_bytes(&[0u8; 16][..(16 - len % 16) % 16]);
poly.add_bytes(aad);
pad(&mut poly, aad.len());
if seal {
chacha.cipher(inout);
poly.add_bytes(inout);
} else {
poly.add_bytes(inout);
chacha.cipher(inout);
}
pad(&mut poly, inout.len());
poly.add_bytes(&(aad.len() as u64).to_le_bytes());
poly.add_bytes(&(inout.len() as u64).to_le_bytes());
poly.finish()
}