1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
7)]
8
9#[cfg(feature = "hazmat")]
10pub mod hazmat;
11
12mod backend;
13mod field_element;
14
15pub use universal_hash;
16
17use crate::backend::State;
18use core::fmt::{self, Debug};
19use universal_hash::{
20 KeyInit, Reset, UhfBackend, UhfClosure, UniversalHash,
21 common::{BlockSizeUser, KeySizeUser, ParBlocksSizeUser},
22 consts::{U4, U16},
23};
24
25#[cfg(feature = "zeroize")]
26use zeroize::Zeroize;
27
28pub const BLOCK_SIZE: usize = 16;
30
31pub const KEY_SIZE: usize = 16;
33
34pub type Key = universal_hash::Key<Polyval>;
36
37pub type Block = universal_hash::Block<Polyval>;
39
40pub type ParBlocks = universal_hash::ParBlocks<Polyval>;
42
43pub type Tag = universal_hash::Block<Polyval>;
45
46#[derive(Clone)]
49pub struct Polyval {
50 state: State,
52}
53
54impl Polyval {
55 #[must_use]
57 pub fn new(h: &Key) -> Self {
58 Self {
59 state: State::new(h),
60 }
61 }
62}
63
64impl KeyInit for Polyval {
65 fn new(h: &Key) -> Self {
66 Self::new(h)
67 }
68}
69
70impl KeySizeUser for Polyval {
71 type KeySize = U16;
72}
73
74impl BlockSizeUser for Polyval {
75 type BlockSize = U16;
76}
77
78impl ParBlocksSizeUser for Polyval {
79 type ParBlocksSize = U4;
80}
81
82impl UniversalHash for Polyval {
83 fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
84 f.call(self);
85 }
86
87 fn finalize(self) -> Tag {
88 self.state.finalize()
89 }
90}
91
92impl UhfBackend for Polyval {
93 fn proc_block(&mut self, block: &Block) {
94 self.state.proc_block(block);
95 }
96
97 fn proc_par_blocks(&mut self, blocks: &ParBlocks) {
98 self.state.proc_par_blocks(blocks);
99 }
100}
101
102impl Reset for Polyval {
103 fn reset(&mut self) {
104 self.state.reset();
105 }
106}
107
108impl Debug for Polyval {
109 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
110 f.debug_struct("Polyval").finish_non_exhaustive()
111 }
112}
113
114impl Drop for Polyval {
115 fn drop(&mut self) {
116 #[cfg(feature = "zeroize")]
117 self.state.zeroize();
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use crate::{BLOCK_SIZE, Polyval, universal_hash::UniversalHash};
124 use hex_literal::hex;
125
126 const H: [u8; BLOCK_SIZE] = hex!("25629347589242761d31f826ba4b757b");
132 const X_1: [u8; BLOCK_SIZE] = hex!("4f4f95668c83dfb6401762bb2d01a262");
133 const X_2: [u8; BLOCK_SIZE] = hex!("d1a24ddd2721d006bbe45f20d3c9f362");
134
135 const POLYVAL_RESULT: [u8; BLOCK_SIZE] = hex!("f7a3b47b846119fae5b7866cf5e5b77e");
137
138 #[test]
139 fn polyval_test_vector() {
140 let mut poly = Polyval::new(&H.into());
141 poly.update(&[X_1.into(), X_2.into()]);
142
143 let result = poly.finalize();
144 assert_eq!(&POLYVAL_RESULT[..], result.as_slice());
145 }
146}