1#[rustfmt::skip]
8const SR: [u8; 256] = [
9 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
10 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
11 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
12 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
13 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
14 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
15 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
16 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
17 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
18 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
19 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
20 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
21 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
22 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
23 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
24 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
25];
26
27#[rustfmt::skip]
28const SQ: [u8; 256] = [
29 0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB,
30 0xE4, 0x8E, 0x48, 0x49, 0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2,
31 0xD8, 0xE9, 0xCC, 0xED, 0x40, 0x2F, 0x11, 0x28, 0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, 0x1B, 0xB9,
32 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, 0x07, 0x4B, 0x0E, 0xC1, 0x51, 0xAA, 0x89, 0xD4,
33 0xCA, 0x01, 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, 0x9F, 0x20, 0x4C, 0x64,
34 0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, 0xF4,
35 0x8D, 0xB0, 0xE5, 0x93, 0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA,
36 0xBC, 0x0F, 0x08, 0x52, 0x1D, 0x55, 0x1A, 0xC5, 0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, 0x5B, 0x5A,
37 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, 0x7E, 0x0D, 0xFC, 0x50, 0x8A, 0xB6, 0x62, 0xF5, 0x0A, 0xF8, 0xDC,
38 0x03, 0x3C, 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, 0xF2, 0xD5, 0x97, 0x66, 0x81, 0x32, 0xA0, 0x00,
39 0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, 0xF7, 0x8C, 0x79, 0xD6, 0xA7, 0xBF, 0x8B, 0x3F, 0x1F, 0x53,
40 0x63, 0x75, 0x35, 0x2C, 0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, 0x7C, 0xA1, 0x05, 0x58, 0x2D, 0xBD,
41 0xD9, 0xC7, 0xAF, 0x6B, 0x54, 0x0B, 0xE0, 0x38, 0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C,
42 0xDF, 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26, 0x61, 0x76, 0x34, 0x2B,
43 0xAD, 0x99, 0xFB, 0x72, 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A,
44 0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86,
45];
46
47const SR_ANF: [[u128; 2]; 8] = crate::ct::build_byte_sbox_anf(&SR);
48const SQ_ANF: [[u128; 2]; 8] = crate::ct::build_byte_sbox_anf(&SQ);
49
50const MUL_ALPHA: [u32; 256] = build_alpha_table([23, 245, 48, 239]);
54const DIV_ALPHA: [u32; 256] = build_alpha_table([16, 39, 6, 64]);
55const MUL_ALPHA_FACTORS: [u8; 4] = alpha_factors([23, 245, 48, 239]);
56const DIV_ALPHA_FACTORS: [u8; 4] = alpha_factors([16, 39, 6, 64]);
57
58#[inline]
59fn load_be_u32(bytes: &[u8]) -> u32 {
60 let mut word = [0u8; 4];
61 word.copy_from_slice(bytes);
62 u32::from_be_bytes(word)
63}
64
65#[inline]
66const fn mulx(v: u8, c: u8) -> u8 {
67 if (v & 0x80) != 0 {
68 (v << 1) ^ c
69 } else {
70 v << 1
71 }
72}
73
74#[inline]
75fn mulx_ct(v: u8, c: u8) -> u8 {
76 let hi = 0u8.wrapping_sub(v >> 7);
77 (v << 1) ^ (c & hi)
78}
79
80#[inline]
81const fn mulx_pow(mut v: u8, i: u8, c: u8) -> u8 {
82 let mut n = 0;
83 while n < i {
84 v = mulx(v, c);
85 n += 1;
86 }
87 v
88}
89
90const fn build_alpha_table(pows: [u8; 4]) -> [u32; 256] {
91 let mut table = [0u32; 256];
92 let mut i = 0;
93 while i < 256 {
94 let c = i as u8;
95 table[i] = u32::from_be_bytes([
96 mulx_pow(c, pows[0], 0xA9),
97 mulx_pow(c, pows[1], 0xA9),
98 mulx_pow(c, pows[2], 0xA9),
99 mulx_pow(c, pows[3], 0xA9),
100 ]);
101 i += 1;
102 }
103 table
104}
105
106const fn alpha_factors(pows: [u8; 4]) -> [u8; 4] {
107 [
108 mulx_pow(1, pows[0], 0xA9),
109 mulx_pow(1, pows[1], 0xA9),
110 mulx_pow(1, pows[2], 0xA9),
111 mulx_pow(1, pows[3], 0xA9),
112 ]
113}
114
115#[inline]
116fn gf_mul_const_ct(mut value: u8, mut factor: u8, poly: u8) -> u8 {
117 let mut out = 0u8;
118 let mut i = 0u8;
119 while i < 8 {
120 let bit_mask = 0u8.wrapping_sub(factor & 1);
121 out ^= value & bit_mask;
122 value = mulx_ct(value, poly);
123 factor >>= 1;
124 i = i.wrapping_add(1);
125 }
126 out
127}
128
129#[inline]
130fn alpha_word_ct(input: u8, factors: [u8; 4]) -> u32 {
131 u32::from_be_bytes([
132 gf_mul_const_ct(input, factors[0], 0xA9),
133 gf_mul_const_ct(input, factors[1], 0xA9),
134 gf_mul_const_ct(input, factors[2], 0xA9),
135 gf_mul_const_ct(input, factors[3], 0xA9),
136 ])
137}
138
139#[inline]
140fn sbox_eval(coeffs: &[[u128; 2]; 8], input: u8) -> u8 {
141 crate::ct::eval_byte_sbox(coeffs, input)
142}
143
144#[inline]
145fn s1<const CT: bool>(w: u32) -> u32 {
146 let (srw0, srw1, srw2, srw3) = if CT {
147 (
148 sbox_eval(&SR_ANF, (w >> 24) as u8),
149 sbox_eval(&SR_ANF, ((w >> 16) & 0xFF) as u8),
150 sbox_eval(&SR_ANF, ((w >> 8) & 0xFF) as u8),
151 sbox_eval(&SR_ANF, (w & 0xFF) as u8),
152 )
153 } else {
154 (
155 SR[(w >> 24) as usize],
156 SR[((w >> 16) & 0xFF) as usize],
157 SR[((w >> 8) & 0xFF) as usize],
158 SR[(w & 0xFF) as usize],
159 )
160 };
161 let mul = if CT { mulx_ct } else { mulx };
162 let r0 = mul(srw0, 0x1B) ^ srw1 ^ srw2 ^ mul(srw3, 0x1B) ^ srw3;
163 let r1 = mul(srw0, 0x1B) ^ srw0 ^ mul(srw1, 0x1B) ^ srw2 ^ srw3;
164 let r2 = srw0 ^ mul(srw1, 0x1B) ^ srw1 ^ mul(srw2, 0x1B) ^ srw3;
165 let r3 = srw0 ^ srw1 ^ mul(srw2, 0x1B) ^ srw2 ^ mul(srw3, 0x1B);
166 u32::from_be_bytes([r0, r1, r2, r3])
167}
168
169#[inline]
170fn s2<const CT: bool>(w: u32) -> u32 {
171 let (sqw0, sqw1, sqw2, sqw3) = if CT {
172 (
173 sbox_eval(&SQ_ANF, (w >> 24) as u8),
174 sbox_eval(&SQ_ANF, ((w >> 16) & 0xFF) as u8),
175 sbox_eval(&SQ_ANF, ((w >> 8) & 0xFF) as u8),
176 sbox_eval(&SQ_ANF, (w & 0xFF) as u8),
177 )
178 } else {
179 (
180 SQ[(w >> 24) as usize],
181 SQ[((w >> 16) & 0xFF) as usize],
182 SQ[((w >> 8) & 0xFF) as usize],
183 SQ[(w & 0xFF) as usize],
184 )
185 };
186 let mul = if CT { mulx_ct } else { mulx };
187 let r0 = mul(sqw0, 0x69) ^ sqw1 ^ sqw2 ^ mul(sqw3, 0x69) ^ sqw3;
188 let r1 = mul(sqw0, 0x69) ^ sqw0 ^ mul(sqw1, 0x69) ^ sqw2 ^ sqw3;
189 let r2 = sqw0 ^ mul(sqw1, 0x69) ^ sqw1 ^ mul(sqw2, 0x69) ^ sqw3;
190 let r3 = sqw0 ^ sqw1 ^ mul(sqw2, 0x69) ^ sqw2 ^ mul(sqw3, 0x69);
191 u32::from_be_bytes([r0, r1, r2, r3])
192}
193
194struct Snow3gCore {
195 s: [u32; 16],
196 r1: u32,
197 r2: u32,
198 r3: u32,
199}
200
201#[inline]
202fn clock_fsm<const CT: bool>(core: &mut Snow3gCore) -> u32 {
203 let f = core.s[15].wrapping_add(core.r1) ^ core.r2;
204 let r = core.r2.wrapping_add(core.r3 ^ core.s[5]);
205 core.r3 = s2::<CT>(core.r2);
206 core.r2 = s1::<CT>(core.r1);
207 core.r1 = r;
208 f
209}
210
211#[inline]
212fn lfsr_feedback<const CT: bool>(core: &Snow3gCore) -> u32 {
213 let mul_alpha = if CT {
214 alpha_word_ct((core.s[0] >> 24) as u8, MUL_ALPHA_FACTORS)
215 } else {
216 MUL_ALPHA[(core.s[0] >> 24) as usize]
217 };
218 let div_alpha = if CT {
219 alpha_word_ct((core.s[11] & 0xFF) as u8, DIV_ALPHA_FACTORS)
220 } else {
221 DIV_ALPHA[(core.s[11] & 0xFF) as usize]
222 };
223 ((core.s[0] << 8) & 0xFFFF_FF00)
224 ^ mul_alpha
225 ^ core.s[2]
226 ^ ((core.s[11] >> 8) & 0x00FF_FFFF)
227 ^ div_alpha
228}
229
230#[inline]
231fn clock_lfsr<const CT: bool>(core: &mut Snow3gCore, f: Option<u32>) {
232 let mut v = lfsr_feedback::<CT>(core);
233 if let Some(fsm_word) = f {
234 v ^= fsm_word;
235 }
236 core.s.copy_within(1..16, 0);
237 core.s[15] = v;
238}
239
240fn init_core<const CT: bool>(key: &[u8; 16], iv: &[u8; 16]) -> Snow3gCore {
241 let k = [
242 load_be_u32(&key[0..4]),
243 load_be_u32(&key[4..8]),
244 load_be_u32(&key[8..12]),
245 load_be_u32(&key[12..16]),
246 ];
247 let iv = [
248 load_be_u32(&iv[0..4]),
249 load_be_u32(&iv[4..8]),
250 load_be_u32(&iv[8..12]),
251 load_be_u32(&iv[12..16]),
252 ];
253
254 let mut core = Snow3gCore {
255 s: [
256 k[0] ^ 0xFFFF_FFFF,
257 k[1] ^ 0xFFFF_FFFF,
258 k[2] ^ 0xFFFF_FFFF,
259 k[3] ^ 0xFFFF_FFFF,
260 k[0],
261 k[1],
262 k[2],
263 k[3],
264 k[0] ^ 0xFFFF_FFFF,
265 k[1] ^ 0xFFFF_FFFF ^ iv[3],
266 k[2] ^ 0xFFFF_FFFF ^ iv[2],
267 k[3] ^ 0xFFFF_FFFF,
268 k[0] ^ iv[1],
269 k[1],
270 k[2],
271 k[3] ^ iv[0],
272 ],
273 r1: 0,
274 r2: 0,
275 r3: 0,
276 };
277
278 for _ in 0..32 {
279 let f = clock_fsm::<CT>(&mut core);
280 clock_lfsr::<CT>(&mut core, Some(f));
281 }
282
283 let _ = clock_fsm::<CT>(&mut core);
284 clock_lfsr::<CT>(&mut core, None);
285 core
286}
287
288#[inline]
289fn next_word_core<const CT: bool>(core: &mut Snow3gCore) -> u32 {
290 let z = clock_fsm::<CT>(core) ^ core.s[0];
291 clock_lfsr::<CT>(core, None);
292 z
293}
294
295fn fill_core<const CT: bool>(core: &mut Snow3gCore, buf: &mut [u8]) {
296 let mut chunks = buf.chunks_exact_mut(4);
297 for chunk in &mut chunks {
298 let ks = next_word_core::<CT>(core).to_be_bytes();
299 for (b, k) in chunk.iter_mut().zip(ks.iter()) {
300 *b ^= k;
301 }
302 }
303 let rem = chunks.into_remainder();
304 if !rem.is_empty() {
305 let ks = next_word_core::<CT>(core).to_be_bytes();
306 for (b, k) in rem.iter_mut().zip(ks.iter()) {
307 *b ^= k;
308 }
309 }
310}
311
312pub struct Snow3g {
314 core: Snow3gCore,
315}
316
317pub struct Snow3gCt {
323 core: Snow3gCore,
324}
325
326impl Snow3g {
327 #[must_use]
329 pub fn new(key: &[u8; 16], iv: &[u8; 16]) -> Self {
330 Self {
331 core: init_core::<false>(key, iv),
332 }
333 }
334
335 pub fn new_wiping(key: &mut [u8; 16], iv: &mut [u8; 16]) -> Self {
337 let out = Self::new(key, iv);
338 crate::ct::zeroize_slice(key.as_mut_slice());
339 crate::ct::zeroize_slice(iv.as_mut_slice());
340 out
341 }
342
343 pub fn next_word(&mut self) -> u32 {
345 next_word_core::<false>(&mut self.core)
346 }
347
348 pub fn fill(&mut self, buf: &mut [u8]) {
350 fill_core::<false>(&mut self.core, buf);
351 }
352}
353
354impl Snow3gCt {
355 #[must_use]
357 pub fn new(key: &[u8; 16], iv: &[u8; 16]) -> Self {
358 Self {
359 core: init_core::<true>(key, iv),
360 }
361 }
362
363 pub fn new_wiping(key: &mut [u8; 16], iv: &mut [u8; 16]) -> Self {
365 let out = Self::new(key, iv);
366 crate::ct::zeroize_slice(key.as_mut_slice());
367 crate::ct::zeroize_slice(iv.as_mut_slice());
368 out
369 }
370
371 pub fn next_word(&mut self) -> u32 {
373 next_word_core::<true>(&mut self.core)
374 }
375
376 pub fn fill(&mut self, buf: &mut [u8]) {
378 fill_core::<true>(&mut self.core, buf);
379 }
380}
381
382impl Drop for Snow3g {
383 fn drop(&mut self) {
384 crate::ct::zeroize_slice(self.core.s.as_mut_slice());
385 self.core.r1 = 0;
386 self.core.r2 = 0;
387 self.core.r3 = 0;
388 }
389}
390
391impl Drop for Snow3gCt {
392 fn drop(&mut self) {
393 crate::ct::zeroize_slice(self.core.s.as_mut_slice());
394 self.core.r1 = 0;
395 self.core.r2 = 0;
396 self.core.r3 = 0;
397 }
398}
399
400#[cfg(test)]
401mod tests {
402 use super::*;
403
404 fn xorshift64(state: &mut u64) -> u64 {
405 let mut x = *state;
406 x ^= x << 13;
407 x ^= x >> 7;
408 x ^= x << 17;
409 *state = x;
410 x
411 }
412
413 fn fill_bytes(state: &mut u64, out: &mut [u8]) {
414 for chunk in out.chunks_mut(8) {
415 let bytes = xorshift64(state).to_le_bytes();
416 let n = chunk.len();
417 chunk.copy_from_slice(&bytes[..n]);
418 }
419 }
420
421 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
422 struct TraceRow {
423 s0: u32,
424 s2: u32,
425 s5: u32,
426 s11: u32,
427 s15: u32,
428 r1: u32,
429 r2: u32,
430 r3: u32,
431 }
432
433 fn trace_row(core: &Snow3gCore) -> TraceRow {
434 TraceRow {
435 s0: core.s[0],
436 s2: core.s[2],
437 s5: core.s[5],
438 s11: core.s[11],
439 s15: core.s[15],
440 r1: core.r1,
441 r2: core.r2,
442 r3: core.r3,
443 }
444 }
445
446 fn initial_lfsr_from_key_iv(key: &[u8; 16], iv: &[u8; 16]) -> [u32; 16] {
447 let k = [
448 load_be_u32(&key[0..4]),
449 load_be_u32(&key[4..8]),
450 load_be_u32(&key[8..12]),
451 load_be_u32(&key[12..16]),
452 ];
453 let iv = [
454 load_be_u32(&iv[0..4]),
455 load_be_u32(&iv[4..8]),
456 load_be_u32(&iv[8..12]),
457 load_be_u32(&iv[12..16]),
458 ];
459 [
460 k[0] ^ 0xFFFF_FFFF,
461 k[1] ^ 0xFFFF_FFFF,
462 k[2] ^ 0xFFFF_FFFF,
463 k[3] ^ 0xFFFF_FFFF,
464 k[0],
465 k[1],
466 k[2],
467 k[3],
468 k[0] ^ 0xFFFF_FFFF,
469 k[1] ^ 0xFFFF_FFFF ^ iv[3],
470 k[2] ^ 0xFFFF_FFFF ^ iv[2],
471 k[3] ^ 0xFFFF_FFFF,
472 k[0] ^ iv[1],
473 k[1],
474 k[2],
475 k[3] ^ iv[0],
476 ]
477 }
478
479 #[derive(Clone, Copy)]
480 struct OfficialTraceCase {
481 key: [u8; 16],
482 iv: [u8; 16],
483 initial_lfsr: [u32; 16],
484 init_rows: [TraceRow; 8],
485 final_lfsr: [u32; 16],
486 final_fsm: [u32; 3],
487 keystream_rows: [TraceRow; 3],
488 outputs: [u32; 2],
489 }
490
491 fn assert_official_trace<const CT: bool>(case: &OfficialTraceCase) {
492 assert_eq!(
493 initial_lfsr_from_key_iv(&case.key, &case.iv),
494 case.initial_lfsr
495 );
496
497 let mut core = Snow3gCore {
498 s: case.initial_lfsr,
499 r1: 0,
500 r2: 0,
501 r3: 0,
502 };
503
504 assert_eq!(trace_row(&core), case.init_rows[0], "initial row");
505 for (i, expected) in case.init_rows.iter().enumerate().skip(1) {
506 let f = clock_fsm::<CT>(&mut core);
507 clock_lfsr::<CT>(&mut core, Some(f));
508 assert_eq!(trace_row(&core), *expected, "init row {i}");
509 }
510
511 for _ in (case.init_rows.len() - 1)..32 {
512 let f = clock_fsm::<CT>(&mut core);
513 clock_lfsr::<CT>(&mut core, Some(f));
514 }
515
516 assert_eq!(core.s, case.final_lfsr, "final LFSR after init");
517 assert_eq!(
518 [core.r1, core.r2, core.r3],
519 case.final_fsm,
520 "final FSM after init"
521 );
522
523 let _ = clock_fsm::<CT>(&mut core);
524 clock_lfsr::<CT>(&mut core, None);
525 assert_eq!(trace_row(&core), case.keystream_rows[0], "keystream row 0");
526
527 let z1 = next_word_core::<CT>(&mut core);
528 assert_eq!(z1, case.outputs[0], "z1");
529 assert_eq!(trace_row(&core), case.keystream_rows[1], "keystream row 1");
530
531 let z2 = next_word_core::<CT>(&mut core);
532 assert_eq!(z2, case.outputs[1], "z2");
533 assert_eq!(trace_row(&core), case.keystream_rows[2], "keystream row 2");
534 }
535
536 fn assert_iterated_test_set_4<const CT: bool>() {
537 let key = [
538 0x0D, 0xED, 0x72, 0x63, 0x10, 0x9C, 0xF9, 0x2E, 0x33, 0x52, 0x25, 0x5A, 0x14, 0x0E,
539 0x0F, 0x76,
540 ];
541 let iv = [
542 0x6B, 0x68, 0x07, 0x9A, 0x41, 0xA7, 0xC4, 0xC9, 0x1B, 0xEF, 0xD7, 0x9F, 0x7F, 0xDC,
543 0xC2, 0x33,
544 ];
545
546 let mut core = init_core::<CT>(&key, &iv);
547 assert_eq!(next_word_core::<CT>(&mut core), 0xD712_C05C, "z1");
548 assert_eq!(next_word_core::<CT>(&mut core), 0xA937_C2A6, "z2");
549 assert_eq!(next_word_core::<CT>(&mut core), 0xEB7E_AAE3, "z3");
550 for _ in 0..2496 {
551 let _ = next_word_core::<CT>(&mut core);
552 }
553 assert_eq!(next_word_core::<CT>(&mut core), 0x9C0D_B3AA, "z2500");
554 }
555
556 #[test]
557 fn keystream_test_set_1() {
558 let key = [
559 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81,
560 0xFF, 0x48,
561 ];
562 let iv = [
563 0xEA, 0x02, 0x47, 0x14, 0xAD, 0x5C, 0x4D, 0x84, 0xDF, 0x1F, 0x9B, 0x25, 0x1C, 0x0B,
564 0xF4, 0x5F,
565 ];
566 let mut snow = Snow3g::new(&key, &iv);
567 assert_eq!(snow.next_word(), 0xABEE_9704);
568 assert_eq!(snow.next_word(), 0x7AC3_1373);
569 }
570
571 #[test]
572 fn keystream_test_set_2() {
573 let key = [
574 0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC, 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66,
575 0xB1, 0xF3,
576 ];
577 let iv = [
578 0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C, 0xDE, 0x55, 0x19, 0x88, 0xCE, 0xB2,
579 0xF9, 0xB7,
580 ];
581 let mut snow = Snow3g::new(&key, &iv);
582 assert_eq!(snow.next_word(), 0xEFF8_A342);
583 assert_eq!(snow.next_word(), 0xF751_480F);
584 }
585
586 #[test]
587 fn keystream_test_set_3() {
588 let key = [
589 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1, 0xA8, 0xFF, 0x86, 0x67, 0xB1, 0x71,
590 0x40, 0x13,
591 ];
592 let iv = [
593 0x62, 0xA5, 0x40, 0x98, 0x1B, 0xA6, 0xF9, 0xB7, 0x45, 0x92, 0xB0, 0xE7, 0x86, 0x90,
594 0xF7, 0x1B,
595 ];
596 let mut snow = Snow3g::new(&key, &iv);
597 assert_eq!(snow.next_word(), 0xA8C8_74A9);
598 assert_eq!(snow.next_word(), 0x7AE7_C4F8);
599 }
600
601 #[test]
602 fn keystream_test_set_1_ct() {
603 let key = [
604 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81,
605 0xFF, 0x48,
606 ];
607 let iv = [
608 0xEA, 0x02, 0x47, 0x14, 0xAD, 0x5C, 0x4D, 0x84, 0xDF, 0x1F, 0x9B, 0x25, 0x1C, 0x0B,
609 0xF4, 0x5F,
610 ];
611 let mut snow = Snow3gCt::new(&key, &iv);
612 assert_eq!(snow.next_word(), 0xABEE_9704);
613 assert_eq!(snow.next_word(), 0x7AC3_1373);
614 }
615
616 #[test]
617 fn keystream_test_set_2_ct() {
618 let key = [
619 0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC, 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66,
620 0xB1, 0xF3,
621 ];
622 let iv = [
623 0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C, 0xDE, 0x55, 0x19, 0x88, 0xCE, 0xB2,
624 0xF9, 0xB7,
625 ];
626 let mut snow = Snow3gCt::new(&key, &iv);
627 assert_eq!(snow.next_word(), 0xEFF8_A342);
628 assert_eq!(snow.next_word(), 0xF751_480F);
629 }
630
631 #[test]
632 fn keystream_test_set_3_ct() {
633 let key = [
634 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1, 0xA8, 0xFF, 0x86, 0x67, 0xB1, 0x71,
635 0x40, 0x13,
636 ];
637 let iv = [
638 0x62, 0xA5, 0x40, 0x98, 0x1B, 0xA6, 0xF9, 0xB7, 0x45, 0x92, 0xB0, 0xE7, 0x86, 0x90,
639 0xF7, 0x1B,
640 ];
641 let mut snow = Snow3gCt::new(&key, &iv);
642 assert_eq!(snow.next_word(), 0xA8C8_74A9);
643 assert_eq!(snow.next_word(), 0x7AE7_C4F8);
644 }
645
646 #[test]
647 fn fill_xor_roundtrip() {
648 let key = [0x12u8; 16];
649 let iv = [0x34u8; 16];
650 let plaintext = b"Hello, SNOW 3G!!";
651 let mut buf = *plaintext;
652 Snow3g::new(&key, &iv).fill(&mut buf);
653 Snow3g::new(&key, &iv).fill(&mut buf);
654 assert_eq!(&buf, plaintext);
655 }
656
657 #[test]
658 fn fill_partial_word() {
659 let key = [0xABu8; 16];
660 let iv = [0xCDu8; 16];
661 let mut buf7 = [0u8; 7];
662 let mut buf8 = [0u8; 8];
663 Snow3g::new(&key, &iv).fill(&mut buf7);
664 Snow3g::new(&key, &iv).fill(&mut buf8);
665 assert_eq!(buf7[..], buf8[..7]);
666 }
667
668 #[test]
669 fn fill_xor_roundtrip_ct() {
670 let key = [0x12u8; 16];
671 let iv = [0x34u8; 16];
672 let plaintext = b"Hello, SNOW 3G!!";
673 let mut buf = *plaintext;
674 Snow3gCt::new(&key, &iv).fill(&mut buf);
675 Snow3gCt::new(&key, &iv).fill(&mut buf);
676 assert_eq!(&buf, plaintext);
677 }
678
679 #[test]
680 fn fill_partial_word_ct() {
681 let key = [0xABu8; 16];
682 let iv = [0xCDu8; 16];
683 let mut buf7 = [0u8; 7];
684 let mut buf8 = [0u8; 8];
685 Snow3gCt::new(&key, &iv).fill(&mut buf7);
686 Snow3gCt::new(&key, &iv).fill(&mut buf8);
687 assert_eq!(buf7[..], buf8[..7]);
688 }
689
690 #[test]
691 fn ct_sboxes_match_tables() {
692 for x in 0u16..=255 {
693 let b = u8::try_from(x).expect("table index fits in u8");
694 assert_eq!(sbox_eval(&SR_ANF, b), SR[x as usize], "SR {x:02x}");
695 assert_eq!(sbox_eval(&SQ_ANF, b), SQ[x as usize], "SQ {x:02x}");
696 assert_eq!(
697 alpha_word_ct(b, MUL_ALPHA_FACTORS),
698 MUL_ALPHA[x as usize],
699 "MUL {x:02x}"
700 );
701 assert_eq!(
702 alpha_word_ct(b, DIV_ALPHA_FACTORS),
703 DIV_ALPHA[x as usize],
704 "DIV {x:02x}"
705 );
706 }
707 }
708
709 #[test]
710 fn snow3g_and_ct_match() {
711 let key = [0x12u8; 16];
712 let iv = [0x34u8; 16];
713 let mut fast = Snow3g::new(&key, &iv);
714 let mut slow = Snow3gCt::new(&key, &iv);
715 for _ in 0..4 {
716 assert_eq!(fast.next_word(), slow.next_word());
717 }
718 }
719
720 #[test]
721 fn snow3g_and_ct_match_random_streams() {
722 let mut seed = 0xfeed_face_cafe_beefu64;
723 for _ in 0..128 {
724 let mut key = [0u8; 16];
725 let mut iv = [0u8; 16];
726 fill_bytes(&mut seed, &mut key);
727 fill_bytes(&mut seed, &mut iv);
728 let len = (xorshift64(&mut seed) as usize % 2048) + 1;
729
730 let mut fast_buf = vec![0u8; len];
731 let mut ct_buf = vec![0u8; len];
732 fill_bytes(&mut seed, &mut fast_buf);
733 ct_buf.copy_from_slice(&fast_buf);
734
735 Snow3g::new(&key, &iv).fill(&mut fast_buf);
736 Snow3gCt::new(&key, &iv).fill(&mut ct_buf);
737 assert_eq!(fast_buf, ct_buf);
738 }
739 }
740
741 #[test]
742 fn official_test_set_1_trace_fast_and_ct() {
743 let key = [
744 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81,
745 0xFF, 0x48,
746 ];
747 let iv = [
748 0xEA, 0x02, 0x47, 0x14, 0xAD, 0x5C, 0x4D, 0x84, 0xDF, 0x1F, 0x9B, 0x25, 0x1C, 0x0B,
749 0xF4, 0x5F,
750 ];
751 let initial_lfsr = [
752 0xD429_BA60,
753 0x7D3A_4CFF,
754 0x6AD3_B6EF,
755 0xB77E_00B7,
756 0x2BD6_459F,
757 0x82C5_B300,
758 0x952C_4910,
759 0x4881_FF48,
760 0xD429_BA60,
761 0x6131_B8A0,
762 0xB5CC_2DCA,
763 0xB77E_00B7,
764 0x868A_081B,
765 0x82C5_B300,
766 0x952C_4910,
767 0xA283_B85C,
768 ];
769 let init_rows = [
770 TraceRow {
771 s0: 0xD429_BA60,
772 s2: 0x6AD3_B6EF,
773 s5: 0x82C5_B300,
774 s11: 0xB77E_00B7,
775 s15: 0xA283_B85C,
776 r1: 0x0000_0000,
777 r2: 0x0000_0000,
778 r3: 0x0000_0000,
779 },
780 TraceRow {
781 s0: 0x7D3A_4CFF,
782 s2: 0xB77E_00B7,
783 s5: 0x952C_4910,
784 s11: 0x868A_081B,
785 s15: 0x97DF_2884,
786 r1: 0x82C5_B300,
787 r2: 0x6363_6363,
788 r3: 0x2525_2525,
789 },
790 TraceRow {
791 s0: 0x6AD3_B6EF,
792 s2: 0x2BD6_459F,
793 s5: 0x4881_FF48,
794 s11: 0x82C5_B300,
795 s15: 0x311B_A301,
796 r1: 0x136C_CF98,
797 r2: 0x486C_5BC4,
798 r3: 0x9393_9393,
799 },
800 TraceRow {
801 s0: 0xB77E_00B7,
802 s2: 0x82C5_B300,
803 s5: 0xD429_BA60,
804 s11: 0x952C_4910,
805 s15: 0xA69F_CBCB,
806 r1: 0x237E_C89F,
807 r2: 0xEAEB_C424,
808 r3: 0x4B78_15EA,
809 },
810 TraceRow {
811 s0: 0x2BD6_459F,
812 s2: 0x952C_4910,
813 s5: 0x6131_B8A0,
814 s11: 0xA283_B85C,
815 s15: 0xE76F_0ADA,
816 r1: 0x8A3D_73AE,
817 r2: 0x21A4_385B,
818 r3: 0xE662_EC27,
819 },
820 TraceRow {
821 s0: 0x82C5_B300,
822 s2: 0x4881_FF48,
823 s5: 0xB5CC_2DCA,
824 s11: 0x97DF_2884,
825 s15: 0xA52D_CD12,
826 r1: 0xA8F7_8CE2,
827 r2: 0x63A7_F600,
828 r3: 0xBC3F_3A8D,
829 },
830 TraceRow {
831 s0: 0x952C_4910,
832 s2: 0xD429_BA60,
833 s5: 0xB77E_00B7,
834 s11: 0x311B_A301,
835 s15: 0x1A34_9A62,
836 r1: 0x6D9B_0D47,
837 r2: 0x2071_2A2D,
838 r3: 0x391D_0883,
839 },
840 TraceRow {
841 s0: 0x4881_FF48,
842 s2: 0x6131_B8A0,
843 s5: 0x868A_081B,
844 s11: 0xA69F_CBCB,
845 s15: 0x2A2A_44DB,
846 r1: 0xAED4_3261,
847 r2: 0x401B_1511,
848 r3: 0x45A6_ED60,
849 },
850 ];
851 let final_lfsr = [
852 0x8F12_15A6,
853 0xE003_A052,
854 0x9241_C929,
855 0x68D7_BF8C,
856 0x16BF_4C2A,
857 0x8DEF_9D70,
858 0x3238_1704,
859 0x11DD_346A,
860 0xE18B_81EA,
861 0x77EB_D4FE,
862 0x57ED_9505,
863 0x0C33_C0EF,
864 0x1A03_7B59,
865 0x9759_1E82,
866 0xA91C_CB44,
867 0x7B48_E04F,
868 ];
869 let final_fsm = [0x61DA_9249, 0x427D_F38C, 0x0FB6_B101];
870 let keystream_rows = [
871 TraceRow {
872 s0: 0xE003_A052,
873 s2: 0x68D7_BF8C,
874 s5: 0x3238_1704,
875 s11: 0x1A03_7B59,
876 s15: 0x1646_644C,
877 r1: 0xC4D7_1FFD,
878 r2: 0x90F0_B31F,
879 r3: 0xCC61_2008,
880 },
881 TraceRow {
882 s0: 0x9241_C929,
883 s2: 0x16BF_4C2A,
884 s5: 0x11DD_346A,
885 s11: 0x9759_1E82,
886 s15: 0x52E4_3190,
887 r1: 0x8F49_EA2B,
888 r2: 0x0AAC_C1E1,
889 r3: 0x3367_438C,
890 },
891 TraceRow {
892 s0: 0x68D7_BF8C,
893 s2: 0x8DEF_9D70,
894 s5: 0xE18B_81EA,
895 s11: 0xA91C_CB44,
896 s15: 0xB737_110E,
897 r1: 0x2D67_39C7,
898 r2: 0x5295_DA23,
899 r3: 0x5293_E49E,
900 },
901 ];
902 let outputs = [0xABEE_9704, 0x7AC3_1373];
903
904 let case = OfficialTraceCase {
905 key,
906 iv,
907 initial_lfsr,
908 init_rows,
909 final_lfsr,
910 final_fsm,
911 keystream_rows,
912 outputs,
913 };
914 assert_official_trace::<false>(&case);
915 assert_official_trace::<true>(&case);
916 }
917
918 #[test]
919 fn official_test_set_2_trace_fast_and_ct() {
920 let key = [
921 0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC, 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66,
922 0xB1, 0xF3,
923 ];
924 let iv = [
925 0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C, 0xDE, 0x55, 0x19, 0x88, 0xCE, 0xB2,
926 0xF9, 0xB7,
927 ];
928 let initial_lfsr = [
929 0x731C_C1D3,
930 0x3C3F_4A03,
931 0xE0C2_1759,
932 0x2399_4E0C,
933 0x8CE3_3E2C,
934 0xC3C0_B5FC,
935 0x1F3D_E8A6,
936 0xDC66_B1F3,
937 0x731C_C1D3,
938 0xF28D_B3B4,
939 0x3E97_0ED1,
940 0x2399_4E0C,
941 0xBE9C_8F30,
942 0xC3C0_B5FC,
943 0x1F3D_E8A6,
944 0x0FA3_6461,
945 ];
946 let init_rows = [
947 TraceRow {
948 s0: 0x731C_C1D3,
949 s2: 0xE0C2_1759,
950 s5: 0xC3C0_B5FC,
951 s11: 0x2399_4E0C,
952 s15: 0x0FA3_6461,
953 r1: 0x0000_0000,
954 r2: 0x0000_0000,
955 r3: 0x0000_0000,
956 },
957 TraceRow {
958 s0: 0x3C3F_4A03,
959 s2: 0x2399_4E0C,
960 s5: 0x1F3D_E8A6,
961 s11: 0xBE9C_8F30,
962 s15: 0xEF81_E474,
963 r1: 0xC3C0_B5FC,
964 r2: 0x6363_6363,
965 r3: 0x2525_2525,
966 },
967 TraceRow {
968 s0: 0xE0C2_1759,
969 s2: 0x8CE3_3E2C,
970 s5: 0xDC66_B1F3,
971 s11: 0xC3C0_B5FC,
972 s15: 0x7A55_4815,
973 r1: 0x9D7C_30E6,
974 r2: 0xF878_FA8B,
975 r3: 0x9393_9393,
976 },
977 TraceRow {
978 s0: 0x2399_4E0C,
979 s2: 0xC3C0_B5FC,
980 s5: 0x731C_C1D3,
981 s11: 0x1F3D_E8A6,
982 s15: 0x53E0_AE66,
983 r1: 0x486E_1CEB,
984 r2: 0x2148_E845,
985 r3: 0x098F_198B,
986 },
987 TraceRow {
988 s0: 0x8CE3_3E2C,
989 s2: 0x1F3D_E8A6,
990 s5: 0xF28D_B3B4,
991 s11: 0x0FA3_6461,
992 s15: 0x9A1E_E9B8,
993 r1: 0x9BDC_C09D,
994 r2: 0x87A6_22BB,
995 r3: 0xEFFA_4239,
996 },
997 TraceRow {
998 s0: 0xC3C0_B5FC,
999 s2: 0xDC66_B1F3,
1000 s5: 0x3E97_0ED1,
1001 s11: 0xEF81_E474,
1002 s15: 0x2390_FE04,
1003 r1: 0xA51E_1448,
1004 r2: 0xF6CF_B4FB,
1005 r3: 0x2087_DC1D,
1006 },
1007 TraceRow {
1008 s0: 0x1F3D_E8A6,
1009 s2: 0x731C_C1D3,
1010 s5: 0x2399_4E0C,
1011 s11: 0x7A55_4815,
1012 s15: 0x6FB8_C36C,
1013 r1: 0x14E0_87C7,
1014 r2: 0x7246_2DC5,
1015 r3: 0x0B8B_F471,
1016 },
1017 TraceRow {
1018 s0: 0xDC66_B1F3,
1019 s2: 0xF28D_B3B4,
1020 s5: 0xBE9C_8F30,
1021 s11: 0x53E0_AE66,
1022 s15: 0xBA5D_B98F,
1023 r1: 0x9A58_E842,
1024 r2: 0x481D_2AB5,
1025 r3: 0x5C8E_E565,
1026 },
1027 ];
1028 let final_lfsr = [
1029 0x04D6_A929,
1030 0x942E_1440,
1031 0x82AB_D3FE,
1032 0x5832_E9F4,
1033 0x5F97_02A0,
1034 0x0871_2C81,
1035 0x644C_C9B9,
1036 0xDBF6_DE13,
1037 0xBAA5_B1D0,
1038 0x92E9_DD53,
1039 0xA2E2_FA6D,
1040 0xCE69_65AA,
1041 0x02C0_CD4E,
1042 0x6E6D_984F,
1043 0x114A_90E7,
1044 0x5279_F8DA,
1045 ];
1046 let final_fsm = [0x6513_0120, 0xA14C_7DBD, 0xB68B_551A];
1047 let keystream_rows = [
1048 TraceRow {
1049 s0: 0x942E_1440,
1050 s2: 0x5832_E9F4,
1051 s5: 0x644C_C9B9,
1052 s11: 0x02C0_CD4E,
1053 s15: 0xC1E9_3B6B,
1054 r1: 0x6046_F758,
1055 r2: 0x59E6_85C1,
1056 r3: 0x7DCB_C989,
1057 },
1058 TraceRow {
1059 s0: 0x82AB_D3FE,
1060 s2: 0x5F97_02A0,
1061 s5: 0xDBF6_DE13,
1062 s11: 0x6E6D_984F,
1063 s15: 0xCEB9_9926,
1064 r1: 0x736D_85F1,
1065 r2: 0x37DD_84E6,
1066 r3: 0xA9BE_CBB1,
1067 },
1068 TraceRow {
1069 s0: 0x5832_E9F4,
1070 s2: 0x0871_2C81,
1071 s5: 0xBAA5_B1D0,
1072 s11: 0x114A_90E7,
1073 s15: 0xE34F_6919,
1074 r1: 0xAA25_9A88,
1075 r2: 0x56C4_5F48,
1076 r3: 0xC354_6A61,
1077 },
1078 ];
1079 let outputs = [0xEFF8_A342, 0xF751_480F];
1080
1081 let case = OfficialTraceCase {
1082 key,
1083 iv,
1084 initial_lfsr,
1085 init_rows,
1086 final_lfsr,
1087 final_fsm,
1088 keystream_rows,
1089 outputs,
1090 };
1091 assert_official_trace::<false>(&case);
1092 assert_official_trace::<true>(&case);
1093 }
1094
1095 #[test]
1096 fn official_test_set_3_trace_fast_and_ct() {
1097 let key = [
1098 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1, 0xA8, 0xFF, 0x86, 0x67, 0xB1, 0x71,
1099 0x40, 0x13,
1100 ];
1101 let iv = [
1102 0x62, 0xA5, 0x40, 0x98, 0x1B, 0xA6, 0xF9, 0xB7, 0x45, 0x92, 0xB0, 0xE7, 0x86, 0x90,
1103 0xF7, 0x1B,
1104 ];
1105 let initial_lfsr = [
1106 0xBFCA_3997,
1107 0xF507_392E,
1108 0x5700_7998,
1109 0x4E8E_BFEC,
1110 0x4035_C668,
1111 0x0AF8_C6D1,
1112 0xA8FF_8667,
1113 0xB171_4013,
1114 0xBFCA_3997,
1115 0x7397_CE35,
1116 0x1292_C97F,
1117 0x4E8E_BFEC,
1118 0x5B93_3FDF,
1119 0x0AF8_C6D1,
1120 0xA8FF_8667,
1121 0xD3D4_008B,
1122 ];
1123 let init_rows = [
1124 TraceRow {
1125 s0: 0xBFCA_3997,
1126 s2: 0x5700_7998,
1127 s5: 0x0AF8_C6D1,
1128 s11: 0x4E8E_BFEC,
1129 s15: 0xD3D4_008B,
1130 r1: 0x0000_0000,
1131 r2: 0x0000_0000,
1132 r3: 0x0000_0000,
1133 },
1134 TraceRow {
1135 s0: 0xF507_392E,
1136 s2: 0x4E8E_BFEC,
1137 s5: 0xA8FF_8667,
1138 s11: 0x5B93_3FDF,
1139 s15: 0xEE2C_ABF5,
1140 r1: 0x0AF8_C6D1,
1141 r2: 0x6363_6363,
1142 r3: 0x2525_2525,
1143 },
1144 TraceRow {
1145 s0: 0x5700_7998,
1146 s2: 0x4035_C668,
1147 s5: 0xB171_4013,
1148 s11: 0x0AF8_C6D1,
1149 s15: 0x6673_56A3,
1150 r1: 0xF13E_06A5,
1151 r2: 0x79A1_E99D,
1152 r3: 0x9393_9393,
1153 },
1154 TraceRow {
1155 s0: 0x4E8E_BFEC,
1156 s2: 0x0AF8_C6D1,
1157 s5: 0xBFCA_3997,
1158 s11: 0xA8FF_8667,
1159 s15: 0x6410_181D,
1160 r1: 0x9C84_BD1D,
1161 r2: 0x8EEE_B4AE,
1162 r3: 0xE599_5CC4,
1163 },
1164 TraceRow {
1165 s0: 0x4035_C668,
1166 s2: 0xA8FF_8667,
1167 s5: 0x7397_CE35,
1168 s11: 0xD3D4_008B,
1169 s15: 0x241A_7790,
1170 r1: 0xE942_1A01,
1171 r2: 0x7519_6F5C,
1172 r3: 0xC83E_1776,
1173 },
1174 TraceRow {
1175 s0: 0x0AF8_C6D1,
1176 s2: 0xB171_4013,
1177 s5: 0x1292_C97F,
1178 s11: 0xEE2C_ABF5,
1179 s15: 0xC485_B826,
1180 r1: 0x30C3_489F,
1181 r2: 0x36A4_4937,
1182 r3: 0x0F31_7420,
1183 },
1184 TraceRow {
1185 s0: 0xA8FF_8667,
1186 s2: 0xBFCA_3997,
1187 s5: 0x4E8E_BFEC,
1188 s11: 0x6673_56A3,
1189 s15: 0xA211_C1E9,
1190 r1: 0x5448_0696,
1191 r2: 0x02D9_0971,
1192 r3: 0x3D98_2023,
1193 },
1194 TraceRow {
1195 s0: 0xB171_4013,
1196 s2: 0x7397_CE35,
1197 s5: 0x5B93_3FDF,
1198 s11: 0x6410_181D,
1199 s15: 0x6E8A_E7E6,
1200 r1: 0x75EF_A940,
1201 r2: 0xD63B_98F8,
1202 r3: 0x883F_13A7,
1203 },
1204 ];
1205 let final_lfsr = [
1206 0xFEAF_BAD8,
1207 0x1B11_050A,
1208 0x2370_8014,
1209 0xAC84_94DB,
1210 0xED97_D431,
1211 0xDBBB_59B3,
1212 0x6CD3_0005,
1213 0x7EC3_6405,
1214 0xB20F_02AC,
1215 0xEB40_7735,
1216 0x50E4_1A0E,
1217 0xFFA8_ABC1,
1218 0xEB48_00A7,
1219 0xD4E6_749D,
1220 0xD1C4_52FE,
1221 0xA92A_3153,
1222 ];
1223 let final_fsm = [0x6599_AA50, 0x5EA9_188B, 0xF418_89FC];
1224 let keystream_rows = [
1225 TraceRow {
1226 s0: 0x1B11_050A,
1227 s2: 0xAC84_94DB,
1228 s5: 0x6CD3_0005,
1229 s11: 0xEB48_00A7,
1230 s15: 0x0FE9_1C6F,
1231 r1: 0x8E4C_E8DA,
1232 r2: 0x2DEF_74EA,
1233 r3: 0x42B4_B0A3,
1234 },
1235 TraceRow {
1236 s0: 0x2370_8014,
1237 s2: 0xED97_D431,
1238 s5: 0x7EC3_6405,
1239 s11: 0xD4E6_749D,
1240 s15: 0xC3CB_3734,
1241 r1: 0x5C57_2590,
1242 r2: 0x79B5_1828,
1243 r3: 0x2496_A1E1,
1244 },
1245 TraceRow {
1246 s0: 0xAC84_94DB,
1247 s2: 0xDBBB_59B3,
1248 s5: 0xB20F_02AC,
1249 s11: 0xD1C4_52FE,
1250 s15: 0x739A_B29C,
1251 r1: 0xD40A_DE0C,
1252 r2: 0x5037_B990,
1253 r3: 0x32D1_FAE0,
1254 },
1255 ];
1256 let outputs = [0xA8C8_74A9, 0x7AE7_C4F8];
1257
1258 let case = OfficialTraceCase {
1259 key,
1260 iv,
1261 initial_lfsr,
1262 init_rows,
1263 final_lfsr,
1264 final_fsm,
1265 keystream_rows,
1266 outputs,
1267 };
1268 assert_official_trace::<false>(&case);
1269 assert_official_trace::<true>(&case);
1270 }
1271
1272 #[test]
1273 fn official_test_set_4_iterated_fast_and_ct() {
1274 assert_iterated_test_set_4::<false>();
1275 assert_iterated_test_set_4::<true>();
1276 }
1277}