#![no_std]
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
#![warn(missing_docs, rust_2018_idioms)]
mod field;
pub use universal_hash;
use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash};
pub type Key = universal_hash::Key<Polyval>;
pub type Block = universal_hash::Block<Polyval>;
pub type Tag = universal_hash::Output<Polyval>;
#[allow(non_snake_case)]
#[derive(Clone)]
#[repr(align(16))]
pub struct Polyval {
H: field::Element,
S: field::Element,
}
impl NewUniversalHash for Polyval {
type KeySize = U16;
fn new(h: &Key) -> Self {
Self {
H: field::Element::from_bytes(h.clone().into()),
S: field::Element::default(),
}
}
}
impl UniversalHash for Polyval {
type BlockSize = U16;
fn update(&mut self, x: &Block) {
let x = field::Element::from_bytes(x.clone().into());
self.S = (self.S + x) * self.H;
}
fn update_padded(&mut self, data: &[u8]) {
let mut chunks = data.chunks_exact(16);
for chunk in &mut chunks {
self.update(Block::from_slice(chunk));
}
let rem = chunks.remainder();
if !rem.is_empty() {
let mut padded_block = Block::default();
padded_block[..rem.len()].copy_from_slice(rem);
self.update(&padded_block);
}
}
fn reset(&mut self) {
self.S = field::Element::default();
}
fn finalize(self) -> Tag {
Output::new(self.S.to_bytes().into())
}
}