#![no_std]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
pub use universal_hash;
use core::fmt::{self, Debug};
use universal_hash::{
KeyInit, UhfClosure, UniversalHash,
common::{BlockSizeUser, KeySizeUser},
consts::{U16, U32},
};
mod backend;
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(poly1305_backend = "soft"),
target_feature = "avx2", // Fuzz tests bypass AVX2 autodetection code
any(fuzzing, test)
))]
mod fuzz;
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(poly1305_backend = "soft")
))]
use crate::backend::autodetect::State;
#[cfg(not(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(poly1305_backend = "soft")
)))]
use crate::backend::soft::State;
pub const KEY_SIZE: usize = 32;
pub const BLOCK_SIZE: usize = 16;
pub type Key = universal_hash::Key<Poly1305>;
pub type Block = universal_hash::Block<Poly1305>;
pub type Tag = universal_hash::Block<Poly1305>;
#[derive(Clone)]
pub struct Poly1305 {
state: State,
}
impl KeySizeUser for Poly1305 {
type KeySize = U32;
}
impl KeyInit for Poly1305 {
fn new(key: &Key) -> Poly1305 {
Poly1305 {
state: State::new(key),
}
}
}
impl BlockSizeUser for Poly1305 {
type BlockSize = U16;
}
impl UniversalHash for Poly1305 {
fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
self.state.update_with_backend(f);
}
fn finalize(self) -> Tag {
self.state.finalize()
}
}
impl Poly1305 {
#[must_use]
pub fn compute_unpadded(mut self, data: &[u8]) -> Tag {
let (blocks, remaining) = Block::slice_as_chunks(data);
for block in blocks {
self.state.compute_block(block, false);
}
if !remaining.is_empty() {
let mut block = Block::default();
block[..remaining.len()].copy_from_slice(remaining);
block[remaining.len()] = 1;
self.state.compute_block(&block, true);
}
self.state.finalize()
}
}
impl Debug for Poly1305 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Poly1305").finish_non_exhaustive()
}
}
#[cfg(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(poly1305_backend = "soft"),
target_feature = "avx2", // Fuzz tests bypass AVX2 autodetection code
any(fuzzing, test)
))]
pub use crate::fuzz::fuzz_avx2;