aws_lc_rs/aead/
poly1305.rs
use super::{Tag, TAG_LEN};
use crate::aws_lc::{CRYPTO_poly1305_finish, CRYPTO_poly1305_init, CRYPTO_poly1305_update};
use crate::cipher::block::BLOCK_LEN;
use core::mem::MaybeUninit;
pub(super) struct Key {
pub(super) key_and_nonce: [u8; KEY_LEN],
}
const KEY_LEN: usize = 2 * BLOCK_LEN;
impl Key {
#[inline]
#[allow(dead_code)]
pub(super) fn new(key_and_nonce: [u8; KEY_LEN]) -> Self {
Self { key_and_nonce }
}
}
pub struct Context {
state: poly1305_state,
}
#[repr(C, align(64))]
#[allow(non_camel_case_types)]
struct poly1305_state(aws_lc::poly1305_state);
impl Context {
#[inline]
pub(super) fn from_key(Key { key_and_nonce }: Key) -> Self {
unsafe {
let mut state = MaybeUninit::<poly1305_state>::uninit();
CRYPTO_poly1305_init(state.as_mut_ptr().cast(), key_and_nonce.as_ptr());
Self {
state: state.assume_init(),
}
}
}
#[inline]
pub fn update(&mut self, input: &[u8]) {
unsafe {
CRYPTO_poly1305_update(
self.state.0.as_mut_ptr().cast(),
input.as_ptr(),
input.len(),
);
}
}
#[inline]
pub(super) fn finish(mut self) -> Tag {
unsafe {
let mut tag = MaybeUninit::<[u8; TAG_LEN]>::uninit();
CRYPTO_poly1305_finish(self.state.0.as_mut_ptr().cast(), tag.as_mut_ptr().cast());
crate::fips::set_fips_service_status_unapproved();
Tag(tag.assume_init(), TAG_LEN)
}
}
}
#[inline]
pub(super) fn sign(key: Key, input: &[u8]) -> Tag {
let mut ctx = Context::from_key(key);
ctx.update(input);
ctx.finish()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{test, test_file};
#[test]
pub fn test_poly1305() {
test::run(
test_file!("data/poly1305_test.txt"),
|section, test_case| {
assert_eq!(section, "");
let key = test_case.consume_bytes("Key");
let key: &[u8; BLOCK_LEN * 2] = key.as_slice().try_into().unwrap();
let input = test_case.consume_bytes("Input");
let expected_mac = test_case.consume_bytes("MAC");
let key = Key::new(*key);
let Tag(actual_mac, _) = sign(key, &input);
assert_eq!(expected_mac, actual_mac.as_ref());
Ok(())
},
);
}
}