Skip to main content

binius_field/packed_fields/
rijndael.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4use crate::{
5	arch::{
6		AesInvert1x, AesInvert16x, AesInvert32x, AesInvert64x, AesSquare1x, AesSquare16x,
7		AesSquare32x, AesSquare64x, AesWideMul1x, AesWideMul16x, AesWideMul32x, AesWideMul64x,
8		M128, M256, M512, portable::packed_macros::*,
9	},
10	fields::rijndael::Rijndael8b,
11};
12
13define_packed_binary_field!(
14	PackedRijndael1x8b,
15	Rijndael8b,
16	u8,
17	(AesSquare1x),
18	(AesInvert1x),
19	(AesWideMul1x)
20);
21define_packed_binary_field!(
22	PackedRijndael16x8b,
23	Rijndael8b,
24	M128,
25	(AesSquare16x),
26	(AesInvert16x),
27	(AesWideMul16x)
28);
29define_packed_binary_field!(
30	PackedRijndael32x8b,
31	Rijndael8b,
32	M256,
33	(AesSquare32x),
34	(AesInvert32x),
35	(AesWideMul32x)
36);
37define_packed_binary_field!(
38	PackedRijndael64x8b,
39	Rijndael8b,
40	M512,
41	(AesSquare64x),
42	(AesInvert64x),
43	(AesWideMul64x)
44);
45
46#[cfg(test)]
47mod tests {
48	use super::*;
49	use crate::{WideMul, packed_fields::test_utils::packed_field_tests};
50
51	packed_field_tests!(aes_1x8b, PackedRijndael1x8b);
52	packed_field_tests!(aes_16x8b, PackedRijndael16x8b);
53	packed_field_tests!(aes_32x8b, PackedRijndael32x8b);
54	packed_field_tests!(aes_64x8b, PackedRijndael64x8b);
55
56	#[test]
57	fn test_wide_mul_exhaustive_scalar_pairs() {
58		// The scalar field has only 2^8 elements, so every product admits an exhaustive check.
59		// Each byte pair is broadcast across the 128-bit packing and multiplied deferred.
60		//
61		//     reduce(wide_mul(a, b)) must equal the scalar product in every lane.
62		//
63		// The scalar multiply is an independent oracle: it runs the tower-field log/exp tables,
64		// not the packed widening path under test.
65		for a in 0..=u8::MAX {
66			for b in 0..=u8::MAX {
67				let expected = crate::Rijndael8b::new(a) * crate::Rijndael8b::new(b);
68
69				let a_packed = crate::PackedRijndael16x8b::broadcast(crate::Rijndael8b::new(a));
70				let b_packed = crate::PackedRijndael16x8b::broadcast(crate::Rijndael8b::new(b));
71				let reduced = crate::PackedRijndael16x8b::reduce(
72					crate::PackedRijndael16x8b::wide_mul(a_packed, b_packed),
73				);
74
75				assert_eq!(
76					reduced,
77					crate::PackedRijndael16x8b::broadcast(expected),
78					"a={a:#04x} b={b:#04x}"
79				);
80			}
81		}
82	}
83}