1use super::packed::PackedPrimitiveType;
4use crate::{
5 arch::PairwiseTableStrategy,
6 arithmetic_traits::{TaggedInvertOrZero, TaggedMul, TaggedMulAlpha, TaggedSquare},
7 packed::PackedField,
8 underlier::UnderlierType,
9 AESTowerField8b, BinaryField2b, BinaryField4b, BinaryField8b,
10};
11
12impl<U: UnderlierType> TaggedMul<PairwiseTableStrategy> for PackedPrimitiveType<U, BinaryField2b>
13where
14 Self: PackedField<Scalar = BinaryField2b>,
15{
16 #[inline]
17 fn mul(self, rhs: Self) -> Self {
18 Self::from_fn(|i| mul_binary_tower_4b(self.get(i).into(), rhs.get(i).into()).into())
19 }
20}
21
22impl<U: UnderlierType> TaggedMul<PairwiseTableStrategy> for PackedPrimitiveType<U, BinaryField4b>
23where
24 Self: PackedField<Scalar = BinaryField4b>,
25{
26 #[inline]
27 fn mul(self, rhs: Self) -> Self {
28 Self::from_fn(|i| mul_binary_tower_4b(self.get(i).into(), rhs.get(i).into()).into())
29 }
30}
31
32const fn mul_binary_tower_4b(a: u8, b: u8) -> u8 {
33 #[rustfmt::skip]
34 const MUL_4B_LOOKUP: [u8; 128] = [
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
37 0x20, 0x13, 0xa8, 0x9b, 0xec, 0xdf, 0x64, 0x57,
38 0x30, 0x21, 0xfc, 0xed, 0x74, 0x65, 0xb8, 0xa9,
39 0x40, 0xc8, 0xd9, 0x51, 0xae, 0x26, 0x37, 0xbf,
40 0x50, 0xfa, 0x8d, 0x27, 0x36, 0x9c, 0xeb, 0x41,
41 0x60, 0xdb, 0x71, 0xca, 0x42, 0xf9, 0x53, 0xe8,
42 0x70, 0xe9, 0x25, 0xbc, 0xda, 0x43, 0x8f, 0x16,
43 0x80, 0x4c, 0x6e, 0xa2, 0xf7, 0x3b, 0x19, 0xd5,
44 0x90, 0x7e, 0x3a, 0xd4, 0x6f, 0x81, 0xc5, 0x2b,
45 0xa0, 0x5f, 0xc6, 0x39, 0x1b, 0xe4, 0x7d, 0x82,
46 0xb0, 0x6d, 0x92, 0x4f, 0x83, 0x5e, 0xa1, 0x7c,
47 0xc0, 0x84, 0xb7, 0xf3, 0x59, 0x1d, 0x2e, 0x6a,
48 0xd0, 0xb6, 0xe3, 0x85, 0xc1, 0xa7, 0xf2, 0x94,
49 0xe0, 0x97, 0x1f, 0x68, 0xb5, 0xc2, 0x4a, 0x3d,
50 0xf0, 0xa5, 0x4b, 0x1e, 0x2d, 0x78, 0x96, 0xc3,
51 ];
52 let idx = a << 4 | b;
53 (MUL_4B_LOOKUP[idx as usize >> 1] >> ((idx & 1) * 4)) & 0x0f
54}
55
56impl<U: UnderlierType> TaggedMul<PairwiseTableStrategy> for PackedPrimitiveType<U, BinaryField8b>
57where
58 Self: PackedField<Scalar = BinaryField8b>,
59{
60 #[inline]
61 fn mul(self, rhs: Self) -> Self {
62 #[rustfmt::skip]
63 const EXP_TABLE: [u8; 256] = [
64 0x1, 0x13, 0x43, 0x66, 0xab, 0x8c, 0x60, 0xc6, 0x91, 0xca, 0x59, 0xb2, 0x6a, 0x63, 0xf4, 0x53,
65 0x17, 0x0f, 0xfa, 0xba, 0xee, 0x87, 0xd6, 0xe0, 0x6e, 0x2f, 0x68, 0x42, 0x75, 0xe8, 0xea, 0xcb,
66 0x4a, 0xf1, 0x0c, 0xc8, 0x78, 0x33, 0xd1, 0x9e, 0x30, 0xe3, 0x5c, 0xed, 0xb5, 0x14, 0x3d, 0x38,
67 0x67, 0xb8, 0xcf, 0x06, 0x6d, 0x1d, 0xaa, 0x9f, 0x23, 0xa0, 0x3a, 0x46, 0x39, 0x74, 0xfb, 0xa9,
68 0xad, 0xe1, 0x7d, 0x6c, 0x0e, 0xe9, 0xf9, 0x88, 0x2c, 0x5a, 0x80, 0xa8, 0xbe, 0xa2, 0x1b, 0xc7,
69 0x82, 0x89, 0x3f, 0x19, 0xe6, 0x03, 0x32, 0xc2, 0xdd, 0x56, 0x48, 0xd0, 0x8d, 0x73, 0x85, 0xf7,
70 0x61, 0xd5, 0xd2, 0xac, 0xf2, 0x3e, 0x0a, 0xa5, 0x65, 0x99, 0x4e, 0xbd, 0x90, 0xd9, 0x1a, 0xd4,
71 0xc1, 0xef, 0x94, 0x95, 0x86, 0xc5, 0xa3, 0x08, 0x84, 0xe4, 0x22, 0xb3, 0x79, 0x20, 0x92, 0xf8,
72 0x9b, 0x6f, 0x3c, 0x2b, 0x24, 0xde, 0x64, 0x8a, 0xd, 0xdb, 0x3b, 0x55, 0x7a, 0x12, 0x50, 0x25,
73 0xcd, 0x27, 0xec, 0xa6, 0x57, 0x5b, 0x93, 0xeb, 0xd8, 0x09, 0x97, 0xa7, 0x44, 0x18, 0xf5, 0x40,
74 0x54, 0x69, 0x51, 0x36, 0x8e, 0x41, 0x47, 0x2a, 0x37, 0x9d, 0x02, 0x21, 0x81, 0xbb, 0xfd, 0xc4,
75 0xb0, 0x4b, 0xe2, 0x4f, 0xae, 0xd3, 0xbf, 0xb1, 0x58, 0xa1, 0x29, 0x05, 0x5f, 0xdf, 0x77, 0xc9,
76 0x6b, 0x70, 0xb7, 0x35, 0xbc, 0x83, 0x9a, 0x7c, 0x7f, 0x4d, 0x8f, 0x52, 0x04, 0x4c, 0x9c, 0x11,
77 0x62, 0xe7, 0x10, 0x71, 0xa4, 0x76, 0xda, 0x28, 0x16, 0x1c, 0xb9, 0xdc, 0x45, 0x0b, 0xb6, 0x26,
78 0xff, 0xe5, 0x31, 0xf0, 0x1f, 0x8b, 0x1e, 0x98, 0x5d, 0xfe, 0xf6, 0x72, 0x96, 0xb4, 0x07, 0x7e,
79 0x5e, 0xcc, 0x34, 0xaf, 0xc0, 0xfc, 0xd7, 0xf3, 0x2d, 0x49, 0xc3, 0xce, 0x15, 0x2e, 0x7b, 0x00,
80 ];
81 #[rustfmt::skip]
82 const LOG_TABLE: [u8; 256] = [
83 0x00, 0x00, 0xaa, 0x55, 0xcc, 0xbb, 0x33, 0xee, 0x77, 0x99, 0x66, 0xdd, 0x22, 0x88, 0x44, 0x11,
84 0xd2, 0xcf, 0x8d, 0x01, 0x2d, 0xfc, 0xd8, 0x10, 0x9d, 0x53, 0x6e, 0x4e, 0xd9, 0x35, 0xe6, 0xe4,
85 0x7d, 0xab, 0x7a, 0x38, 0x84, 0x8f, 0xdf, 0x91, 0xd7, 0xba, 0xa7, 0x83, 0x48, 0xf8, 0xfd, 0x19,
86 0x28, 0xe2, 0x56, 0x25, 0xf2, 0xc3, 0xa3, 0xa8, 0x2f, 0x3c, 0x3a, 0x8a, 0x82, 0x2e, 0x65, 0x52,
87 0x9f, 0xa5, 0x1b, 0x02, 0x9c, 0xdc, 0x3b, 0xa6, 0x5a, 0xf9, 0x20, 0xb1, 0xcd, 0xc9, 0x6a, 0xb3,
88 0x8e, 0xa2, 0xcb, 0x0f, 0xa0, 0x8b, 0x59, 0x94, 0xb8, 0x0a, 0x49, 0x95, 0x2a, 0xe8, 0xf0, 0xbc,
89 0x06, 0x60, 0xd0, 0x0d, 0x86, 0x68, 0x03, 0x30, 0x1a, 0xa1, 0x0c, 0xc0, 0x43, 0x34, 0x18, 0x81,
90 0xc1, 0xd3, 0xeb, 0x5d, 0x3d, 0x1c, 0xd5, 0xbe, 0x24, 0x7c, 0x8c, 0xfe, 0xc7, 0x42, 0xef, 0xc8,
91 0x4a, 0xac, 0x50, 0xc5, 0x78, 0x5e, 0x74, 0x15, 0x47, 0x51, 0x87, 0xe5, 0x05, 0x5c, 0xa4, 0xca,
92 0x6c, 0x08, 0x7e, 0x96, 0x72, 0x73, 0xec, 0x9a, 0xe7, 0x69, 0xc6, 0x80, 0xce, 0xa9, 0x27, 0x37,
93 0x39, 0xb9, 0x4d, 0x76, 0xd4, 0x67, 0x93, 0x9b, 0x4b, 0x3f, 0x36, 0x04, 0x63, 0x40, 0xb4, 0xf3,
94 0xb0, 0xb7, 0x0b, 0x7b, 0xed, 0x2c, 0xde, 0xc2, 0x31, 0xda, 0x13, 0xad, 0xc4, 0x6b, 0x4c, 0xb6,
95 0xf4, 0x70, 0x57, 0xfa, 0xaf, 0x75, 0x07, 0x4f, 0x23, 0xbf, 0x09, 0x1f, 0xf1, 0x90, 0xfb, 0x32,
96 0x5b, 0x26, 0x62, 0xb5, 0x6f, 0x61, 0x16, 0xf6, 0x98, 0x6d, 0xd6, 0x89, 0xdb, 0x58, 0x85, 0xbd,
97 0x17, 0x41, 0xb2, 0x29, 0x79, 0xe1, 0x54, 0xd1, 0x1d, 0x45, 0x1e, 0x97, 0x92, 0x2b, 0x14, 0x71,
98 0xe3, 0x21, 0x64, 0xf7, 0x0e, 0x9e, 0xea, 0x5f, 0x7f, 0x46, 0x12, 0x3e, 0xf5, 0xae, 0xe9, 0xe0,
99 ];
100
101 Self::from_fn(|i| {
102 multiply_8b_using_log_table(self.get(i).val(), rhs.get(i).val(), &LOG_TABLE, &EXP_TABLE)
103 .into()
104 })
105 }
106}
107
108impl<U: UnderlierType> TaggedMul<PairwiseTableStrategy> for PackedPrimitiveType<U, AESTowerField8b>
109where
110 Self: PackedField<Scalar = AESTowerField8b>,
111{
112 #[inline]
113 fn mul(self, rhs: Self) -> Self {
114 #[rustfmt::skip]
115 const AES_EXP_TABLE: [u8; 256] = [
116 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
117 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
118 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
119 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
120 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
121 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
122 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
123 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
124 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
125 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
126 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
127 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
128 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
129 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
130 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
131 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x0
132 ];
133
134 #[rustfmt::skip]
135 const AES_LOG_TABLE: [u8; 256] = [
136 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
137 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
138 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
139 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
140 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
141 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
142 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
143 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
144 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
145 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
146 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
147 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
148 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
149 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
150 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
151 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07,
152 ];
153
154 Self::from_fn(|i| {
155 multiply_8b_using_log_table(
156 self.get(i).val(),
157 rhs.get(i).val(),
158 &AES_LOG_TABLE,
159 &AES_EXP_TABLE,
160 )
161 .into()
162 })
163 }
164}
165
166#[inline]
167fn multiply_8b_using_log_table(
168 lhs: u8,
169 rhs: u8,
170 log_table: &[u8; 256],
171 exp_table: &[u8; 256],
172) -> u8 {
173 let result = if lhs != 0 && rhs != 0 {
174 let log_table_index = log_table[lhs as usize] as usize + log_table[rhs as usize] as usize;
175 let log_table_index = if log_table_index > 254 {
176 log_table_index - 255
177 } else {
178 log_table_index
179 };
180
181 unsafe {
182 *exp_table.get_unchecked(log_table_index)
188 }
189 } else {
190 0
191 };
192
193 result
194}
195
196#[inline(always)]
198fn unary_op_with_table<PT>(val: PT, table: &[u8; 256]) -> PT
199where
200 PT: PackedField,
201 PT::Scalar: From<u8>,
202 u8: From<PT::Scalar>,
203{
204 PT::from_fn(|i| table[u8::from(val.get(i)) as usize].into())
205}
206
207macro_rules! impl_unary_ops {
209 ($tagged_op_type:ident, $method_name:ident, $table:ident, $field:ty) => {
210 impl<U: UnderlierType> $tagged_op_type<PairwiseTableStrategy>
211 for PackedPrimitiveType<U, $field>
212 where
213 Self: PackedField<Scalar = $field>,
214 {
215 #[inline(always)]
216 fn $method_name(self) -> Self {
217 unary_op_with_table(self, &$table)
218 }
219 }
220 };
221}
222
223#[rustfmt::skip]
224static BINARY_TOWER_8B_SQUARE_MAP: [u8; 256] = [
225 0x00, 0x01, 0x03, 0x02, 0x09, 0x08, 0x0a, 0x0b, 0x07, 0x06, 0x04, 0x05, 0x0e, 0x0f, 0x0d, 0x0c,
226 0x41, 0x40, 0x42, 0x43, 0x48, 0x49, 0x4b, 0x4a, 0x46, 0x47, 0x45, 0x44, 0x4f, 0x4e, 0x4c, 0x4d,
227 0xc3, 0xc2, 0xc0, 0xc1, 0xca, 0xcb, 0xc9, 0xc8, 0xc4, 0xc5, 0xc7, 0xc6, 0xcd, 0xcc, 0xce, 0xcf,
228 0x82, 0x83, 0x81, 0x80, 0x8b, 0x8a, 0x88, 0x89, 0x85, 0x84, 0x86, 0x87, 0x8c, 0x8d, 0x8f, 0x8e,
229 0xa9, 0xa8, 0xaa, 0xab, 0xa0, 0xa1, 0xa3, 0xa2, 0xae, 0xaf, 0xad, 0xac, 0xa7, 0xa6, 0xa4, 0xa5,
230 0xe8, 0xe9, 0xeb, 0xea, 0xe1, 0xe0, 0xe2, 0xe3, 0xef, 0xee, 0xec, 0xed, 0xe6, 0xe7, 0xe5, 0xe4,
231 0x6a, 0x6b, 0x69, 0x68, 0x63, 0x62, 0x60, 0x61, 0x6d, 0x6c, 0x6e, 0x6f, 0x64, 0x65, 0x67, 0x66,
232 0x2b, 0x2a, 0x28, 0x29, 0x22, 0x23, 0x21, 0x20, 0x2c, 0x2d, 0x2f, 0x2e, 0x25, 0x24, 0x26, 0x27,
233 0x57, 0x56, 0x54, 0x55, 0x5e, 0x5f, 0x5d, 0x5c, 0x50, 0x51, 0x53, 0x52, 0x59, 0x58, 0x5a, 0x5b,
234 0x16, 0x17, 0x15, 0x14, 0x1f, 0x1e, 0x1c, 0x1d, 0x11, 0x10, 0x12, 0x13, 0x18, 0x19, 0x1b, 0x1a,
235 0x94, 0x95, 0x97, 0x96, 0x9d, 0x9c, 0x9e, 0x9f, 0x93, 0x92, 0x90, 0x91, 0x9a, 0x9b, 0x99, 0x98,
236 0xd5, 0xd4, 0xd6, 0xd7, 0xdc, 0xdd, 0xdf, 0xde, 0xd2, 0xd3, 0xd1, 0xd0, 0xdb, 0xda, 0xd8, 0xd9,
237 0xfe, 0xff, 0xfd, 0xfc, 0xf7, 0xf6, 0xf4, 0xf5, 0xf9, 0xf8, 0xfa, 0xfb, 0xf0, 0xf1, 0xf3, 0xf2,
238 0xbf, 0xbe, 0xbc, 0xbd, 0xb6, 0xb7, 0xb5, 0xb4, 0xb8, 0xb9, 0xbb, 0xba, 0xb1, 0xb0, 0xb2, 0xb3,
239 0x3d, 0x3c, 0x3e, 0x3f, 0x34, 0x35, 0x37, 0x36, 0x3a, 0x3b, 0x39, 0x38, 0x33, 0x32, 0x30, 0x31,
240 0x7c, 0x7d, 0x7f, 0x7e, 0x75, 0x74, 0x76, 0x77, 0x7b, 0x7a, 0x78, 0x79, 0x72, 0x73, 0x71, 0x70,
241];
242
243impl_unary_ops!(TaggedSquare, square, BINARY_TOWER_8B_SQUARE_MAP, BinaryField8b);
244
245#[rustfmt::skip]
246const AES_TOWER_8B_SQUARE_MAP: [u8; 256] = [
247 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55,
248 0x1b, 0x1a, 0x1f, 0x1e, 0x0b, 0x0a, 0x0f, 0x0e, 0x5b, 0x5a, 0x5f, 0x5e, 0x4b, 0x4a, 0x4f, 0x4e,
249 0x6c, 0x6d, 0x68, 0x69, 0x7c, 0x7d, 0x78, 0x79, 0x2c, 0x2d, 0x28, 0x29, 0x3c, 0x3d, 0x38, 0x39,
250 0x77, 0x76, 0x73, 0x72, 0x67, 0x66, 0x63, 0x62, 0x37, 0x36, 0x33, 0x32, 0x27, 0x26, 0x23, 0x22,
251 0xab, 0xaa, 0xaf, 0xae, 0xbb, 0xba, 0xbf, 0xbe, 0xeb, 0xea, 0xef, 0xee, 0xfb, 0xfa, 0xff, 0xfe,
252 0xb0, 0xb1, 0xb4, 0xb5, 0xa0, 0xa1, 0xa4, 0xa5, 0xf0, 0xf1, 0xf4, 0xf5, 0xe0, 0xe1, 0xe4, 0xe5,
253 0xc7, 0xc6, 0xc3, 0xc2, 0xd7, 0xd6, 0xd3, 0xd2, 0x87, 0x86, 0x83, 0x82, 0x97, 0x96, 0x93, 0x92,
254 0xdc, 0xdd, 0xd8, 0xd9, 0xcc, 0xcd, 0xc8, 0xc9, 0x9c, 0x9d, 0x98, 0x99, 0x8c, 0x8d, 0x88, 0x89,
255 0x9a, 0x9b, 0x9e, 0x9f, 0x8a, 0x8b, 0x8e, 0x8f, 0xda, 0xdb, 0xde, 0xdf, 0xca, 0xcb, 0xce, 0xcf,
256 0x81, 0x80, 0x85, 0x84, 0x91, 0x90, 0x95, 0x94, 0xc1, 0xc0, 0xc5, 0xc4, 0xd1, 0xd0, 0xd5, 0xd4,
257 0xf6, 0xf7, 0xf2, 0xf3, 0xe6, 0xe7, 0xe2, 0xe3, 0xb6, 0xb7, 0xb2, 0xb3, 0xa6, 0xa7, 0xa2, 0xa3,
258 0xed, 0xec, 0xe9, 0xe8, 0xfd, 0xfc, 0xf9, 0xf8, 0xad, 0xac, 0xa9, 0xa8, 0xbd, 0xbc, 0xb9, 0xb8,
259 0x31, 0x30, 0x35, 0x34, 0x21, 0x20, 0x25, 0x24, 0x71, 0x70, 0x75, 0x74, 0x61, 0x60, 0x65, 0x64,
260 0x2a, 0x2b, 0x2e, 0x2f, 0x3a, 0x3b, 0x3e, 0x3f, 0x6a, 0x6b, 0x6e, 0x6f, 0x7a, 0x7b, 0x7e, 0x7f,
261 0x5d, 0x5c, 0x59, 0x58, 0x4d, 0x4c, 0x49, 0x48, 0x1d, 0x1c, 0x19, 0x18, 0x0d, 0x0c, 0x09, 0x08,
262 0x46, 0x47, 0x42, 0x43, 0x56, 0x57, 0x52, 0x53, 0x06, 0x07, 0x02, 0x03, 0x16, 0x17, 0x12, 0x13,
263];
264
265impl_unary_ops!(TaggedSquare, square, AES_TOWER_8B_SQUARE_MAP, AESTowerField8b);
266
267#[rustfmt::skip]
268const BINARY_TOWER_8B_MUL_ALPHA_MAP: [u8; 256] = [
269 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
270 0x41, 0x51, 0x61, 0x71, 0x01, 0x11, 0x21, 0x31, 0xc1, 0xd1, 0xe1, 0xf1, 0x81, 0x91, 0xa1, 0xb1,
271 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2, 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
272 0xc3, 0xd3, 0xe3, 0xf3, 0x83, 0x93, 0xa3, 0xb3, 0x43, 0x53, 0x63, 0x73, 0x03, 0x13, 0x23, 0x33,
273 0x94, 0x84, 0xb4, 0xa4, 0xd4, 0xc4, 0xf4, 0xe4, 0x14, 0x04, 0x34, 0x24, 0x54, 0x44, 0x74, 0x64,
274 0xd5, 0xc5, 0xf5, 0xe5, 0x95, 0x85, 0xb5, 0xa5, 0x55, 0x45, 0x75, 0x65, 0x15, 0x05, 0x35, 0x25,
275 0x16, 0x06, 0x36, 0x26, 0x56, 0x46, 0x76, 0x66, 0x96, 0x86, 0xb6, 0xa6, 0xd6, 0xc6, 0xf6, 0xe6,
276 0x57, 0x47, 0x77, 0x67, 0x17, 0x07, 0x37, 0x27, 0xd7, 0xc7, 0xf7, 0xe7, 0x97, 0x87, 0xb7, 0xa7,
277 0xe8, 0xf8, 0xc8, 0xd8, 0xa8, 0xb8, 0x88, 0x98, 0x68, 0x78, 0x48, 0x58, 0x28, 0x38, 0x08, 0x18,
278 0xa9, 0xb9, 0x89, 0x99, 0xe9, 0xf9, 0xc9, 0xd9, 0x29, 0x39, 0x09, 0x19, 0x69, 0x79, 0x49, 0x59,
279 0x6a, 0x7a, 0x4a, 0x5a, 0x2a, 0x3a, 0x0a, 0x1a, 0xea, 0xfa, 0xca, 0xda, 0xaa, 0xba, 0x8a, 0x9a,
280 0x2b, 0x3b, 0x0b, 0x1b, 0x6b, 0x7b, 0x4b, 0x5b, 0xab, 0xbb, 0x8b, 0x9b, 0xeb, 0xfb, 0xcb, 0xdb,
281 0x7c, 0x6c, 0x5c, 0x4c, 0x3c, 0x2c, 0x1c, 0x0c, 0xfc, 0xec, 0xdc, 0xcc, 0xbc, 0xac, 0x9c, 0x8c,
282 0x3d, 0x2d, 0x1d, 0x0d, 0x7d, 0x6d, 0x5d, 0x4d, 0xbd, 0xad, 0x9d, 0x8d, 0xfd, 0xed, 0xdd, 0xcd,
283 0xfe, 0xee, 0xde, 0xce, 0xbe, 0xae, 0x9e, 0x8e, 0x7e, 0x6e, 0x5e, 0x4e, 0x3e, 0x2e, 0x1e, 0x0e,
284 0xbf, 0xaf, 0x9f, 0x8f, 0xff, 0xef, 0xdf, 0xcf, 0x3f, 0x2f, 0x1f, 0x0f, 0x7f, 0x6f, 0x5f, 0x4f,
285];
286
287impl_unary_ops!(TaggedMulAlpha, mul_alpha, BINARY_TOWER_8B_MUL_ALPHA_MAP, BinaryField8b);
288
289#[rustfmt::skip]
290const AES_TOWER_8B_MUL_ALPHA_MAP: [u8; 256] = [
291 0x00, 0xd3, 0xbd, 0x6e, 0x61, 0xb2, 0xdc, 0x0f, 0xc2, 0x11, 0x7f, 0xac, 0xa3, 0x70, 0x1e, 0xcd,
292 0x9f, 0x4c, 0x22, 0xf1, 0xfe, 0x2d, 0x43, 0x90, 0x5d, 0x8e, 0xe0, 0x33, 0x3c, 0xef, 0x81, 0x52,
293 0x25, 0xf6, 0x98, 0x4b, 0x44, 0x97, 0xf9, 0x2a, 0xe7, 0x34, 0x5a, 0x89, 0x86, 0x55, 0x3b, 0xe8,
294 0xba, 0x69, 0x07, 0xd4, 0xdb, 0x08, 0x66, 0xb5, 0x78, 0xab, 0xc5, 0x16, 0x19, 0xca, 0xa4, 0x77,
295 0x4a, 0x99, 0xf7, 0x24, 0x2b, 0xf8, 0x96, 0x45, 0x88, 0x5b, 0x35, 0xe6, 0xe9, 0x3a, 0x54, 0x87,
296 0xd5, 0x06, 0x68, 0xbb, 0xb4, 0x67, 0x09, 0xda, 0x17, 0xc4, 0xaa, 0x79, 0x76, 0xa5, 0xcb, 0x18,
297 0x6f, 0xbc, 0xd2, 0x01, 0x0e, 0xdd, 0xb3, 0x60, 0xad, 0x7e, 0x10, 0xc3, 0xcc, 0x1f, 0x71, 0xa2,
298 0xf0, 0x23, 0x4d, 0x9e, 0x91, 0x42, 0x2c, 0xff, 0x32, 0xe1, 0x8f, 0x5c, 0x53, 0x80, 0xee, 0x3d,
299 0x94, 0x47, 0x29, 0xfa, 0xf5, 0x26, 0x48, 0x9b, 0x56, 0x85, 0xeb, 0x38, 0x37, 0xe4, 0x8a, 0x59,
300 0x0b, 0xd8, 0xb6, 0x65, 0x6a, 0xb9, 0xd7, 0x04, 0xc9, 0x1a, 0x74, 0xa7, 0xa8, 0x7b, 0x15, 0xc6,
301 0xb1, 0x62, 0x0c, 0xdf, 0xd0, 0x03, 0x6d, 0xbe, 0x73, 0xa0, 0xce, 0x1d, 0x12, 0xc1, 0xaf, 0x7c,
302 0x2e, 0xfd, 0x93, 0x40, 0x4f, 0x9c, 0xf2, 0x21, 0xec, 0x3f, 0x51, 0x82, 0x8d, 0x5e, 0x30, 0xe3,
303 0xde, 0x0d, 0x63, 0xb0, 0xbf, 0x6c, 0x02, 0xd1, 0x1c, 0xcf, 0xa1, 0x72, 0x7d, 0xae, 0xc0, 0x13,
304 0x41, 0x92, 0xfc, 0x2f, 0x20, 0xf3, 0x9d, 0x4e, 0x83, 0x50, 0x3e, 0xed, 0xe2, 0x31, 0x5f, 0x8c,
305 0xfb, 0x28, 0x46, 0x95, 0x9a, 0x49, 0x27, 0xf4, 0x39, 0xea, 0x84, 0x57, 0x58, 0x8b, 0xe5, 0x36,
306 0x64, 0xb7, 0xd9, 0x0a, 0x05, 0xd6, 0xb8, 0x6b, 0xa6, 0x75, 0x1b, 0xc8, 0xc7, 0x14, 0x7a, 0xa9,
307];
308
309impl_unary_ops!(TaggedMulAlpha, mul_alpha, AES_TOWER_8B_MUL_ALPHA_MAP, AESTowerField8b);
310
311#[rustfmt::skip]
312const BINARY_TOWER_8B_INVERT_MAP : [u8; 256] = [
313 0x00, 0x01, 0x03, 0x02, 0x06, 0x0e, 0x04, 0x0f, 0x0d, 0x0a, 0x09, 0x0c, 0x0b, 0x08, 0x05, 0x07,
314 0x14, 0x67, 0x94, 0x7b, 0x10, 0x66, 0x9e, 0x7e, 0xd2, 0x81, 0x27, 0x4b, 0xd1, 0x8f, 0x2f, 0x42,
315 0x3c, 0xe6, 0xde, 0x7c, 0xb3, 0xc1, 0x4a, 0x1a, 0x30, 0xe9, 0xdd, 0x79, 0xb1, 0xc6, 0x43, 0x1e,
316 0x28, 0xe8, 0x9d, 0xb9, 0x63, 0x39, 0x8d, 0xc2, 0x62, 0x35, 0x83, 0xc5, 0x20, 0xe7, 0x97, 0xbb,
317 0x61, 0x48, 0x1f, 0x2e, 0xac, 0xc8, 0xbc, 0x56, 0x41, 0x60, 0x26, 0x1b, 0xcf, 0xaa, 0x5b, 0xbe,
318 0xef, 0x73, 0x6d, 0x5e, 0xf7, 0x86, 0x47, 0xbd, 0x88, 0xfc, 0xbf, 0x4e, 0x76, 0xe0, 0x53, 0x6c,
319 0x49, 0x40, 0x38, 0x34, 0xe4, 0xeb, 0x15, 0x11, 0x8b, 0x85, 0xaf, 0xa9, 0x5f, 0x52, 0x98, 0x92,
320 0xfb, 0xb5, 0xee, 0x51, 0xb7, 0xf0, 0x5c, 0xe1, 0xdc, 0x2b, 0x95, 0x13, 0x23, 0xdf, 0x17, 0x9f,
321 0xd3, 0x19, 0xc4, 0x3a, 0x8a, 0x69, 0x55, 0xf6, 0x58, 0xfd, 0x84, 0x68, 0xc3, 0x36, 0xd0, 0x1d,
322 0xa6, 0xf3, 0x6f, 0x99, 0x12, 0x7a, 0xba, 0x3e, 0x6e, 0x93, 0xa0, 0xf8, 0xb8, 0x32, 0x16, 0x7f,
323 0x9a, 0xf9, 0xe2, 0xdb, 0xed, 0xd8, 0x90, 0xf2, 0xae, 0x6b, 0x4d, 0xce, 0x44, 0xc9, 0xa8, 0x6a,
324 0xc7, 0x2c, 0xc0, 0x24, 0xfa, 0x71, 0xf1, 0x74, 0x9c, 0x33, 0x96, 0x3f, 0x46, 0x57, 0x4f, 0x5a,
325 0xb2, 0x25, 0x37, 0x8c, 0x82, 0x3b, 0x2d, 0xb0, 0x45, 0xad, 0xd7, 0xff, 0xf4, 0xd4, 0xab, 0x4c,
326 0x8e, 0x1c, 0x18, 0x80, 0xcd, 0xf5, 0xfe, 0xca, 0xa5, 0xec, 0xe3, 0xa3, 0x78, 0x2a, 0x22, 0x7d,
327 0x5d, 0x77, 0xa2, 0xda, 0x64, 0xea, 0x21, 0x3d, 0x31, 0x29, 0xe5, 0x65, 0xd9, 0xa4, 0x72, 0x50,
328 0x75, 0xb6, 0xa7, 0x91, 0xcc, 0xd5, 0x87, 0x54, 0x9b, 0xa1, 0xb4, 0x70, 0x59, 0x89, 0xd6, 0xcb,
329];
330
331impl_unary_ops!(TaggedInvertOrZero, invert_or_zero, BINARY_TOWER_8B_INVERT_MAP, BinaryField8b);
332impl_unary_ops!(TaggedInvertOrZero, invert_or_zero, BINARY_TOWER_8B_INVERT_MAP, BinaryField4b);
333impl_unary_ops!(TaggedInvertOrZero, invert_or_zero, BINARY_TOWER_8B_INVERT_MAP, BinaryField2b);
334
335#[rustfmt::skip]
336const AES_TOWER_8B_INVERT_MAP: [u8; 256] = [
337 0x00, 0x01, 0x8d, 0xf6, 0xcb, 0x52, 0x7b, 0xd1, 0xe8, 0x4f, 0x29, 0xc0, 0xb0, 0xe1, 0xe5, 0xc7,
338 0x74, 0xb4, 0xaa, 0x4b, 0x99, 0x2b, 0x60, 0x5f, 0x58, 0x3f, 0xfd, 0xcc, 0xff, 0x40, 0xee, 0xb2,
339 0x3a, 0x6e, 0x5a, 0xf1, 0x55, 0x4d, 0xa8, 0xc9, 0xc1, 0x0a, 0x98, 0x15, 0x30, 0x44, 0xa2, 0xc2,
340 0x2c, 0x45, 0x92, 0x6c, 0xf3, 0x39, 0x66, 0x42, 0xf2, 0x35, 0x20, 0x6f, 0x77, 0xbb, 0x59, 0x19,
341 0x1d, 0xfe, 0x37, 0x67, 0x2d, 0x31, 0xf5, 0x69, 0xa7, 0x64, 0xab, 0x13, 0x54, 0x25, 0xe9, 0x09,
342 0xed, 0x5c, 0x05, 0xca, 0x4c, 0x24, 0x87, 0xbf, 0x18, 0x3e, 0x22, 0xf0, 0x51, 0xec, 0x61, 0x17,
343 0x16, 0x5e, 0xaf, 0xd3, 0x49, 0xa6, 0x36, 0x43, 0xf4, 0x47, 0x91, 0xdf, 0x33, 0x93, 0x21, 0x3b,
344 0x79, 0xb7, 0x97, 0x85, 0x10, 0xb5, 0xba, 0x3c, 0xb6, 0x70, 0xd0, 0x06, 0xa1, 0xfa, 0x81, 0x82,
345 0x83, 0x7e, 0x7f, 0x80, 0x96, 0x73, 0xbe, 0x56, 0x9b, 0x9e, 0x95, 0xd9, 0xf7, 0x02, 0xb9, 0xa4,
346 0xde, 0x6a, 0x32, 0x6d, 0xd8, 0x8a, 0x84, 0x72, 0x2a, 0x14, 0x9f, 0x88, 0xf9, 0xdc, 0x89, 0x9a,
347 0xfb, 0x7c, 0x2e, 0xc3, 0x8f, 0xb8, 0x65, 0x48, 0x26, 0xc8, 0x12, 0x4a, 0xce, 0xe7, 0xd2, 0x62,
348 0x0c, 0xe0, 0x1f, 0xef, 0x11, 0x75, 0x78, 0x71, 0xa5, 0x8e, 0x76, 0x3d, 0xbd, 0xbc, 0x86, 0x57,
349 0x0b, 0x28, 0x2f, 0xa3, 0xda, 0xd4, 0xe4, 0x0f, 0xa9, 0x27, 0x53, 0x04, 0x1b, 0xfc, 0xac, 0xe6,
350 0x7a, 0x07, 0xae, 0x63, 0xc5, 0xdb, 0xe2, 0xea, 0x94, 0x8b, 0xc4, 0xd5, 0x9d, 0xf8, 0x90, 0x6b,
351 0xb1, 0x0d, 0xd6, 0xeb, 0xc6, 0x0e, 0xcf, 0xad, 0x08, 0x4e, 0xd7, 0xe3, 0x5d, 0x50, 0x1e, 0xb3,
352 0x5b, 0x23, 0x38, 0x34, 0x68, 0x46, 0x03, 0x8c, 0xdd, 0x9c, 0x7d, 0xa0, 0xcd, 0x1a, 0x41, 0x1c,
353];
354
355impl_unary_ops!(TaggedInvertOrZero, invert_or_zero, AES_TOWER_8B_INVERT_MAP, AESTowerField8b);
356
357#[cfg(test)]
358mod tests {
359 use super::*;
360 use crate::test_utils::{
361 define_invert_tests, define_mul_alpha_tests, define_multiply_tests, define_square_tests,
362 };
363
364 define_multiply_tests!(TaggedMul<PairwiseTableStrategy>::mul, TaggedMul<PairwiseTableStrategy>);
365
366 define_square_tests!(
367 TaggedSquare<PairwiseTableStrategy>::square,
368 TaggedSquare<PairwiseTableStrategy>
369 );
370
371 define_invert_tests!(
372 TaggedInvertOrZero<PairwiseTableStrategy>::invert_or_zero,
373 TaggedInvertOrZero<PairwiseTableStrategy>
374 );
375
376 define_mul_alpha_tests!(
377 TaggedMulAlpha<PairwiseTableStrategy>::mul_alpha,
378 TaggedMulAlpha<PairwiseTableStrategy>
379 );
380}