1use crate::{
2 backend::{Big, Small, POLYVAL},
3 impl_hash, impl_state,
4};
5
6impl_state!(PolyvalState, LE);
7
8#[cfg(feature = "experimental")]
9type State = PolyvalState;
10
11impl_hash! {
12 pub struct Polyval(Big<POLYVAL>);
29}
30
31impl_hash! {
32 pub struct PolyvalLite(Small<POLYVAL>);
38}
39
40#[cfg(test)]
41mod tests {
42 use serde::Deserialize;
43
44 use super::*;
45 use crate::{as_blocks, KEY_SIZE};
46
47 macro_rules! hex {
48 ($($s:literal)*) => {{
49 const LEN: usize = hex_literal::hex!($($s)*).len();
50 const OUTPUT: [u8; LEN] = hex_literal::hex!($($s)*);
51 &OUTPUT
52 }};
53 }
54
55 #[test]
56 fn test_rfc_vectors() {
57 type TestCase = (&'static [u8; KEY_SIZE], &'static [u8], &'static [u8; 16]);
58 let cases: &[TestCase] = &[
59 (
60 hex!("25629347589242761d31f826ba4b757b"),
61 hex!("4f4f95668c83dfb6401762bb2d01a262"),
62 hex!("cedac64537ff50989c16011551086d77"),
63 ),
64 (
65 hex!("25629347589242761d31f826ba4b757b"),
66 hex!(
67 "4f4f95668c83dfb6401762bb2d01a262"
68 "d1a24ddd2721d006bbe45f20d3c9f362"
69 ),
70 hex!("f7a3b47b846119fae5b7866cf5e5b77e"),
71 ),
72 (
73 hex!("d9b360279694941ac5dbc6987ada7377"),
74 hex!("00000000000000000000000000000000"),
75 hex!("00000000000000000000000000000000"),
76 ),
77 (
78 hex!("d9b360279694941ac5dbc6987ada7377"),
79 hex!("01000000000000000000000000000000"
80 "000000000000000040"),
81 hex!("eb93b7740962c5e49d2a90a7dc5cec74"),
82 ),
83 (
84 hex!("d9b360279694941ac5dbc6987ada7377"),
85 hex!("01000000000000000000000000000000"
86 "000000000000000060"),
87 hex!("48eb6c6c5a2dbe4a1dde508fee06361b"),
88 ),
89 (
90 hex!("d9b360279694941ac5dbc6987ada7377"),
91 hex!("01000000000000000000000000000000"
92 "000000000000000080"),
93 hex!("20806c26e3c1de019e111255708031d6"),
94 ),
95 (
96 hex!("d9b360279694941ac5dbc6987ada7377"),
97 hex!(
98 "01000000000000000000000000000000"
99 "02000000000000000000000000000000"
100 "00000000000000000001"
101 ),
102 hex!("ce6edc9a50b36d9a98986bbf6a261c3b"),
103 ),
104 (
105 hex!("0533fd71f4119257361a3ff1469dd4e5"),
106 hex!(
107 "489c8fde2be2cf97e74e932d4ed87d00"
108 "c9882e5386fd9f92ec00000000000000"
109 "780000000000000048"
110 ),
111 hex!("bf160bc9ded8c63057d2c38aae552fb4"),
112 ),
113 (
114 hex!("64779ab10ee8a280272f14cc8851b727"),
115 hex!(
116 "0da55210cc1c1b0abde3b2f204d1e9f8"
117 "b06bc47f000000000000000000000000"
118 "1db2316fd568378da107b52b00000000"
119 "a00000000000000060"
120 ),
121 hex!("cc86ee22c861e1fd474c84676b42739c"),
122 ),
123 (
124 hex!("27c2959ed4daea3b1f52e849478de376"),
125 hex!(
126 "f37de21c7ff901cfe8a69615a93fdf7a"
127 "98cad481796245709f00000000000000"
128 "21702de0de18baa9c9596291b0846600"
129 "c80000000000000078"
130 ),
131 hex!("c4fa5e5b713853703bcf8e6424505fa5"),
132 ),
133 (
134 hex!("670b98154076ddb59b7a9137d0dcc0f0"),
135 hex!(
136 "9c2159058b1f0fe91433a5bdc20e214e"
137 "ab7fecef4454a10ef0657df21ac70000"
138 "b202b370ef9768ec6561c4fe6b7e7296"
139 "fa850000000000000000000000000000"
140 "f00000000000000090"
141 ),
142 hex!("4e4108f09f41d797dc9256f8da8d58c7"),
143 ),
144 (
145 hex!("cb8c3aa3f8dbaeb4b28a3e86ff6625f8"),
146 hex!(
147 "734320ccc9d9bbbb19cb81b2af4ecbc3"
148 "e72834321f7aa0f70b7282b4f33df23f"
149 "16754100000000000000000000000000"
150 "ced532ce4159b035277d4dfbb7db6296"
151 "8b13cd4eec0000000000000000000000"
152 "1801000000000000a8"
153 ),
154 hex!("ffd503c7dd712eb3791b7114b17bb0cf"),
155 ),
156 ];
157
158 for (i, &(h, x, r)) in cases.iter().enumerate() {
159 let mut p = Polyval::new_unchecked(h);
160 p.update_padded(x);
161 assert_eq!(&p.tag().0, r, "#{i} (precomp)");
162
163 let mut p = PolyvalLite::new_unchecked(h);
164 p.update_padded(x);
165 assert_eq!(&p.tag().0, r, "#{i} (lite)");
166 }
167 }
168
169 #[test]
170 fn test_vectors() {
171 #[derive(Deserialize)]
172 #[allow(dead_code)]
173 struct Lengths {
174 block: usize,
175 key: usize,
176 nonce: usize,
177 }
178
179 #[derive(Deserialize)]
180 #[allow(dead_code)]
181 struct BlockCipher {
182 cipher: String,
183 lengths: Lengths,
184 }
185
186 #[derive(Deserialize)]
187 #[allow(dead_code)]
188 struct Input {
189 #[serde(with = "hex::serde")]
190 key_hex: Vec<u8>,
191 #[serde(default, with = "hex::serde")]
192 tweak_hex: Vec<u8>,
193 #[serde(with = "hex::serde")]
194 message_hex: Vec<u8>,
195 #[serde(default, with = "hex::serde")]
196 nonce_hex: Vec<u8>,
197 }
198
199 #[derive(Deserialize)]
200 #[allow(dead_code)]
201 struct Cipher {
202 cipher: String,
203 block_cipher: Option<BlockCipher>,
204 }
205
206 #[derive(Deserialize)]
207 #[allow(dead_code)]
208 struct TestVector {
209 cipher: Cipher,
210 description: String,
211 input: Input,
212 #[serde(default, with = "hex::serde")]
213 plaintext_hex: Vec<u8>,
214 #[serde(default, with = "hex::serde")]
215 ciphertext_hex: Vec<u8>,
216 #[serde(with = "hex::serde")]
217 hash_hex: Vec<u8>,
218 }
219
220 const DATA: &str = include_str!("testdata/polyval.json");
221 let tests: Vec<TestVector> = serde_json::from_str(DATA).expect("should be valid JSON");
222 for (i, tc) in tests.iter().enumerate() {
223 let h: [u8; KEY_SIZE] = (&*tc.input.key_hex).try_into().unwrap_or_else(|_| {
224 panic!(
225 "#{i}: {} should be `BLOCK_SIZE` all non-zero bytes",
226 tc.description
227 )
228 });
229 let mut p = Polyval::new_unchecked(&h);
230 let (blocks, []) = as_blocks(&tc.input.message_hex) else {
231 panic!("#{i}: {} should block sized", tc.description);
232 };
233 p.update_blocks(blocks);
234 let got: [u8; 16] = p.clone().tag().into();
235 let want = &tc.hash_hex[..];
236 assert_eq!(got, want, "#{i}: (precomp) {}", tc.description);
237
238 let mut p = PolyvalLite::new_unchecked(&h);
239 let (blocks, []) = as_blocks(&tc.input.message_hex) else {
240 panic!("#{i}: {} should block sized", tc.description);
241 };
242 p.update_blocks(blocks);
243 let got: [u8; 16] = p.clone().tag().into();
244 let want = &tc.hash_hex[..];
245 assert_eq!(got, want, "#{i}: (lite) {}", tc.description);
246 }
247 }
248}