1const SBOX: [u8; 256] = [
31 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
32 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
33 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
34 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
35 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
36 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
37 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
38 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
39 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
40 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
41 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
42 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
43 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
44 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
45 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
46 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
47];
48
49const INV_SBOX: [u8; 256] = {
51 let mut inv = [0u8; 256];
52 let mut x = 0usize;
53 while x < 256 {
54 let mut i = 0usize;
55 loop {
56 if SBOX[i] as usize == x {
57 inv[x] = i as u8;
58 break;
59 }
60 i += 1;
61 }
62 x += 1;
63 }
64 inv
65};
66
67fn xtime(x: u8) -> u8 {
69 let hi = ((x >> 7) & 1).wrapping_neg();
70 (x << 1) ^ (hi & 0x1b)
71}
72
73fn gf_mul(mut a: u8, mut b: u8) -> u8 {
75 let mut p = 0u8;
76 for _ in 0..8 {
77 p ^= a & ((b & 1).wrapping_neg());
78 let hi = ((a >> 7) & 1).wrapping_neg();
79 a = (a << 1) ^ (hi & 0x1b);
80 b >>= 1;
81 }
82 p
83}
84
85#[inline]
88fn ct_table_lookup(table: &[u8; 256], x: u8) -> u8 {
89 let mut acc = 0u8;
90 for (i, &entry) in table.iter().enumerate() {
91 let eq = (((i as u8) ^ x) == 0) as u8;
92 acc |= entry & eq.wrapping_neg();
93 }
94 acc
95}
96
97#[inline]
98fn sbox(x: u8) -> u8 {
99 ct_table_lookup(&SBOX, x)
100}
101
102#[inline]
103#[cfg(test)]
106fn inv_sbox(x: u8) -> u8 {
107 ct_table_lookup(&INV_SBOX, x)
108}
109
110#[inline]
116fn sub_bytes(s: &mut [u8; 16]) {
117 let mut acc = [0u8; 16];
118 for (i, &entry) in SBOX.iter().enumerate() {
119 let idx = i as u8;
120 for (a, &x) in acc.iter_mut().zip(s.iter()) {
121 let eq = ((x == idx) as u8).wrapping_neg();
122 *a |= entry & eq;
123 }
124 }
125 *s = acc;
126}
127
128#[inline]
131fn inv_sub_bytes(s: &mut [u8; 16]) {
132 let mut acc = [0u8; 16];
133 for (i, &entry) in INV_SBOX.iter().enumerate() {
134 let idx = i as u8;
135 for (a, &x) in acc.iter_mut().zip(s.iter()) {
136 let eq = ((x == idx) as u8).wrapping_neg();
137 *a |= entry & eq;
138 }
139 }
140 *s = acc;
141}
142
143fn sub_word(w: [u8; 4]) -> [u8; 4] {
144 [sbox(w[0]), sbox(w[1]), sbox(w[2]), sbox(w[3])]
145}
146
147macro_rules! aes_impl {
148 ($name:ident, $nk:expr, $nr:expr, $doc:expr) => {
149 #[doc = $doc]
150 #[derive(Clone)]
151 pub struct $name {
152 rk: Vec<u8>,
154 rk_planes: Vec<[Planes; 16]>,
159 }
160
161 impl $name {
162 pub const KEY_LEN: usize = $nk * 4;
164 const NR: usize = $nr;
165
166 pub fn new(key: &[u8; $nk * 4]) -> Self {
168 let total = 16 * ($nr + 1);
169 let mut rk = vec![0u8; total];
170 let nk_bytes = $nk * 4;
171 rk[..nk_bytes].copy_from_slice(key);
172
173 let mut rcon = 1u8;
174 let mut i = nk_bytes;
175 while i < total {
176 let mut t: [u8; 4] = rk[i - 4..i].try_into().unwrap();
177 if i % nk_bytes == 0 {
178 t = sub_word([t[1], t[2], t[3], t[0]]);
179 t[0] ^= rcon;
180 rcon = xtime(rcon);
181 } else if $nk > 6 && i % nk_bytes == 16 {
182 t = sub_word(t);
183 }
184 for j in 0..4 {
185 rk[i + j] = rk[i - nk_bytes + j] ^ t[j];
186 }
187 i += 4;
188 }
189 let mut rk_planes = Vec::with_capacity($nr + 1);
190 for round in 0..=$nr {
191 let mut planes = [[0u64; 8]; 16];
192 for g in 0..16 {
193 for (b, plane) in planes[g].iter_mut().enumerate() {
194 *plane = u64::from((rk[round * 16 + g] >> b) & 1).wrapping_neg();
195 }
196 }
197 rk_planes.push(planes);
198 }
199 Self { rk, rk_planes }
200 }
201
202 fn add_round_key(&self, state: &mut [u8; 16], round: usize) {
203 for j in 0..16 {
204 state[j] ^= self.rk[round * 16 + j];
205 }
206 }
207
208 pub fn encrypt_block(&self, block: &mut [u8; 16]) {
214 let mut s = *block;
215 self.add_round_key(&mut s, 0);
216 for round in 1..Self::NR {
217 sub_bytes(&mut s);
218 shift_rows(&mut s);
219 mix_columns(&mut s);
220 self.add_round_key(&mut s, round);
221 }
222 sub_bytes(&mut s);
223 shift_rows(&mut s);
224 self.add_round_key(&mut s, Self::NR);
225 *block = s;
226 }
227
228 pub fn decrypt_block(&self, block: &mut [u8; 16]) {
230 let mut s = *block;
231 self.add_round_key(&mut s, Self::NR);
232 for round in (1..Self::NR).rev() {
233 inv_shift_rows(&mut s);
234 inv_sub_bytes(&mut s);
235 self.add_round_key(&mut s, round);
236 inv_mix_columns(&mut s);
237 }
238 inv_shift_rows(&mut s);
239 inv_sub_bytes(&mut s);
240 self.add_round_key(&mut s, 0);
241 *block = s;
242 }
243
244 #[allow(dead_code)]
255 pub(crate) fn encrypt_ctr_batch(&self, base: [u8; 16], n: usize, out: &mut [u8]) {
256 debug_assert!(n > 0 && n <= CTR_BATCH_BLOCKS && out.len() >= n * 16);
257 #[cfg(feature = "simd")]
258 {
259 if n <= 64 {
260 encrypt_ctr_batch_p::<u64>(&self.rk_planes, base, n, out)
261 } else if n <= 128 {
262 encrypt_ctr_batch_p::<Simd<u64, 2>>(&self.rk_planes, base, n, out)
263 } else if n <= 256 {
264 encrypt_ctr_batch_p::<Simd<u64, 4>>(&self.rk_planes, base, n, out)
265 } else {
266 encrypt_ctr_batch_p::<Simd<u64, 8>>(&self.rk_planes, base, n, out)
267 }
268 }
269 #[cfg(not(feature = "simd"))]
270 encrypt_ctr_batch_p::<u64>(&self.rk_planes, base, n, out);
271 }
272 }
273
274 impl Drop for $name {
275 fn drop(&mut self) {
276 self.rk.fill(0);
277 self.rk_planes.fill([[0u64; 8]; 16]);
278 }
279 }
280
281 impl std::fmt::Debug for $name {
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 f.write_str(stringify!($name))
284 }
285 }
286 };
287}
288
289use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
309
310#[cfg(feature = "simd")]
311use std::simd::Simd;
312
313trait Plane:
320 Copy
321 + BitAnd<Output = Self>
322 + BitOr<Output = Self>
323 + BitXor<Output = Self>
324 + Not<Output = Self>
325 + BitAndAssign
326 + BitOrAssign
327 + BitXorAssign
328{
329 const LANES: usize;
331 fn broadcast(x: u64) -> Self;
334 fn from_lane_groups(f: impl FnMut(usize) -> u64) -> Self;
336 fn to_lane_group(self, e: usize) -> u64;
338}
339
340impl Plane for u64 {
341 const LANES: usize = 64;
342 #[inline]
343 fn broadcast(x: u64) -> Self {
344 x
345 }
346 #[inline]
347 fn from_lane_groups(mut f: impl FnMut(usize) -> u64) -> Self {
348 f(0)
349 }
350 #[inline]
351 fn to_lane_group(self, e: usize) -> u64 {
352 debug_assert_eq!(e, 0);
353 self
354 }
355}
356
357#[cfg(feature = "simd")]
360impl<const L: usize> Plane for Simd<u64, L> {
361 const LANES: usize = 64 * L;
362 #[inline]
363 fn broadcast(x: u64) -> Self {
364 Simd::splat(x)
365 }
366 #[inline]
367 fn from_lane_groups(f: impl FnMut(usize) -> u64) -> Self {
368 Simd::from_array(core::array::from_fn(f))
369 }
370 #[inline]
371 fn to_lane_group(self, e: usize) -> u64 {
372 self.to_array()[e]
373 }
374}
375
376type Planes = [u64; 8];
378
379#[cfg(feature = "simd")]
383pub(crate) const CTR_BATCH_BLOCKS: usize = 512;
384#[cfg(not(feature = "simd"))]
385pub(crate) const CTR_BATCH_BLOCKS: usize = 64;
386
387fn bs_mul<P: Plane>(a: &[P; 8], b: &[P; 8]) -> [P; 8] {
392 let mut t = [P::broadcast(0); 15];
393 for i in 0..8 {
394 for j in 0..8 {
395 t[i + j] ^= a[i] & b[j];
396 }
397 }
398 [
399 t[0] ^ t[8] ^ t[12] ^ t[13],
400 t[1] ^ t[8] ^ t[9] ^ t[12] ^ t[14],
401 t[2] ^ t[9] ^ t[10] ^ t[13],
402 t[3] ^ t[8] ^ t[10] ^ t[11] ^ t[12] ^ t[13] ^ t[14],
403 t[4] ^ t[8] ^ t[9] ^ t[11] ^ t[14],
404 t[5] ^ t[9] ^ t[10] ^ t[12],
405 t[6] ^ t[10] ^ t[11] ^ t[13],
406 t[7] ^ t[11] ^ t[12] ^ t[14],
407 ]
408}
409
410fn bs_sq<P: Plane>(a: &[P; 8]) -> [P; 8] {
413 [
414 a[0] ^ a[4] ^ a[6],
415 a[4] ^ a[6] ^ a[7],
416 a[1] ^ a[5],
417 a[4] ^ a[5] ^ a[6] ^ a[7],
418 a[2] ^ a[4] ^ a[7],
419 a[5] ^ a[6],
420 a[3] ^ a[5],
421 a[6] ^ a[7],
422 ]
423}
424
425fn bs_xtime<P: Plane>(a: &[P; 8]) -> [P; 8] {
427 [
428 a[7],
429 a[0] ^ a[7],
430 a[1],
431 a[2] ^ a[7],
432 a[3] ^ a[7],
433 a[4],
434 a[5],
435 a[6],
436 ]
437}
438
439fn bs_sbox<P: Plane>(x: &mut [P; 8]) {
441 let a = *x;
442 let x2 = bs_sq(&a);
444 let x3 = bs_mul(&a, &x2); let x6 = bs_sq(&x3);
446 let x12 = bs_sq(&x6);
447 let x24 = bs_sq(&x12);
448 let x48 = bs_sq(&x24);
449 let x96 = bs_sq(&x48);
450 let x192 = bs_sq(&x96);
451 let x4 = bs_sq(&x2);
452 let x7 = bs_mul(&x3, &x4); let x14 = bs_sq(&x7);
454 let t = bs_mul(&x192, &x48);
455 let inv = bs_mul(&t, &x14); for i in 0..8 {
458 let mut s =
459 inv[i] ^ inv[(i + 4) % 8] ^ inv[(i + 5) % 8] ^ inv[(i + 6) % 8] ^ inv[(i + 7) % 8];
460 if (0x63 >> i) & 1 == 1 {
461 s = !s; }
463 x[i] = s;
464 }
465}
466
467fn bs_rounds<P: Plane>(st: &mut [[P; 8]; 16], rk_planes: &[[Planes; 16]]) {
472 for rk in &rk_planes[1..rk_planes.len() - 1] {
473 for group in st.iter_mut() {
474 bs_sbox(group);
475 }
476 bs_shift_rows(st);
477 bs_mix_columns(st);
478 for (sg, rg) in st.iter_mut().zip(rk.iter()) {
479 for (s, r) in sg.iter_mut().zip(rg.iter()) {
480 *s ^= P::broadcast(*r);
481 }
482 }
483 }
484 for group in st.iter_mut() {
485 bs_sbox(group);
486 }
487 bs_shift_rows(st);
488 let rk = &rk_planes[rk_planes.len() - 1];
489 for (sg, rg) in st.iter_mut().zip(rk.iter()) {
490 for (s, r) in sg.iter_mut().zip(rg.iter()) {
491 *s ^= P::broadcast(*r);
492 }
493 }
494}
495
496fn bs_shift_rows<P: Plane>(s: &mut [[P; 8]; 16]) {
498 let t = *s;
499 for row in 1..4 {
500 for col in 0..4 {
501 s[4 * col + row] = t[4 * ((col + row) % 4) + row];
502 }
503 }
504}
505
506fn bs_mix_columns<P: Plane>(s: &mut [[P; 8]; 16]) {
508 for c in 0..4 {
509 let o = 4 * c;
510 let (a0, a1, a2, a3) = (s[o], s[o + 1], s[o + 2], s[o + 3]);
511 let xt0 = bs_xtime(&a0);
512 let xt1 = bs_xtime(&a1);
513 let xt2 = bs_xtime(&a2);
514 let xt3 = bs_xtime(&a3);
515 for b in 0..8 {
516 s[o][b] = xt0[b] ^ xt1[b] ^ a1[b] ^ a2[b] ^ a3[b];
517 s[o + 1][b] = a0[b] ^ xt1[b] ^ xt2[b] ^ a2[b] ^ a3[b];
518 s[o + 2][b] = a0[b] ^ a1[b] ^ xt2[b] ^ xt3[b] ^ a3[b];
519 s[o + 3][b] = xt0[b] ^ a0[b] ^ a1[b] ^ a2[b] ^ xt3[b];
520 }
521 }
522}
523
524fn ctr_group_planes(ctr0: u32, e: usize, n: usize) -> [[u64; 8]; 16] {
527 let mut grp = [[0u64; 8]; 16];
528 for i in 0..64usize {
529 let lane = e * 64 + i;
530 if lane < n {
531 let ctr = ctr0.wrapping_add(lane as u32).to_be_bytes();
532 for k in 0..4 {
533 for (b, slot) in grp[12 + k].iter_mut().enumerate() {
534 *slot |= u64::from((ctr[k] >> b) & 1) << i;
535 }
536 }
537 }
538 }
539 grp
540}
541
542fn encrypt_ctr_batch_p<P: Plane>(
549 rk_planes: &[[Planes; 16]],
550 base: [u8; 16],
551 n: usize,
552 out: &mut [u8],
553) {
554 debug_assert!(n > 0 && n <= P::LANES && out.len() >= n * 16);
555
556 let mut st = [[P::broadcast(0); 8]; 16];
558 for (g, byte) in base[..12].iter().enumerate() {
559 for (b, plane) in st[g].iter_mut().enumerate() {
560 *plane = P::broadcast(u64::from((byte >> b) & 1).wrapping_neg());
561 }
562 }
563 let ctr0 = u32::from_be_bytes(base[12..16].try_into().unwrap());
565 let ng = P::LANES / 64;
566 let mut groups = [[[0u64; 8]; 16]; 8]; for (e, slot) in groups.iter_mut().enumerate().take(ng) {
568 *slot = ctr_group_planes(ctr0, e, n);
569 }
570 for g in 12..16 {
571 for (b, slot) in st[g].iter_mut().enumerate() {
572 *slot = P::from_lane_groups(|e| groups[e][g][b]);
573 }
574 }
575
576 let rk0 = &rk_planes[0];
578 for (sg, rg) in st.iter_mut().zip(rk0.iter()) {
579 for (s, r) in sg.iter_mut().zip(rg.iter()) {
580 *s ^= P::broadcast(*r);
581 }
582 }
583 bs_rounds(&mut st, rk_planes);
584
585 for e in 0..ng {
587 let grp = st.map(|g8| {
588 let mut grp8 = [0u64; 8];
589 for (slot, p) in grp8.iter_mut().zip(g8.iter()) {
590 *slot = p.to_lane_group(e);
591 }
592 grp8
593 });
594 for i in 0..64usize {
595 let lane = e * 64 + i;
596 if lane >= n {
597 continue; }
599 for (g, group) in grp.iter().enumerate() {
600 let mut byte = 0u8;
601 for (b, plane) in group.iter().enumerate() {
602 byte |= (((plane >> i) & 1) as u8) << b;
603 }
604 out[lane * 16 + g] = byte;
605 }
606 }
607 }
608}
609
610fn shift_rows(s: &mut [u8; 16]) {
611 let t = *s;
613 for row in 1..4 {
614 for col in 0..4 {
615 s[4 * col + row] = t[4 * ((col + row) % 4) + row];
616 }
617 }
618}
619
620fn inv_shift_rows(s: &mut [u8; 16]) {
621 let t = *s;
622 for row in 1..4 {
623 for col in 0..4 {
624 s[4 * ((col + row) % 4) + row] = t[4 * col + row];
625 }
626 }
627}
628
629fn mix_columns(s: &mut [u8; 16]) {
630 for c in 0..4 {
631 let o = 4 * c;
632 let (a0, a1, a2, a3) = (s[o], s[o + 1], s[o + 2], s[o + 3]);
633 s[o] = xtime(a0) ^ xtime(a1) ^ a1 ^ a2 ^ a3;
635 s[o + 1] = a0 ^ xtime(a1) ^ xtime(a2) ^ a2 ^ a3;
636 s[o + 2] = a0 ^ a1 ^ xtime(a2) ^ xtime(a3) ^ a3;
637 s[o + 3] = xtime(a0) ^ a0 ^ a1 ^ a2 ^ xtime(a3);
638 }
639}
640
641fn inv_mix_columns(s: &mut [u8; 16]) {
642 for c in 0..4 {
643 let o = 4 * c;
644 let (a0, a1, a2, a3) = (s[o], s[o + 1], s[o + 2], s[o + 3]);
645 s[o] = gf_mul(a0, 14) ^ gf_mul(a1, 11) ^ gf_mul(a2, 13) ^ gf_mul(a3, 9);
646 s[o + 1] = gf_mul(a0, 9) ^ gf_mul(a1, 14) ^ gf_mul(a2, 11) ^ gf_mul(a3, 13);
647 s[o + 2] = gf_mul(a0, 13) ^ gf_mul(a1, 9) ^ gf_mul(a2, 14) ^ gf_mul(a3, 11);
648 s[o + 3] = gf_mul(a0, 11) ^ gf_mul(a1, 13) ^ gf_mul(a2, 9) ^ gf_mul(a3, 14);
649 }
650}
651
652aes_impl!(Aes128, 4, 10, "AES-128 块密码实例。");
653aes_impl!(Aes192, 6, 12, "AES-192 块密码实例。");
654aes_impl!(Aes256, 8, 14, "AES-256 块密码实例。");
655
656#[cfg(test)]
657mod tests {
658 use super::*;
659
660 #[test]
661 fn sbox_known_values_and_bijection() {
662 assert_eq!(sbox(0x00), 0x63);
664 assert_eq!(sbox(0x01), 0x7c);
665 assert_eq!(sbox(0x53), 0xed);
666 assert_eq!(sbox(0xff), 0x16);
667 for (x, &official) in SBOX.iter().enumerate() {
669 assert_eq!(sbox(x as u8), official, "sbox({x:#04x})");
670 }
671 let mut seen = [false; 256];
672 for x in 0..=255u8 {
673 assert_eq!(inv_sbox(sbox(x)), x, "round trip at {x}");
674 seen[sbox(x) as usize] = true;
675 }
676 assert!(seen.iter().all(|&s| s), "sbox must be a bijection");
677 }
678
679 #[test]
680 fn fips197_appendix_c_kats() {
681 let mut key = [0u8; 16];
683 for (i, b) in key.iter_mut().enumerate() {
684 *b = i as u8;
685 }
686 let aes = Aes128::new(&key);
687 let mut block = [
688 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
689 0xee, 0xff,
690 ];
691 aes.encrypt_block(&mut block);
692 assert_eq!(
693 block,
694 [
695 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4,
696 0xc5, 0x5a
697 ]
698 );
699 aes.decrypt_block(&mut block);
700 assert_eq!(
701 block,
702 [
703 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
704 0xee, 0xff
705 ]
706 );
707
708 let mut key = [0u8; 32];
710 for (i, b) in key.iter_mut().enumerate() {
711 *b = i as u8;
712 }
713 let aes = Aes256::new(&key);
714 let mut block = [
715 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
716 0xee, 0xff,
717 ];
718 aes.encrypt_block(&mut block);
719 assert_eq!(
720 block,
721 [
722 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49,
723 0x60, 0x89
724 ]
725 );
726 aes.decrypt_block(&mut block);
727 assert_eq!(
728 block,
729 [
730 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
731 0xee, 0xff,
732 ]
733 );
734 }
735
736 #[test]
737 fn bitslice_circuits_match_scalar_exhaustive() {
738 let planes_of = |v: u8| -> Planes {
741 let mut p = [0u64; 8];
742 for (b, plane) in p.iter_mut().enumerate() {
743 *plane = u64::from((v >> b) & 1).wrapping_neg();
744 }
745 p
746 };
747 let byte_of = |p: &Planes| -> u8 {
748 let mut v = 0u8;
749 for (b, plane) in p.iter().enumerate() {
750 v |= ((plane & 1) as u8) << b;
751 }
752 v
753 };
754 for v in 0..=255u8 {
755 let a = planes_of(v);
756 assert_eq!(byte_of(&bs_sq(&a)), gf_mul(v, v), "sq({v:#04x})");
757 assert_eq!(byte_of(&bs_xtime(&a)), xtime(v), "xtime({v:#04x})");
758 let mut s = a;
759 bs_sbox(&mut s);
760 assert_eq!(byte_of(&s), sbox(v), "sbox({v:#04x})");
761 }
762 for x in 0..=255u8 {
764 for y in 0..=255u8 {
765 assert_eq!(
766 byte_of(&bs_mul(&planes_of(x), &planes_of(y))),
767 gf_mul(x, y),
768 "mul({x:#04x},{y:#04x})"
769 );
770 }
771 }
772 let mut lanes = [0u8; 64];
774 let mut seed = 0x9E37_79B9u32;
775 for v in lanes.iter_mut() {
776 seed ^= seed << 13;
777 seed ^= seed >> 17;
778 seed ^= seed << 5;
779 *v = seed as u8;
780 }
781 let mut group = [0u64; 8];
782 for (lane, &v) in lanes.iter().enumerate() {
783 for (b, plane) in group.iter_mut().enumerate() {
784 *plane |= u64::from((v >> b) & 1) << lane;
785 }
786 }
787 bs_sbox(&mut group);
788 for (lane, &v) in lanes.iter().enumerate() {
789 let mut got = 0u8;
790 for (b, plane) in group.iter().enumerate() {
791 got |= (((plane >> lane) & 1) as u8) << b;
792 }
793 assert_eq!(got, sbox(v), "lane {lane}");
794 }
795 }
796
797 #[test]
798 fn sub_bytes_matches_scalar() {
799 let mut seed = 0x243F_6A88u32;
803 let mut next = || {
804 seed ^= seed << 13;
805 seed ^= seed >> 17;
806 seed ^= seed << 5;
807 seed
808 };
809 let mut states = vec![[0u8; 16], [0xff; 16], [0x53; 16]];
810 for _ in 0..64 {
811 states.push(core::array::from_fn(|_| next() as u8));
812 }
813 for st in &states {
814 let mut fwd = *st;
815 sub_bytes(&mut fwd);
816 let mut inv = *st;
817 inv_sub_bytes(&mut inv);
818 for g in 0..16 {
819 assert_eq!(fwd[g], sbox(st[g]), "sub_bytes state={st:?} g={g}");
820 assert_eq!(inv[g], inv_sbox(st[g]), "inv_sub_bytes state={st:?} g={g}");
821 }
822 }
823 }
824
825 #[test]
826 fn encrypt_ctr_batch_matches_scalar() {
827 let mut key = [0u8; 16];
828 for (i, b) in key.iter_mut().enumerate() {
829 *b = i as u8;
830 }
831 let aes = Aes128::new(&key);
832 let mut key256 = [0u8; 32];
833 for (i, b) in key256.iter_mut().enumerate() {
834 *b = (i * 7) as u8;
835 }
836 let aes256 = Aes256::new(&key256);
837 let mut base = [
838 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0x00, 0x00,
839 0x00, 0x01,
840 ];
841 #[cfg(feature = "simd")]
843 let sizes = [
844 1usize, 2, 3, 63, 64, 65, 100, 128, 129, 200, 256, 257, 300, 511, 512,
845 ];
846 #[cfg(not(feature = "simd"))]
847 let sizes = [1usize, 2, 3, 63, 64];
848 for n in sizes {
849 let mut fast = vec![0u8; CTR_BATCH_BLOCKS * 16];
850 aes.encrypt_ctr_batch(base, n, &mut fast);
851 let mut expect = vec![0u8; n * 16];
852 let ctr0 = u32::from_be_bytes(base[12..16].try_into().unwrap());
853 for i in 0..n {
854 let mut blk = base;
855 blk[12..16].copy_from_slice(&ctr0.wrapping_add(i as u32).to_be_bytes());
856 aes.encrypt_block(&mut blk);
857 expect[i * 16..(i + 1) * 16].copy_from_slice(&blk);
858 }
859 assert_eq!(&fast[..n * 16], &expect, "n={n} aes128");
860 let mut expect256 = vec![0u8; n * 16];
862 for i in 0..n {
863 let mut blk = base;
864 blk[12..16].copy_from_slice(&ctr0.wrapping_add(i as u32).to_be_bytes());
865 aes256.encrypt_block(&mut blk);
866 expect256[i * 16..(i + 1) * 16].copy_from_slice(&blk);
867 }
868 aes256.encrypt_ctr_batch(base, n, &mut fast);
869 assert_eq!(&fast[..n * 16], &expect256, "n={n} aes256");
870 }
871 base[12..16].copy_from_slice(&0xFFFF_FFFDu32.to_be_bytes());
873 let mut fast = vec![0u8; CTR_BATCH_BLOCKS * 16];
874 aes.encrypt_ctr_batch(base, 64, &mut fast);
875 let ctr0 = u32::from_be_bytes(base[12..16].try_into().unwrap());
876 for i in 0..64usize {
877 let mut blk = base;
878 blk[12..16].copy_from_slice(&ctr0.wrapping_add(i as u32).to_be_bytes());
879 aes.encrypt_block(&mut blk);
880 assert_eq!(&fast[i * 16..(i + 1) * 16], &blk, "wrap i={i}");
881 }
882 #[cfg(feature = "simd")]
883 {
884 let mut base = [
887 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xff, 0xff,
888 0xff, 0x00,
889 ];
890 let mut fast = vec![0u8; 512 * 16];
891 aes.encrypt_ctr_batch(base, 512, &mut fast);
892 let ctr0 = u32::from_be_bytes(base[12..16].try_into().unwrap());
893 for i in 0..512usize {
894 let mut blk = base;
895 blk[12..16].copy_from_slice(&ctr0.wrapping_add(i as u32).to_be_bytes());
896 aes.encrypt_block(&mut blk);
897 assert_eq!(&fast[i * 16..(i + 1) * 16], &blk, "wrap512 i={i}");
898 }
899 base[12..16].copy_from_slice(&0xFFFF_FFFDu32.to_be_bytes());
900 aes.encrypt_ctr_batch(base, 129, &mut fast);
901 let ctr0 = u32::from_be_bytes(base[12..16].try_into().unwrap());
902 for i in 0..129usize {
903 let mut blk = base;
904 blk[12..16].copy_from_slice(&ctr0.wrapping_add(i as u32).to_be_bytes());
905 aes.encrypt_block(&mut blk);
906 assert_eq!(&fast[i * 16..(i + 1) * 16], &blk, "wrap129 i={i}");
907 }
908 }
909 }
910}