1#![allow(deprecated)]
2#[allow(deprecated)]
21use aes::cipher::{Array, BlockCipherDecrypt, KeyInit};
22use aes::{Aes128, Aes256};
23use polyval::{Polyval, universal_hash::UniversalHash};
24use sha2::{Digest, Sha256};
25
26use crate::common::{BLOCK_LENGTH, Direction, Error, absorb, elk, xor_blocks, xor_blocks_3};
27use crate::hctr2::AesCipher;
28
29#[allow(non_camel_case_types)]
31#[deprecated(note = "Use common::Error instead")]
32pub type Hctr3Error = Error;
33
34pub struct Hctr3<Aes: AesCipher> {
36 ks_enc: Aes,
37 ks_dec: Aes::Dec,
38 ke_enc: Aes,
39 h: [u8; BLOCK_LENGTH],
40 l: [u8; BLOCK_LENGTH],
41}
42
43#[allow(non_camel_case_types)]
45pub type Hctr3_128 = Hctr3<Aes128>;
46
47#[allow(non_camel_case_types)]
49pub type Hctr3_256 = Hctr3<Aes256>;
50
51impl<Aes: AesCipher> Hctr3<Aes> {
52 pub const KEY_LENGTH: usize = Aes::KEY_LEN;
54
55 pub const BLOCK_LENGTH: usize = BLOCK_LENGTH;
57
58 pub const MIN_INPUT_LENGTH: usize = BLOCK_LENGTH;
60
61 pub fn new(key: &[u8]) -> Self {
65 debug_assert_eq!(key.len(), Aes::KEY_LEN);
66
67 let ks_enc = Aes::new(Array::from_slice(key));
68 let ks_dec = Aes::new_dec(key);
69
70 let ke_key: Vec<u8> = if Aes::KEY_LEN <= 16 {
71 let mut ke_block = Array::clone_from_slice(&[0u8; 16]);
72 ks_enc.encrypt_block(&mut ke_block);
73 ke_block[..Aes::KEY_LEN].to_vec()
74 } else {
75 let mut ke_block0 = Array::clone_from_slice(&[0u8; 16]);
76 let mut ke_block1 = Array::clone_from_slice(&[0x01u8; 16]);
77 ks_enc.encrypt_block(&mut ke_block0);
78 ks_enc.encrypt_block(&mut ke_block1);
79 let mut ke = vec![0u8; Aes::KEY_LEN];
80 ke[..16].copy_from_slice(ke_block0.as_slice());
81 ke[16..].copy_from_slice(&ke_block1.as_slice()[..(Aes::KEY_LEN - 16)]);
82 ke
83 };
84
85 let ke_enc = Aes::new(Array::from_slice(&ke_key));
86
87 let mut h_block = Array::clone_from_slice(&[0u8; 16]);
88 let mut l_block = Array::clone_from_slice(&{
89 let mut b = [0u8; 16];
90 b[15] = 1;
91 b
92 });
93 ke_enc.encrypt_block(&mut h_block);
94 ke_enc.encrypt_block(&mut l_block);
95
96 let h: [u8; 16] = h_block.as_slice().try_into().unwrap();
97 let l: [u8; 16] = l_block.as_slice().try_into().unwrap();
98 Self {
99 ks_enc,
100 ks_dec,
101 ke_enc,
102 h,
103 l,
104 }
105 }
106
107 pub fn encrypt(
109 &self,
110 plaintext: &[u8],
111 tweak: &[u8],
112 ciphertext: &mut [u8],
113 ) -> Result<(), Error> {
114 self.hctr3(plaintext, tweak, ciphertext, Direction::Encrypt)
115 }
116
117 pub fn decrypt(
119 &self,
120 ciphertext: &[u8],
121 tweak: &[u8],
122 plaintext: &mut [u8],
123 ) -> Result<(), Error> {
124 self.hctr3(ciphertext, tweak, plaintext, Direction::Decrypt)
125 }
126
127 fn hctr3(
128 &self,
129 src: &[u8],
130 tweak: &[u8],
131 dst: &mut [u8],
132 direction: Direction,
133 ) -> Result<(), Error> {
134 debug_assert_eq!(dst.len(), src.len());
135 if src.len() < BLOCK_LENGTH {
136 return Err(Error::InputTooShort);
137 }
138
139 let m: [u8; BLOCK_LENGTH] = src[..BLOCK_LENGTH].try_into().unwrap();
140 let n = &src[BLOCK_LENGTH..];
141
142 let mut hasher = Sha256::new();
143 hasher.update(tweak);
144 let hash_out = hasher.finalize();
145 let t: [u8; BLOCK_LENGTH] = hash_out[..BLOCK_LENGTH].try_into().unwrap();
146
147 let tweak_len_bits = tweak.len() * 8;
148 let tweak_len_encoded: u128 = if n.len() % BLOCK_LENGTH == 0 {
149 (2 * tweak_len_bits + 2) as u128
150 } else {
151 (2 * tweak_len_bits + 3) as u128
152 };
153
154 let mut poly = Polyval::new(Array::from_slice(&self.h));
155 poly.update(&[Array::from(tweak_len_encoded.to_le_bytes())]);
156 poly.update(&[Array::from(t)]);
157 let poly_after_tweak = poly.clone();
158
159 let hh = absorb(&mut poly, n);
160 let mm = xor_blocks(&hh, &m);
161
162 let uu: [u8; BLOCK_LENGTH] = match direction {
163 Direction::Encrypt => {
164 let mut block = Array::clone_from_slice(&mm);
165 self.ks_enc.encrypt_block(&mut block);
166 block.as_slice().try_into().unwrap()
167 }
168 Direction::Decrypt => {
169 let mut block = Array::clone_from_slice(&mm);
170 self.ks_dec.decrypt_block(&mut block);
171 block.as_slice().try_into().unwrap()
172 }
173 };
174
175 let s = xor_blocks_3(&mm, &uu, &self.l);
176 let (u, v) = dst.split_at_mut(BLOCK_LENGTH);
177 elk(&self.ke_enc, v, n, &s);
178
179 let mut poly = poly_after_tweak;
180 let hh2 = absorb(&mut poly, v);
181 u.copy_from_slice(&xor_blocks(&uu, &hh2));
182
183 Ok(())
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use crate::common::lfsr_next_128;
191
192 #[test]
193 fn test_hctr3_128_roundtrip() {
194 let key = [0u8; 16];
195 let cipher = Hctr3_128::new(&key);
196
197 let plaintext = b"Hello, HCTR3 World!";
198 let mut ciphertext = vec![0u8; plaintext.len()];
199 let mut decrypted = vec![0u8; plaintext.len()];
200
201 let tweak = b"test tweak";
202
203 cipher.encrypt(plaintext, tweak, &mut ciphertext).unwrap();
204 cipher.decrypt(&ciphertext, tweak, &mut decrypted).unwrap();
205
206 assert_eq!(plaintext.as_slice(), decrypted.as_slice());
207 }
208
209 #[test]
210 fn test_hctr3_128_roundtrip_nonzero_key() {
211 let key = [
212 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
213 0x0f, 0x10,
214 ];
215 let cipher = Hctr3_128::new(&key);
216
217 let plaintext = b"Hello, HCTR3 World!";
218 let mut ciphertext = vec![0u8; plaintext.len()];
219 let mut decrypted = vec![0u8; plaintext.len()];
220
221 let tweak = b"test tweak";
222
223 cipher.encrypt(plaintext, tweak, &mut ciphertext).unwrap();
224 assert_ne!(plaintext.as_slice(), ciphertext.as_slice());
225
226 cipher.decrypt(&ciphertext, tweak, &mut decrypted).unwrap();
227 assert_eq!(plaintext.as_slice(), decrypted.as_slice());
228 }
229
230 #[test]
231 fn test_hctr3_128_minimum_length() {
232 let key = [0u8; 16];
233 let cipher = Hctr3_128::new(&key);
234
235 let plaintext = [0x42u8; 16];
236 let mut ciphertext = [0u8; 16];
237 let mut decrypted = [0u8; 16];
238
239 cipher.encrypt(&plaintext, b"", &mut ciphertext).unwrap();
240 cipher.decrypt(&ciphertext, b"", &mut decrypted).unwrap();
241
242 assert_eq!(plaintext, decrypted);
243 }
244
245 #[test]
246 fn test_hctr3_128_input_too_short() {
247 let key = [0u8; 16];
248 let cipher = Hctr3_128::new(&key);
249
250 let plaintext = [0x42u8; 15];
251 let mut ciphertext = [0u8; 15];
252
253 assert_eq!(
254 cipher.encrypt(&plaintext, b"", &mut ciphertext),
255 Err(Error::InputTooShort)
256 );
257 }
258
259 #[test]
260 fn test_hctr3_128_different_tweaks() {
261 let key = [0u8; 16];
262 let cipher = Hctr3_128::new(&key);
263
264 let plaintext = [0x42u8; 32];
265 let mut ciphertext1 = [0u8; 32];
266 let mut ciphertext2 = [0u8; 32];
267
268 cipher
269 .encrypt(&plaintext, b"tweak1", &mut ciphertext1)
270 .unwrap();
271 cipher
272 .encrypt(&plaintext, b"tweak2", &mut ciphertext2)
273 .unwrap();
274
275 assert_ne!(ciphertext1, ciphertext2);
276 }
277
278 #[test]
279 fn test_hctr3_128_large_message() {
280 let key = [0u8; 16];
281 let cipher = Hctr3_128::new(&key);
282
283 let plaintext = [0xABu8; 1024];
284 let mut ciphertext = [0u8; 1024];
285 let mut decrypted = [0u8; 1024];
286
287 cipher
288 .encrypt(&plaintext, b"large tweak", &mut ciphertext)
289 .unwrap();
290 cipher
291 .decrypt(&ciphertext, b"large tweak", &mut decrypted)
292 .unwrap();
293
294 assert_eq!(plaintext.as_slice(), decrypted.as_slice());
295 }
296
297 #[test]
298 fn test_hctr3_256_roundtrip() {
299 let key = [0u8; 32];
300 let cipher = Hctr3_256::new(&key);
301
302 let plaintext = b"Hello, HCTR3-256 World!";
303 let mut ciphertext = vec![0u8; plaintext.len()];
304 let mut decrypted = vec![0u8; plaintext.len()];
305
306 let tweak = b"test tweak 256";
307
308 cipher.encrypt(plaintext, tweak, &mut ciphertext).unwrap();
309 cipher.decrypt(&ciphertext, tweak, &mut decrypted).unwrap();
310
311 assert_eq!(plaintext.as_slice(), decrypted.as_slice());
312 }
313
314 #[test]
315 fn test_lfsr_128_produces_unique_states() {
316 let initial = [0x01u8; 16];
317 let mut state = initial;
318 let mut seen = std::collections::HashSet::new();
319 seen.insert(state);
320
321 for _ in 0..1000 {
322 state = lfsr_next_128(&state);
323 assert!(seen.insert(state), "LFSR produced duplicate state");
324 }
325 }
326}