1use std::{
2 arch::x86_64::{__m256i, __m512i, _mm256_xor_si256, _mm512_xor_si512},
3 mem::transmute,
4 ops::{BitAnd, BitOr, Shl, Shr},
5};
6
7use crate::{
8 ZERO,
9 constants::{EO, IP, IP_INVO, PC_1O, PC_2O, PO},
10 sboxes::{
11 sbox_avx2::{
12 s1_avx_2, s2_avx_2, s3_avx_2, s4_avx_2, s5_avx_2, s6_avx_2, s7_avx_2, s8_avx_2,
13 },
14 sbox_avx512::{
15 s1_avx_512, s2_avx_512, s3_avx_512, s4_avx_512, s5_avx_512, s6_avx_512, s7_avx_512,
16 s8_avx_512,
17 },
18 sbox_optimized::{s1, s2, s3, s4, s5, s6, s7, s8},
19 },
20};
21use bitsliced_op::transpose_64x64;
22use wide::u64x8;
23
24pub fn compute_pc1_optimized(k_slices: &[u64x8; 64]) -> ([u64x8; 28], [u64x8; 28]) {
27 let mut c0 = [ZERO; 28];
28 let mut d0 = [ZERO; 28];
29
30 for (i, &src) in PC_1O.iter().enumerate() {
31 if i < 28 {
32 c0[i] = k_slices[src as usize];
33 } else {
34 d0[i - 28] = k_slices[src as usize];
35 }
36 }
37
38 (c0, d0)
39}
40
41const SHIFTS: [u32; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
42
43pub fn create_subkeys_optimized(c0: &mut [u64x8; 28], d0: &mut [u64x8; 28]) -> [[u64x8; 48]; 16] {
44 let mut subkeys = [[ZERO; 48]; 16];
45
46 for (index, s) in SHIFTS.iter().enumerate() {
47 c0.rotate_left(*s as usize);
48 d0.rotate_left(*s as usize);
49 for (i, &src) in PC_2O.iter().enumerate() {
50 if src < 28 {
51 subkeys[index][i] = c0[src as usize]
52 } else {
53 subkeys[index][i] = d0[(src - 28) as usize];
54 }
55 }
56 }
57
58 subkeys
59}
60
61pub fn encrypt_optimized(plaintext: u64, subkeys: [[u64x8; 48]; 16], output: &mut [u64x8; 64]) {
63 let ip = permute_bits_pc(&IP, plaintext, 64);
64 let ip_bitsliced = transpose_64x64(&[ip; 64]);
66 let mut l: [u64x8; 32] = std::array::from_fn(|i| u64x8::splat(ip_bitsliced[i]));
67 let mut r: [u64x8; 32] = std::array::from_fn(|i| u64x8::splat(ip_bitsliced[i + 32]));
68
69 for i in 0..16 {
70 let (new_l, new_r) = feistel_function_optimized(l, r, subkeys[i]);
71 l = new_l;
72 r = new_r;
73 }
74 let mut r_l = [ZERO; 64];
75 r_l[..32].copy_from_slice(&r);
76 r_l[32..].copy_from_slice(&l);
77 for (i, &src) in IP_INVO.iter().enumerate() {
78 output[i] = r_l[src as usize];
79 }
80}
81
82#[inline(always)]
83fn feistel_function_optimized(
84 l: [u64x8; 32],
85 r: [u64x8; 32],
86 subkey: [u64x8; 48],
87) -> ([u64x8; 32], [u64x8; 32]) {
88 let new_l = r;
89 let mut e = [ZERO; 48];
90 for (i, &src) in EO.iter().enumerate() {
91 e[i] = r[src as usize];
92 }
93 for i in 0..48 {
94 e[i] ^= subkey[i];
95 }
96 let mut output: [u64x8; 32] = [ZERO; 32];
97
98 let s1_output = s1(e[0], e[1], e[2], e[3], e[4], e[5]);
99 let s2_output = s2(e[6], e[7], e[8], e[9], e[10], e[11]);
100 let s3_output = s3(e[12], e[13], e[14], e[15], e[16], e[17]);
101 let s4_output = s4(e[18], e[19], e[20], e[21], e[22], e[23]);
102 let s5_output = s5(e[24], e[25], e[26], e[27], e[28], e[29]);
103 let s6_output = s6(e[30], e[31], e[32], e[33], e[34], e[35]);
104 let s7_output = s7(e[36], e[37], e[38], e[39], e[40], e[41]);
105 let s8_output = s8(e[42], e[43], e[44], e[45], e[46], e[47]);
106 output[0] = s1_output.0;
108 output[1] = s1_output.1;
109 output[2] = s1_output.2;
110 output[3] = s1_output.3;
111
112 output[4] = s2_output.0;
114 output[5] = s2_output.1;
115 output[6] = s2_output.2;
116 output[7] = s2_output.3;
117
118 output[8] = s3_output.0;
120 output[9] = s3_output.1;
121 output[10] = s3_output.2;
122 output[11] = s3_output.3;
123
124 output[12] = s4_output.0;
126 output[13] = s4_output.1;
127 output[14] = s4_output.2;
128 output[15] = s4_output.3;
129
130 output[16] = s5_output.0;
132 output[17] = s5_output.1;
133 output[18] = s5_output.2;
134 output[19] = s5_output.3;
135
136 output[20] = s6_output.0;
138 output[21] = s6_output.1;
139 output[22] = s6_output.2;
140 output[23] = s6_output.3;
141
142 output[24] = s7_output.0;
144 output[25] = s7_output.1;
145 output[26] = s7_output.2;
146 output[27] = s7_output.3;
147
148 output[28] = s8_output.0;
150 output[29] = s8_output.1;
151 output[30] = s8_output.2;
152 output[31] = s8_output.3;
153 let mut new_r = [ZERO; 32];
154 for (i, &src) in PO.iter().enumerate() {
155 new_r[i] = output[src as usize];
156 }
157 for i in 0..32 {
159 new_r[i] = l[i] ^ new_r[i];
160 }
161 (new_l, new_r)
162}
163
164const SUBKEY_SCHEDULE: [[usize; 48]; 16] = [
165 [
167 9, 50, 33, 59, 48, 16, 32, 56, 1, 8, 18, 41, 2, 34, 25, 24, 43, 57, 58, 0, 35, 26, 17, 40,
168 21, 27, 38, 53, 36, 3, 46, 29, 4, 52, 22, 28, 60, 20, 37, 62, 14, 19, 44, 13, 12, 61, 54,
169 30,
170 ],
171 [
173 1, 42, 25, 51, 40, 8, 24, 48, 58, 0, 10, 33, 59, 26, 17, 16, 35, 49, 50, 57, 56, 18, 9, 32,
174 13, 19, 30, 45, 28, 62, 38, 21, 27, 44, 14, 20, 52, 12, 29, 54, 6, 11, 36, 5, 4, 53, 46,
175 22,
176 ],
177 [
179 50, 26, 9, 35, 24, 57, 8, 32, 42, 49, 59, 17, 43, 10, 1, 0, 48, 33, 34, 41, 40, 2, 58, 16,
180 60, 3, 14, 29, 12, 46, 22, 5, 11, 28, 61, 4, 36, 27, 13, 38, 53, 62, 20, 52, 19, 37, 30, 6,
181 ],
182 [
184 34, 10, 58, 48, 8, 41, 57, 16, 26, 33, 43, 1, 56, 59, 50, 49, 32, 17, 18, 25, 24, 51, 42,
185 0, 44, 54, 61, 13, 27, 30, 6, 52, 62, 12, 45, 19, 20, 11, 60, 22, 37, 46, 4, 36, 3, 21, 14,
186 53,
187 ],
188 [
190 18, 59, 42, 32, 57, 25, 41, 0, 10, 17, 56, 50, 40, 43, 34, 33, 16, 1, 2, 9, 8, 35, 26, 49,
191 28, 38, 45, 60, 11, 14, 53, 36, 46, 27, 29, 3, 4, 62, 44, 6, 21, 30, 19, 20, 54, 5, 61, 37,
192 ],
193 [
195 2, 43, 26, 16, 41, 9, 25, 49, 59, 1, 40, 34, 24, 56, 18, 17, 0, 50, 51, 58, 57, 48, 10, 33,
196 12, 22, 29, 44, 62, 61, 37, 20, 30, 11, 13, 54, 19, 46, 28, 53, 5, 14, 3, 4, 38, 52, 45,
197 21,
198 ],
199 [
201 51, 56, 10, 0, 25, 58, 9, 33, 43, 50, 24, 18, 8, 40, 2, 1, 49, 34, 35, 42, 41, 32, 59, 17,
202 27, 6, 13, 28, 46, 45, 21, 4, 14, 62, 60, 38, 3, 30, 12, 37, 52, 61, 54, 19, 22, 36, 29, 5,
203 ],
204 [
206 35, 40, 59, 49, 9, 42, 58, 17, 56, 34, 8, 2, 57, 24, 51, 50, 33, 18, 48, 26, 25, 16, 43, 1,
207 11, 53, 60, 12, 30, 29, 5, 19, 61, 46, 44, 22, 54, 14, 27, 21, 36, 45, 38, 3, 6, 20, 13,
208 52,
209 ],
210 [
212 56, 32, 51, 41, 1, 34, 50, 9, 48, 26, 0, 59, 49, 16, 43, 42, 25, 10, 40, 18, 17, 8, 35, 58,
213 3, 45, 52, 4, 22, 21, 60, 11, 53, 38, 36, 14, 46, 6, 19, 13, 28, 37, 30, 62, 61, 12, 5, 44,
214 ],
215 [
217 40, 16, 35, 25, 50, 18, 34, 58, 32, 10, 49, 43, 33, 0, 56, 26, 9, 59, 24, 2, 1, 57, 48, 42,
218 54, 29, 36, 19, 6, 5, 44, 62, 37, 22, 20, 61, 30, 53, 3, 60, 12, 21, 14, 46, 45, 27, 52,
219 28,
220 ],
221 [
223 24, 0, 48, 9, 34, 2, 18, 42, 16, 59, 33, 56, 17, 49, 40, 10, 58, 43, 8, 51, 50, 41, 32, 26,
224 38, 13, 20, 3, 53, 52, 28, 46, 21, 6, 4, 45, 14, 37, 54, 44, 27, 5, 61, 30, 29, 11, 36, 12,
225 ],
226 [
228 8, 49, 32, 58, 18, 51, 2, 26, 0, 43, 17, 40, 1, 33, 24, 59, 42, 56, 57, 35, 34, 25, 16, 10,
229 22, 60, 4, 54, 37, 36, 12, 30, 5, 53, 19, 29, 61, 21, 38, 28, 11, 52, 45, 14, 13, 62, 20,
230 27,
231 ],
232 [
234 57, 33, 16, 42, 2, 35, 51, 10, 49, 56, 1, 24, 50, 17, 8, 43, 26, 40, 41, 48, 18, 9, 0, 59,
235 6, 44, 19, 38, 21, 20, 27, 14, 52, 37, 3, 13, 45, 5, 22, 12, 62, 36, 29, 61, 60, 46, 4, 11,
236 ],
237 [
239 41, 17, 0, 26, 51, 48, 35, 59, 33, 40, 50, 8, 34, 1, 57, 56, 10, 24, 25, 32, 2, 58, 49, 43,
240 53, 28, 3, 22, 5, 4, 11, 61, 36, 21, 54, 60, 29, 52, 6, 27, 46, 20, 13, 45, 44, 30, 19, 62,
241 ],
242 [
244 25, 1, 49, 10, 35, 32, 48, 43, 17, 24, 34, 57, 18, 50, 41, 40, 59, 8, 9, 16, 51, 42, 33,
245 56, 37, 12, 54, 6, 52, 19, 62, 45, 20, 5, 38, 44, 13, 36, 53, 11, 30, 4, 60, 29, 28, 14, 3,
246 46,
247 ],
248 [
250 17, 58, 41, 2, 56, 24, 40, 35, 9, 16, 26, 49, 10, 42, 33, 32, 51, 0, 1, 8, 43, 34, 25, 48,
251 29, 4, 46, 61, 44, 11, 54, 37, 12, 60, 30, 36, 5, 28, 45, 3, 22, 27, 52, 21, 20, 6, 62, 38,
252 ],
253];
254
255pub fn encrypt_simd(plaintext: u64, keys: &mut [u64x8; 64]) {
256 let ip = permute_bits_pc(&IP, plaintext, 64);
257 let mut l: [u64x8; 32] = [ZERO; 32];
258 let mut r: [u64x8; 32] = [ZERO; 32];
259 for i in 0..32 {
260 let bit_l = (ip >> (63 - i)) & 1;
261 let bit_r = (ip >> (31 - i)) & 1;
262
263 l[i] = u64x8::splat(0u64.wrapping_sub(bit_l));
264 r[i] = u64x8::splat(0u64.wrapping_sub(bit_r));
265 }
266
267 unsafe {
269 feistel_function_simd(&mut l, &mut r, keys, 0);
270 }
271 unsafe {
273 feistel_function_simd(&mut r, &mut l, keys, 1);
274 }
275 unsafe {
277 feistel_function_simd(&mut l, &mut r, keys, 2);
278 }
279 unsafe {
281 feistel_function_simd(&mut r, &mut l, keys, 3);
282 }
283 unsafe {
285 feistel_function_simd(&mut l, &mut r, keys, 4);
286 }
287 unsafe {
289 feistel_function_simd(&mut r, &mut l, keys, 5);
290 }
291 unsafe {
293 feistel_function_simd(&mut l, &mut r, keys, 6);
294 }
295 unsafe {
297 feistel_function_simd(&mut r, &mut l, keys, 7);
298 }
299 unsafe {
301 feistel_function_simd(&mut l, &mut r, keys, 8);
302 }
303 unsafe {
305 feistel_function_simd(&mut r, &mut l, keys, 9);
306 }
307 unsafe {
309 feistel_function_simd(&mut l, &mut r, keys, 10);
310 }
311 unsafe {
313 feistel_function_simd(&mut r, &mut l, keys, 11);
314 }
315 unsafe {
317 feistel_function_simd(&mut l, &mut r, keys, 12);
318 }
319 unsafe {
321 feistel_function_simd(&mut r, &mut l, keys, 13);
322 }
323 unsafe {
325 feistel_function_simd(&mut l, &mut r, keys, 14);
326 }
327 unsafe {
329 feistel_function_simd(&mut r, &mut l, keys, 15);
330 }
331
332 let keys_ptr = keys.as_mut_ptr();
334 for i in 0..64 {
335 unsafe {
336 std::ptr::write(
337 keys_ptr.add(i),
338 if IP_INVO[i] < 32 {
339 r[IP_INVO[i]]
340 } else {
341 l[IP_INVO[i] - 32]
342 },
343 );
344 }
345 }
346}
347
348#[inline(always)]
349pub unsafe fn feistel_function_simd(
350 l: &mut [u64x8; 32],
351 r: &mut [u64x8; 32],
352 keys: &[u64x8; 64],
353 round: usize,
354) {
355 let mut e0 = r[31] ^ keys[SUBKEY_SCHEDULE[round][0]];
357 let mut e1 = r[0] ^ keys[SUBKEY_SCHEDULE[round][1]];
358 let mut e2 = r[1] ^ keys[SUBKEY_SCHEDULE[round][2]];
359 let mut e3 = r[2] ^ keys[SUBKEY_SCHEDULE[round][3]];
360 let mut e4 = r[3] ^ keys[SUBKEY_SCHEDULE[round][4]];
361 let mut e5 = r[4] ^ keys[SUBKEY_SCHEDULE[round][5]];
362
363 let mut f0 = r[3] ^ keys[SUBKEY_SCHEDULE[round][6]];
365 let mut f1 = r[4] ^ keys[SUBKEY_SCHEDULE[round][7]];
366 let mut f2 = r[5] ^ keys[SUBKEY_SCHEDULE[round][8]];
367 let mut f3 = r[6] ^ keys[SUBKEY_SCHEDULE[round][9]];
368 let mut f4 = r[7] ^ keys[SUBKEY_SCHEDULE[round][10]];
369 let mut f5 = r[8] ^ keys[SUBKEY_SCHEDULE[round][11]];
370
371 let mut g0 = r[7] ^ keys[SUBKEY_SCHEDULE[round][12]];
373 let mut g1 = r[8] ^ keys[SUBKEY_SCHEDULE[round][13]];
374 let mut g2 = r[9] ^ keys[SUBKEY_SCHEDULE[round][14]];
375 let mut g3 = r[10] ^ keys[SUBKEY_SCHEDULE[round][15]];
376 let mut g4 = r[11] ^ keys[SUBKEY_SCHEDULE[round][16]];
377 let mut g5 = r[12] ^ keys[SUBKEY_SCHEDULE[round][17]];
378
379 let mut h0 = r[11] ^ keys[SUBKEY_SCHEDULE[round][18]];
381 let mut h1 = r[12] ^ keys[SUBKEY_SCHEDULE[round][19]];
382 let mut h2 = r[13] ^ keys[SUBKEY_SCHEDULE[round][20]];
383 let mut h3 = r[14] ^ keys[SUBKEY_SCHEDULE[round][21]];
384 let mut h4 = r[15] ^ keys[SUBKEY_SCHEDULE[round][22]];
385 let mut h5 = r[16] ^ keys[SUBKEY_SCHEDULE[round][23]];
386
387 {
390 let (o0, o1, o2, o3) = s1(e0, e1, e2, e3, e4, e5);
391 l[8] = l[8] ^ o0;
392 l[16] = l[16] ^ o1;
393 l[22] = l[22] ^ o2;
394 l[30] = l[30] ^ o3;
395 }
396
397 {
399 let (o0, o1, o2, o3) = s2(f0, f1, f2, f3, f4, f5);
400 l[12] = l[12] ^ o0;
401 l[27] = l[27] ^ o1;
402 l[1] = l[1] ^ o2;
403 l[17] = l[17] ^ o3;
404 }
405
406 {
408 let (o0, o1, o2, o3) = s3(g0, g1, g2, g3, g4, g5);
409 l[23] = l[23] ^ o0;
410 l[15] = l[15] ^ o1;
411 l[29] = l[29] ^ o2;
412 l[5] = l[5] ^ o3;
413 }
414
415 {
417 let (o0, o1, o2, o3) = s4(h0, h1, h2, h3, h4, h5);
418 l[25] = l[25] ^ o0;
419 l[19] = l[19] ^ o1;
420 l[9] = l[9] ^ o2;
421 l[0] = l[0] ^ o3;
422 }
423
424 e0 = r[15] ^ keys[SUBKEY_SCHEDULE[round][24]];
426 e1 = r[16] ^ keys[SUBKEY_SCHEDULE[round][25]];
427 e2 = r[17] ^ keys[SUBKEY_SCHEDULE[round][26]];
428 e3 = r[18] ^ keys[SUBKEY_SCHEDULE[round][27]];
429 e4 = r[19] ^ keys[SUBKEY_SCHEDULE[round][28]];
430 e5 = r[20] ^ keys[SUBKEY_SCHEDULE[round][29]];
431
432 f0 = r[19] ^ keys[SUBKEY_SCHEDULE[round][30]];
434 f1 = r[20] ^ keys[SUBKEY_SCHEDULE[round][31]];
435 f2 = r[21] ^ keys[SUBKEY_SCHEDULE[round][32]];
436 f3 = r[22] ^ keys[SUBKEY_SCHEDULE[round][33]];
437 f4 = r[23] ^ keys[SUBKEY_SCHEDULE[round][34]];
438 f5 = r[24] ^ keys[SUBKEY_SCHEDULE[round][35]];
439
440 g0 = r[23] ^ keys[SUBKEY_SCHEDULE[round][36]];
442 g1 = r[24] ^ keys[SUBKEY_SCHEDULE[round][37]];
443 g2 = r[25] ^ keys[SUBKEY_SCHEDULE[round][38]];
444 g3 = r[26] ^ keys[SUBKEY_SCHEDULE[round][39]];
445 g4 = r[27] ^ keys[SUBKEY_SCHEDULE[round][40]];
446 g5 = r[28] ^ keys[SUBKEY_SCHEDULE[round][41]];
447
448 h0 = r[27] ^ keys[SUBKEY_SCHEDULE[round][42]];
450 h1 = r[28] ^ keys[SUBKEY_SCHEDULE[round][43]];
451 h2 = r[29] ^ keys[SUBKEY_SCHEDULE[round][44]];
452 h3 = r[30] ^ keys[SUBKEY_SCHEDULE[round][45]];
453 h4 = r[31] ^ keys[SUBKEY_SCHEDULE[round][46]];
454 h5 = r[0] ^ keys[SUBKEY_SCHEDULE[round][47]];
455
456 {
458 let (o0, o1, o2, o3) = s5(e0, e1, e2, e3, e4, e5);
459 l[7] = l[7] ^ o0;
460 l[13] = l[13] ^ o1;
461 l[24] = l[24] ^ o2;
462 l[2] = l[2] ^ o3;
463 }
464
465 {
467 let (o0, o1, o2, o3) = s6(f0, f1, f2, f3, f4, f5);
468 l[3] = l[3] ^ o0;
469 l[28] = l[28] ^ o1;
470 l[10] = l[10] ^ o2;
471 l[18] = l[18] ^ o3;
472 }
473
474 {
476 let (o0, o1, o2, o3) = s7(g0, g1, g2, g3, g4, g5);
477 l[31] = l[31] ^ o0;
478 l[11] = l[11] ^ o1;
479 l[21] = l[21] ^ o2;
480 l[6] = l[6] ^ o3;
481 }
482
483 {
485 let (o0, o1, o2, o3) = s8(h0, h1, h2, h3, h4, h5);
486 l[4] = l[4] ^ o0;
487 l[26] = l[26] ^ o1;
488 l[14] = l[14] ^ o2;
489 l[20] = l[20] ^ o3;
490 }
491}
492
493const ALL_ONES_AVX: __m512i = unsafe { transmute([!0u64; 8]) };
494const ZERO_AVX: __m512i = unsafe { transmute([0u64; 8]) };
495
496#[inline(always)]
497pub fn encrypt_avx_512(keys: &mut [__m512i; 64]) {
498 let mut l: [__m512i; 32] = [
501 ZERO_AVX,
502 ALL_ONES_AVX,
503 ALL_ONES_AVX,
504 ALL_ONES_AVX,
505 ALL_ONES_AVX,
506 ZERO_AVX,
507 ZERO_AVX,
508 ZERO_AVX,
509 ZERO_AVX,
510 ALL_ONES_AVX,
511 ZERO_AVX,
512 ALL_ONES_AVX,
513 ZERO_AVX,
514 ALL_ONES_AVX,
515 ZERO_AVX,
516 ALL_ONES_AVX,
517 ZERO_AVX,
518 ALL_ONES_AVX,
519 ALL_ONES_AVX,
520 ALL_ONES_AVX,
521 ALL_ONES_AVX,
522 ZERO_AVX,
523 ZERO_AVX,
524 ZERO_AVX,
525 ZERO_AVX,
526 ALL_ONES_AVX,
527 ZERO_AVX,
528 ALL_ONES_AVX,
529 ZERO_AVX,
530 ALL_ONES_AVX,
531 ZERO_AVX,
532 ALL_ONES_AVX,
533 ];
534 let mut r: [__m512i; 32] = [
535 ALL_ONES_AVX,
536 ZERO_AVX,
537 ZERO_AVX,
538 ZERO_AVX,
539 ZERO_AVX,
540 ZERO_AVX,
541 ZERO_AVX,
542 ZERO_AVX,
543 ZERO_AVX,
544 ALL_ONES_AVX,
545 ALL_ONES_AVX,
546 ZERO_AVX,
547 ZERO_AVX,
548 ALL_ONES_AVX,
549 ALL_ONES_AVX,
550 ZERO_AVX,
551 ALL_ONES_AVX,
552 ZERO_AVX,
553 ZERO_AVX,
554 ZERO_AVX,
555 ZERO_AVX,
556 ZERO_AVX,
557 ZERO_AVX,
558 ZERO_AVX,
559 ZERO_AVX,
560 ALL_ONES_AVX,
561 ALL_ONES_AVX,
562 ZERO_AVX,
563 ZERO_AVX,
564 ALL_ONES_AVX,
565 ALL_ONES_AVX,
566 ZERO_AVX,
567 ];
568 unsafe {
570 feistel_avx_512(&mut l, &mut r, keys, 0);
571 }
572 unsafe {
574 feistel_avx_512(&mut r, &mut l, keys, 1);
575 }
576 unsafe {
578 feistel_avx_512(&mut l, &mut r, keys, 2);
579 }
580 unsafe {
582 feistel_avx_512(&mut r, &mut l, keys, 3);
583 }
584 unsafe {
586 feistel_avx_512(&mut l, &mut r, keys, 4);
587 }
588 unsafe {
590 feistel_avx_512(&mut r, &mut l, keys, 5);
591 }
592 unsafe {
594 feistel_avx_512(&mut l, &mut r, keys, 6);
595 }
596 unsafe {
598 feistel_avx_512(&mut r, &mut l, keys, 7);
599 }
600 unsafe {
602 feistel_avx_512(&mut l, &mut r, keys, 8);
603 }
604 unsafe {
606 feistel_avx_512(&mut r, &mut l, keys, 9);
607 }
608 unsafe {
610 feistel_avx_512(&mut l, &mut r, keys, 10);
611 }
612 unsafe {
614 feistel_avx_512(&mut r, &mut l, keys, 11);
615 }
616 unsafe {
618 feistel_avx_512(&mut l, &mut r, keys, 12);
619 }
620 unsafe {
622 feistel_avx_512(&mut r, &mut l, keys, 13);
623 }
624 unsafe {
626 feistel_avx_512(&mut l, &mut r, keys, 14);
627 }
628 unsafe {
630 feistel_avx_512(&mut r, &mut l, keys, 15);
631 }
632
633 unsafe {
635 let out = keys.as_mut_ptr();
636
637 *out.add(0) = l[7];
638 *out.add(1) = r[7];
639 *out.add(2) = l[15];
640 *out.add(3) = r[15];
641 *out.add(4) = l[23];
642 *out.add(5) = r[23];
643 *out.add(6) = l[31];
644 *out.add(7) = r[31];
645
646 *out.add(8) = l[6];
647 *out.add(9) = r[6];
648 *out.add(10) = l[14];
649 *out.add(11) = r[14];
650 *out.add(12) = l[22];
651 *out.add(13) = r[22];
652 *out.add(14) = l[30];
653 *out.add(15) = r[30];
654
655 *out.add(16) = l[5];
656 *out.add(17) = r[5];
657 *out.add(18) = l[13];
658 *out.add(19) = r[13];
659 *out.add(20) = l[21];
660 *out.add(21) = r[21];
661 *out.add(22) = l[29];
662 *out.add(23) = r[29];
663
664 *out.add(24) = l[4];
665 *out.add(25) = r[4];
666 *out.add(26) = l[12];
667 *out.add(27) = r[12];
668 *out.add(28) = l[20];
669 *out.add(29) = r[20];
670 *out.add(30) = l[28];
671 *out.add(31) = r[28];
672
673 *out.add(32) = l[3];
674 *out.add(33) = r[3];
675 *out.add(34) = l[11];
676 *out.add(35) = r[11];
677 *out.add(36) = l[19];
678 *out.add(37) = r[19];
679 *out.add(38) = l[27];
680 *out.add(39) = r[27];
681
682 *out.add(40) = l[2];
683 *out.add(41) = r[2];
684 *out.add(42) = l[10];
685 *out.add(43) = r[10];
686 *out.add(44) = l[18];
687 *out.add(45) = r[18];
688 *out.add(46) = l[26];
689 *out.add(47) = r[26];
690
691 *out.add(48) = l[1];
692 *out.add(49) = r[1];
693 *out.add(50) = l[9];
694 *out.add(51) = r[9];
695 *out.add(52) = l[17];
696 *out.add(53) = r[17];
697 *out.add(54) = l[25];
698 *out.add(55) = r[25];
699
700 *out.add(56) = l[0];
701 *out.add(57) = r[0];
702 *out.add(58) = l[8];
703 *out.add(59) = r[8];
704 *out.add(60) = l[16];
705 *out.add(61) = r[16];
706 *out.add(62) = l[24];
707 *out.add(63) = r[24];
708 }
709}
710
711#[inline(always)]
712pub unsafe fn feistel_avx_512(
713 l: &mut [__m512i; 32],
714 r: &mut [__m512i; 32],
715 keys: &[__m512i; 64],
716 round: usize,
717) {
718 unsafe {
719 let mut e0 = _mm512_xor_si512(r[31], keys[SUBKEY_SCHEDULE[round][0]]);
721 let mut e1 = _mm512_xor_si512(r[0], keys[SUBKEY_SCHEDULE[round][1]]);
722 let mut e2 = _mm512_xor_si512(r[1], keys[SUBKEY_SCHEDULE[round][2]]);
723 let mut e3 = _mm512_xor_si512(r[2], keys[SUBKEY_SCHEDULE[round][3]]);
724 let mut e4 = _mm512_xor_si512(r[3], keys[SUBKEY_SCHEDULE[round][4]]);
725 let mut e5 = _mm512_xor_si512(r[4], keys[SUBKEY_SCHEDULE[round][5]]);
726
727 let mut f0 = _mm512_xor_si512(r[3], keys[SUBKEY_SCHEDULE[round][6]]);
729 let mut f1 = _mm512_xor_si512(r[4], keys[SUBKEY_SCHEDULE[round][7]]);
730 let mut f2 = _mm512_xor_si512(r[5], keys[SUBKEY_SCHEDULE[round][8]]);
731 let mut f3 = _mm512_xor_si512(r[6], keys[SUBKEY_SCHEDULE[round][9]]);
732 let mut f4 = _mm512_xor_si512(r[7], keys[SUBKEY_SCHEDULE[round][10]]);
733 let mut f5 = _mm512_xor_si512(r[8], keys[SUBKEY_SCHEDULE[round][11]]);
734
735 let mut g0 = _mm512_xor_si512(r[7], keys[SUBKEY_SCHEDULE[round][12]]);
737 let mut g1 = _mm512_xor_si512(r[8], keys[SUBKEY_SCHEDULE[round][13]]);
738 let mut g2 = _mm512_xor_si512(r[9], keys[SUBKEY_SCHEDULE[round][14]]);
739 let mut g3 = _mm512_xor_si512(r[10], keys[SUBKEY_SCHEDULE[round][15]]);
740 let mut g4 = _mm512_xor_si512(r[11], keys[SUBKEY_SCHEDULE[round][16]]);
741 let mut g5 = _mm512_xor_si512(r[12], keys[SUBKEY_SCHEDULE[round][17]]);
742
743 let mut h0 = _mm512_xor_si512(r[11], keys[SUBKEY_SCHEDULE[round][18]]);
745 let mut h1 = _mm512_xor_si512(r[12], keys[SUBKEY_SCHEDULE[round][19]]);
746 let mut h2 = _mm512_xor_si512(r[13], keys[SUBKEY_SCHEDULE[round][20]]);
747 let mut h3 = _mm512_xor_si512(r[14], keys[SUBKEY_SCHEDULE[round][21]]);
748 let mut h4 = _mm512_xor_si512(r[15], keys[SUBKEY_SCHEDULE[round][22]]);
749 let mut h5 = _mm512_xor_si512(r[16], keys[SUBKEY_SCHEDULE[round][23]]);
750
751 {
754 let (o0, o1, o2, o3) = s1_avx_512(e0, e1, e2, e3, e4, e5);
755 l[8] = _mm512_xor_si512(l[8], o0);
756 l[16] = _mm512_xor_si512(l[16], o1);
757 l[22] = _mm512_xor_si512(l[22], o2);
758 l[30] = _mm512_xor_si512(l[30], o3);
759 }
760
761 {
763 let (o0, o1, o2, o3) = s2_avx_512(f0, f1, f2, f3, f4, f5);
764 l[12] = _mm512_xor_si512(l[12], o0);
765 l[27] = _mm512_xor_si512(l[27], o1);
766 l[1] = _mm512_xor_si512(l[1], o2);
767 l[17] = _mm512_xor_si512(l[17], o3);
768 }
769
770 {
772 let (o0, o1, o2, o3) = s3_avx_512(g0, g1, g2, g3, g4, g5);
773 l[23] = _mm512_xor_si512(l[23], o0);
774 l[15] = _mm512_xor_si512(l[15], o1);
775 l[29] = _mm512_xor_si512(l[29], o2);
776 l[5] = _mm512_xor_si512(l[5], o3);
777 }
778
779 {
781 let (o0, o1, o2, o3) = s4_avx_512(h0, h1, h2, h3, h4, h5);
782 l[25] = _mm512_xor_si512(l[25], o0);
783 l[19] = _mm512_xor_si512(l[19], o1);
784 l[9] = _mm512_xor_si512(l[9], o2);
785 l[0] = _mm512_xor_si512(l[0], o3);
786 }
787
788 e0 = _mm512_xor_si512(r[15], keys[SUBKEY_SCHEDULE[round][24]]);
790 e1 = _mm512_xor_si512(r[16], keys[SUBKEY_SCHEDULE[round][25]]);
791 e2 = _mm512_xor_si512(r[17], keys[SUBKEY_SCHEDULE[round][26]]);
792 e3 = _mm512_xor_si512(r[18], keys[SUBKEY_SCHEDULE[round][27]]);
793 e4 = _mm512_xor_si512(r[19], keys[SUBKEY_SCHEDULE[round][28]]);
794 e5 = _mm512_xor_si512(r[20], keys[SUBKEY_SCHEDULE[round][29]]);
795
796 f0 = _mm512_xor_si512(r[19], keys[SUBKEY_SCHEDULE[round][30]]);
798 f1 = _mm512_xor_si512(r[20], keys[SUBKEY_SCHEDULE[round][31]]);
799 f2 = _mm512_xor_si512(r[21], keys[SUBKEY_SCHEDULE[round][32]]);
800 f3 = _mm512_xor_si512(r[22], keys[SUBKEY_SCHEDULE[round][33]]);
801 f4 = _mm512_xor_si512(r[23], keys[SUBKEY_SCHEDULE[round][34]]);
802 f5 = _mm512_xor_si512(r[24], keys[SUBKEY_SCHEDULE[round][35]]);
803
804 g0 = _mm512_xor_si512(r[23], keys[SUBKEY_SCHEDULE[round][36]]);
806 g1 = _mm512_xor_si512(r[24], keys[SUBKEY_SCHEDULE[round][37]]);
807 g2 = _mm512_xor_si512(r[25], keys[SUBKEY_SCHEDULE[round][38]]);
808 g3 = _mm512_xor_si512(r[26], keys[SUBKEY_SCHEDULE[round][39]]);
809 g4 = _mm512_xor_si512(r[27], keys[SUBKEY_SCHEDULE[round][40]]);
810 g5 = _mm512_xor_si512(r[28], keys[SUBKEY_SCHEDULE[round][41]]);
811
812 h0 = _mm512_xor_si512(r[27], keys[SUBKEY_SCHEDULE[round][42]]);
814 h1 = _mm512_xor_si512(r[28], keys[SUBKEY_SCHEDULE[round][43]]);
815 h2 = _mm512_xor_si512(r[29], keys[SUBKEY_SCHEDULE[round][44]]);
816 h3 = _mm512_xor_si512(r[30], keys[SUBKEY_SCHEDULE[round][45]]);
817 h4 = _mm512_xor_si512(r[31], keys[SUBKEY_SCHEDULE[round][46]]);
818 h5 = _mm512_xor_si512(r[0], keys[SUBKEY_SCHEDULE[round][47]]);
819
820 {
822 let (o0, o1, o2, o3) = s5_avx_512(e0, e1, e2, e3, e4, e5);
823 l[7] = _mm512_xor_si512(l[7], o0);
824 l[13] = _mm512_xor_si512(l[13], o1);
825 l[24] = _mm512_xor_si512(l[24], o2);
826 l[2] = _mm512_xor_si512(l[2], o3);
827 }
828
829 {
831 let (o0, o1, o2, o3) = s6_avx_512(f0, f1, f2, f3, f4, f5);
832 l[3] = _mm512_xor_si512(l[3], o0);
833 l[28] = _mm512_xor_si512(l[28], o1);
834 l[10] = _mm512_xor_si512(l[10], o2);
835 l[18] = _mm512_xor_si512(l[18], o3);
836 }
837
838 {
840 let (o0, o1, o2, o3) = s7_avx_512(g0, g1, g2, g3, g4, g5);
841 l[31] = _mm512_xor_si512(l[31], o0);
842 l[11] = _mm512_xor_si512(l[11], o1);
843 l[21] = _mm512_xor_si512(l[21], o2);
844 l[6] = _mm512_xor_si512(l[6], o3);
845 }
846
847 {
849 let (o0, o1, o2, o3) = s8_avx_512(h0, h1, h2, h3, h4, h5);
850 l[4] = _mm512_xor_si512(l[4], o0);
851 l[26] = _mm512_xor_si512(l[26], o1);
852 l[14] = _mm512_xor_si512(l[14], o2);
853 l[20] = _mm512_xor_si512(l[20], o3);
854 }
855 }
856}
857
858const ALL_ONES_AVX_2: __m256i = unsafe { transmute([!0u64; 4]) };
860const ZERO_AVX_2: __m256i = unsafe { transmute([0u64; 4]) };
861
862#[inline(always)]
863pub fn encrypt_avx_2(keys: &mut [__m256i; 64]) {
864 let mut l: [__m256i; 32] = [
867 ZERO_AVX_2,
868 ALL_ONES_AVX_2,
869 ALL_ONES_AVX_2,
870 ALL_ONES_AVX_2,
871 ALL_ONES_AVX_2,
872 ZERO_AVX_2,
873 ZERO_AVX_2,
874 ZERO_AVX_2,
875 ZERO_AVX_2,
876 ALL_ONES_AVX_2,
877 ZERO_AVX_2,
878 ALL_ONES_AVX_2,
879 ZERO_AVX_2,
880 ALL_ONES_AVX_2,
881 ZERO_AVX_2,
882 ALL_ONES_AVX_2,
883 ZERO_AVX_2,
884 ALL_ONES_AVX_2,
885 ALL_ONES_AVX_2,
886 ALL_ONES_AVX_2,
887 ALL_ONES_AVX_2,
888 ZERO_AVX_2,
889 ZERO_AVX_2,
890 ZERO_AVX_2,
891 ZERO_AVX_2,
892 ALL_ONES_AVX_2,
893 ZERO_AVX_2,
894 ALL_ONES_AVX_2,
895 ZERO_AVX_2,
896 ALL_ONES_AVX_2,
897 ZERO_AVX_2,
898 ALL_ONES_AVX_2,
899 ];
900 let mut r: [__m256i; 32] = [
901 ALL_ONES_AVX_2,
902 ZERO_AVX_2,
903 ZERO_AVX_2,
904 ZERO_AVX_2,
905 ZERO_AVX_2,
906 ZERO_AVX_2,
907 ZERO_AVX_2,
908 ZERO_AVX_2,
909 ZERO_AVX_2,
910 ALL_ONES_AVX_2,
911 ALL_ONES_AVX_2,
912 ZERO_AVX_2,
913 ZERO_AVX_2,
914 ALL_ONES_AVX_2,
915 ALL_ONES_AVX_2,
916 ZERO_AVX_2,
917 ALL_ONES_AVX_2,
918 ZERO_AVX_2,
919 ZERO_AVX_2,
920 ZERO_AVX_2,
921 ZERO_AVX_2,
922 ZERO_AVX_2,
923 ZERO_AVX_2,
924 ZERO_AVX_2,
925 ZERO_AVX_2,
926 ALL_ONES_AVX_2,
927 ALL_ONES_AVX_2,
928 ZERO_AVX_2,
929 ZERO_AVX_2,
930 ALL_ONES_AVX_2,
931 ALL_ONES_AVX_2,
932 ZERO_AVX_2,
933 ];
934 unsafe {
936 feistel_avx_2(&mut l, &mut r, keys, 0);
937 }
938 unsafe {
940 feistel_avx_2(&mut r, &mut l, keys, 1);
941 }
942 unsafe {
944 feistel_avx_2(&mut l, &mut r, keys, 2);
945 }
946 unsafe {
948 feistel_avx_2(&mut r, &mut l, keys, 3);
949 }
950 unsafe {
952 feistel_avx_2(&mut l, &mut r, keys, 4);
953 }
954 unsafe {
956 feistel_avx_2(&mut r, &mut l, keys, 5);
957 }
958 unsafe {
960 feistel_avx_2(&mut l, &mut r, keys, 6);
961 }
962 unsafe {
964 feistel_avx_2(&mut r, &mut l, keys, 7);
965 }
966 unsafe {
968 feistel_avx_2(&mut l, &mut r, keys, 8);
969 }
970 unsafe {
972 feistel_avx_2(&mut r, &mut l, keys, 9);
973 }
974 unsafe {
976 feistel_avx_2(&mut l, &mut r, keys, 10);
977 }
978 unsafe {
980 feistel_avx_2(&mut r, &mut l, keys, 11);
981 }
982 unsafe {
984 feistel_avx_2(&mut l, &mut r, keys, 12);
985 }
986 unsafe {
988 feistel_avx_2(&mut r, &mut l, keys, 13);
989 }
990 unsafe {
992 feistel_avx_2(&mut l, &mut r, keys, 14);
993 }
994 unsafe {
996 feistel_avx_2(&mut r, &mut l, keys, 15);
997 }
998
999 unsafe {
1001 let out = keys.as_mut_ptr();
1002
1003 *out.add(0) = l[7];
1004 *out.add(1) = r[7];
1005 *out.add(2) = l[15];
1006 *out.add(3) = r[15];
1007 *out.add(4) = l[23];
1008 *out.add(5) = r[23];
1009 *out.add(6) = l[31];
1010 *out.add(7) = r[31];
1011
1012 *out.add(8) = l[6];
1013 *out.add(9) = r[6];
1014 *out.add(10) = l[14];
1015 *out.add(11) = r[14];
1016 *out.add(12) = l[22];
1017 *out.add(13) = r[22];
1018 *out.add(14) = l[30];
1019 *out.add(15) = r[30];
1020
1021 *out.add(16) = l[5];
1022 *out.add(17) = r[5];
1023 *out.add(18) = l[13];
1024 *out.add(19) = r[13];
1025 *out.add(20) = l[21];
1026 *out.add(21) = r[21];
1027 *out.add(22) = l[29];
1028 *out.add(23) = r[29];
1029
1030 *out.add(24) = l[4];
1031 *out.add(25) = r[4];
1032 *out.add(26) = l[12];
1033 *out.add(27) = r[12];
1034 *out.add(28) = l[20];
1035 *out.add(29) = r[20];
1036 *out.add(30) = l[28];
1037 *out.add(31) = r[28];
1038
1039 *out.add(32) = l[3];
1040 *out.add(33) = r[3];
1041 *out.add(34) = l[11];
1042 *out.add(35) = r[11];
1043 *out.add(36) = l[19];
1044 *out.add(37) = r[19];
1045 *out.add(38) = l[27];
1046 *out.add(39) = r[27];
1047
1048 *out.add(40) = l[2];
1049 *out.add(41) = r[2];
1050 *out.add(42) = l[10];
1051 *out.add(43) = r[10];
1052 *out.add(44) = l[18];
1053 *out.add(45) = r[18];
1054 *out.add(46) = l[26];
1055 *out.add(47) = r[26];
1056
1057 *out.add(48) = l[1];
1058 *out.add(49) = r[1];
1059 *out.add(50) = l[9];
1060 *out.add(51) = r[9];
1061 *out.add(52) = l[17];
1062 *out.add(53) = r[17];
1063 *out.add(54) = l[25];
1064 *out.add(55) = r[25];
1065
1066 *out.add(56) = l[0];
1067 *out.add(57) = r[0];
1068 *out.add(58) = l[8];
1069 *out.add(59) = r[8];
1070 *out.add(60) = l[16];
1071 *out.add(61) = r[16];
1072 *out.add(62) = l[24];
1073 *out.add(63) = r[24];
1074 }
1075}
1076
1077#[inline(always)]
1078pub unsafe fn feistel_avx_2(
1079 l: &mut [__m256i; 32],
1080 r: &mut [__m256i; 32],
1081 keys: &[__m256i; 64],
1082 round: usize,
1083) {
1084 unsafe {
1085 let mut e0 = _mm256_xor_si256(r[31], keys[SUBKEY_SCHEDULE[round][0]]);
1087 let mut e1 = _mm256_xor_si256(r[0], keys[SUBKEY_SCHEDULE[round][1]]);
1088 let mut e2 = _mm256_xor_si256(r[1], keys[SUBKEY_SCHEDULE[round][2]]);
1089 let mut e3 = _mm256_xor_si256(r[2], keys[SUBKEY_SCHEDULE[round][3]]);
1090 let mut e4 = _mm256_xor_si256(r[3], keys[SUBKEY_SCHEDULE[round][4]]);
1091 let mut e5 = _mm256_xor_si256(r[4], keys[SUBKEY_SCHEDULE[round][5]]);
1092
1093 let mut f0 = _mm256_xor_si256(r[3], keys[SUBKEY_SCHEDULE[round][6]]);
1095 let mut f1 = _mm256_xor_si256(r[4], keys[SUBKEY_SCHEDULE[round][7]]);
1096 let mut f2 = _mm256_xor_si256(r[5], keys[SUBKEY_SCHEDULE[round][8]]);
1097 let mut f3 = _mm256_xor_si256(r[6], keys[SUBKEY_SCHEDULE[round][9]]);
1098 let mut f4 = _mm256_xor_si256(r[7], keys[SUBKEY_SCHEDULE[round][10]]);
1099 let mut f5 = _mm256_xor_si256(r[8], keys[SUBKEY_SCHEDULE[round][11]]);
1100
1101 let mut g0 = _mm256_xor_si256(r[7], keys[SUBKEY_SCHEDULE[round][12]]);
1103 let mut g1 = _mm256_xor_si256(r[8], keys[SUBKEY_SCHEDULE[round][13]]);
1104 let mut g2 = _mm256_xor_si256(r[9], keys[SUBKEY_SCHEDULE[round][14]]);
1105 let mut g3 = _mm256_xor_si256(r[10], keys[SUBKEY_SCHEDULE[round][15]]);
1106 let mut g4 = _mm256_xor_si256(r[11], keys[SUBKEY_SCHEDULE[round][16]]);
1107 let mut g5 = _mm256_xor_si256(r[12], keys[SUBKEY_SCHEDULE[round][17]]);
1108
1109 let mut h0 = _mm256_xor_si256(r[11], keys[SUBKEY_SCHEDULE[round][18]]);
1111 let mut h1 = _mm256_xor_si256(r[12], keys[SUBKEY_SCHEDULE[round][19]]);
1112 let mut h2 = _mm256_xor_si256(r[13], keys[SUBKEY_SCHEDULE[round][20]]);
1113 let mut h3 = _mm256_xor_si256(r[14], keys[SUBKEY_SCHEDULE[round][21]]);
1114 let mut h4 = _mm256_xor_si256(r[15], keys[SUBKEY_SCHEDULE[round][22]]);
1115 let mut h5 = _mm256_xor_si256(r[16], keys[SUBKEY_SCHEDULE[round][23]]);
1116
1117 {
1120 let (o0, o1, o2, o3) = s1_avx_2(e0, e1, e2, e3, e4, e5);
1121 l[8] = _mm256_xor_si256(l[8], o0);
1122 l[16] = _mm256_xor_si256(l[16], o1);
1123 l[22] = _mm256_xor_si256(l[22], o2);
1124 l[30] = _mm256_xor_si256(l[30], o3);
1125 }
1126
1127 {
1129 let (o0, o1, o2, o3) = s2_avx_2(f0, f1, f2, f3, f4, f5);
1130 l[12] = _mm256_xor_si256(l[12], o0);
1131 l[27] = _mm256_xor_si256(l[27], o1);
1132 l[1] = _mm256_xor_si256(l[1], o2);
1133 l[17] = _mm256_xor_si256(l[17], o3);
1134 }
1135
1136 {
1138 let (o0, o1, o2, o3) = s3_avx_2(g0, g1, g2, g3, g4, g5);
1139 l[23] = _mm256_xor_si256(l[23], o0);
1140 l[15] = _mm256_xor_si256(l[15], o1);
1141 l[29] = _mm256_xor_si256(l[29], o2);
1142 l[5] = _mm256_xor_si256(l[5], o3);
1143 }
1144
1145 {
1147 let (o0, o1, o2, o3) = s4_avx_2(h0, h1, h2, h3, h4, h5);
1148 l[25] = _mm256_xor_si256(l[25], o0);
1149 l[19] = _mm256_xor_si256(l[19], o1);
1150 l[9] = _mm256_xor_si256(l[9], o2);
1151 l[0] = _mm256_xor_si256(l[0], o3);
1152 }
1153
1154 e0 = _mm256_xor_si256(r[15], keys[SUBKEY_SCHEDULE[round][24]]);
1156 e1 = _mm256_xor_si256(r[16], keys[SUBKEY_SCHEDULE[round][25]]);
1157 e2 = _mm256_xor_si256(r[17], keys[SUBKEY_SCHEDULE[round][26]]);
1158 e3 = _mm256_xor_si256(r[18], keys[SUBKEY_SCHEDULE[round][27]]);
1159 e4 = _mm256_xor_si256(r[19], keys[SUBKEY_SCHEDULE[round][28]]);
1160 e5 = _mm256_xor_si256(r[20], keys[SUBKEY_SCHEDULE[round][29]]);
1161
1162 f0 = _mm256_xor_si256(r[19], keys[SUBKEY_SCHEDULE[round][30]]);
1164 f1 = _mm256_xor_si256(r[20], keys[SUBKEY_SCHEDULE[round][31]]);
1165 f2 = _mm256_xor_si256(r[21], keys[SUBKEY_SCHEDULE[round][32]]);
1166 f3 = _mm256_xor_si256(r[22], keys[SUBKEY_SCHEDULE[round][33]]);
1167 f4 = _mm256_xor_si256(r[23], keys[SUBKEY_SCHEDULE[round][34]]);
1168 f5 = _mm256_xor_si256(r[24], keys[SUBKEY_SCHEDULE[round][35]]);
1169
1170 g0 = _mm256_xor_si256(r[23], keys[SUBKEY_SCHEDULE[round][36]]);
1172 g1 = _mm256_xor_si256(r[24], keys[SUBKEY_SCHEDULE[round][37]]);
1173 g2 = _mm256_xor_si256(r[25], keys[SUBKEY_SCHEDULE[round][38]]);
1174 g3 = _mm256_xor_si256(r[26], keys[SUBKEY_SCHEDULE[round][39]]);
1175 g4 = _mm256_xor_si256(r[27], keys[SUBKEY_SCHEDULE[round][40]]);
1176 g5 = _mm256_xor_si256(r[28], keys[SUBKEY_SCHEDULE[round][41]]);
1177
1178 h0 = _mm256_xor_si256(r[27], keys[SUBKEY_SCHEDULE[round][42]]);
1180 h1 = _mm256_xor_si256(r[28], keys[SUBKEY_SCHEDULE[round][43]]);
1181 h2 = _mm256_xor_si256(r[29], keys[SUBKEY_SCHEDULE[round][44]]);
1182 h3 = _mm256_xor_si256(r[30], keys[SUBKEY_SCHEDULE[round][45]]);
1183 h4 = _mm256_xor_si256(r[31], keys[SUBKEY_SCHEDULE[round][46]]);
1184 h5 = _mm256_xor_si256(r[0], keys[SUBKEY_SCHEDULE[round][47]]);
1185
1186 {
1188 let (o0, o1, o2, o3) = s5_avx_2(e0, e1, e2, e3, e4, e5);
1189 l[7] = _mm256_xor_si256(l[7], o0);
1190 l[13] = _mm256_xor_si256(l[13], o1);
1191 l[24] = _mm256_xor_si256(l[24], o2);
1192 l[2] = _mm256_xor_si256(l[2], o3);
1193 }
1194
1195 {
1197 let (o0, o1, o2, o3) = s6_avx_2(f0, f1, f2, f3, f4, f5);
1198 l[3] = _mm256_xor_si256(l[3], o0);
1199 l[28] = _mm256_xor_si256(l[28], o1);
1200 l[10] = _mm256_xor_si256(l[10], o2);
1201 l[18] = _mm256_xor_si256(l[18], o3);
1202 }
1203
1204 {
1206 let (o0, o1, o2, o3) = s7_avx_2(g0, g1, g2, g3, g4, g5);
1207 l[31] = _mm256_xor_si256(l[31], o0);
1208 l[11] = _mm256_xor_si256(l[11], o1);
1209 l[21] = _mm256_xor_si256(l[21], o2);
1210 l[6] = _mm256_xor_si256(l[6], o3);
1211 }
1212
1213 {
1215 let (o0, o1, o2, o3) = s8_avx_2(h0, h1, h2, h3, h4, h5);
1216 l[4] = _mm256_xor_si256(l[4], o0);
1217 l[26] = _mm256_xor_si256(l[26], o1);
1218 l[14] = _mm256_xor_si256(l[14], o2);
1219 l[20] = _mm256_xor_si256(l[20], o3);
1220 }
1221 }
1222}
1223
1224fn permute_bits_pc(p_box: &[u64], input: u64, input_length: usize) -> u64 {
1225 let p_box_length = p_box.len();
1226 let mut output: u64 = 0;
1227 for i in 0..p_box_length {
1228 output |= permute_bits::<u64>(input, input_length, p_box[i] as usize, p_box_length, i + 1);
1229 }
1230 output
1231}
1232
1233fn permute_bits<T>(
1234 input: T,
1235 input_length: usize,
1236 input_index: usize,
1237 output_length: usize,
1238 output_index: usize,
1239) -> T
1240where
1241 T: Copy
1242 + Shl<usize, Output = T>
1243 + Shr<usize, Output = T>
1244 + BitAnd<Output = T>
1245 + BitOr<Output = T>
1246 + From<u64>,
1247{
1248 ((input >> (input_length - input_index)) & T::from(1)) << (output_length - output_index)
1249}