use crate::core::poly1305::{ poly1305_init, poly1305_update, poly1305_finish };
use crypto_api::{
mac::{ MacInfo, Mac },
rng::{ SecureRng, SecKeyGen }
};
use std::error::Error;
pub const POLY1305_KEY: usize = 32;
pub const POLY1305_TAG: usize = 16;
pub struct Poly1305;
impl Poly1305 {
pub fn mac() -> Box<dyn Mac> {
Box::new(Self)
}
pub(in crate) fn chachapoly_auth(tag: &mut[u8], ad: &[u8], data: &[u8], foot: &[u8], key: &[u8]) {
let (mut r, mut s, mut u, mut a) = (vec![0; 5], vec![0; 4], vec![0; 5], vec![0; 5]);
poly1305_init(&mut r, &mut s, &mut u, key);
poly1305_update(&mut a, &r, &u, ad, false);
poly1305_update(&mut a, &r, &u, data, false);
poly1305_update(&mut a, &r, &u, foot, true);
poly1305_finish(tag, &mut a, &mut s);
}
}
impl SecKeyGen for Poly1305 {
fn new_sec_key(&self, buf: &mut[u8], rng: &mut dyn SecureRng) -> Result<usize, Box<dyn Error + 'static>> {
vfy_keygen!(POLY1305_KEY => buf);
rng.random(&mut buf[..POLY1305_KEY])?;
Ok(POLY1305_KEY)
}
}
impl Mac for Poly1305 {
fn info(&self) -> MacInfo {
MacInfo {
name: "Poly1305", is_otm: true,
mac_len: POLY1305_TAG,
mac_len_r: POLY1305_TAG..(POLY1305_TAG + 1),
key_len_r: POLY1305_KEY..(POLY1305_KEY + 1)
}
}
fn auth(&self, buf: &mut[u8], data: &[u8], key: &[u8]) -> Result<usize, Box<dyn Error + 'static>> {
vfy_auth!(key => [POLY1305_KEY], => [buf, POLY1305_TAG]);
let (mut r, mut s, mut u, mut a) = (vec![0; 5], vec![0; 4], vec![0; 5], vec![0; 5]);
poly1305_init(&mut r, &mut s, &mut u, key);
poly1305_update(&mut a, &r, &u, data, true);
poly1305_finish(buf, &mut a, &s);
Ok(POLY1305_TAG)
}
}