1use std::{
2 arch::x86_64::{__m512i, _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 sbox_optimized::{s1, s2, s3, s4, s5, s6, s7, s8},
11 sbox_simd::{s1_avx, s2_avx, s3_avx, s4_avx, s5_avx, s6_avx, s7_avx, s8_avx},
12};
13use bitsliced_op::transpose_64x64;
14use wide::u64x8;
15
16pub fn compute_pc1_optimized(k_slices: &[u64x8; 64]) -> ([u64x8; 28], [u64x8; 28]) {
19 let mut c0 = [ZERO; 28];
20 let mut d0 = [ZERO; 28];
21
22 for (i, &src) in PC_1O.iter().enumerate() {
23 if i < 28 {
24 c0[i] = k_slices[src as usize];
25 } else {
26 d0[i - 28] = k_slices[src as usize];
27 }
28 }
29
30 (c0, d0)
31}
32
33const SHIFTS: [u32; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
34
35pub fn create_subkeys_optimized(c0: &mut [u64x8; 28], d0: &mut [u64x8; 28]) -> [[u64x8; 48]; 16] {
36 let mut subkeys = [[ZERO; 48]; 16];
37
38 for (index, s) in SHIFTS.iter().enumerate() {
39 c0.rotate_left(*s as usize);
40 d0.rotate_left(*s as usize);
41 for (i, &src) in PC_2O.iter().enumerate() {
42 if src < 28 {
43 subkeys[index][i] = c0[src as usize]
44 } else {
45 subkeys[index][i] = d0[(src - 28) as usize];
46 }
47 }
48 }
49
50 subkeys
51}
52
53pub fn encrypt_optimized(plaintext: u64, subkeys: [[u64x8; 48]; 16], output: &mut [u64x8; 64]) {
55 let ip = permute_bits_pc(&IP, plaintext, 64);
56 let ip_bitsliced = transpose_64x64(&[ip; 64]);
58 let mut l: [u64x8; 32] = std::array::from_fn(|i| u64x8::splat(ip_bitsliced[i]));
59 let mut r: [u64x8; 32] = std::array::from_fn(|i| u64x8::splat(ip_bitsliced[i + 32]));
60
61 for i in 0..16 {
62 let (new_l, new_r) = feistel_function_optimized(l, r, subkeys[i]);
63 l = new_l;
64 r = new_r;
65 }
66 let mut r_l = [ZERO; 64];
67 r_l[..32].copy_from_slice(&r);
68 r_l[32..].copy_from_slice(&l);
69 for (i, &src) in IP_INVO.iter().enumerate() {
70 output[i] = r_l[src as usize];
71 }
72}
73
74#[inline(always)]
75fn feistel_function_optimized(
76 l: [u64x8; 32],
77 r: [u64x8; 32],
78 subkey: [u64x8; 48],
79) -> ([u64x8; 32], [u64x8; 32]) {
80 let new_l = r;
81 let mut e = [ZERO; 48];
82 for (i, &src) in EO.iter().enumerate() {
83 e[i] = r[src as usize];
84 }
85 for i in 0..48 {
86 e[i] ^= subkey[i];
87 }
88 let mut output: [u64x8; 32] = [ZERO; 32];
89
90 let s1_output = s1(e[0], e[1], e[2], e[3], e[4], e[5]);
91 let s2_output = s2(e[6], e[7], e[8], e[9], e[10], e[11]);
92 let s3_output = s3(e[12], e[13], e[14], e[15], e[16], e[17]);
93 let s4_output = s4(e[18], e[19], e[20], e[21], e[22], e[23]);
94 let s5_output = s5(e[24], e[25], e[26], e[27], e[28], e[29]);
95 let s6_output = s6(e[30], e[31], e[32], e[33], e[34], e[35]);
96 let s7_output = s7(e[36], e[37], e[38], e[39], e[40], e[41]);
97 let s8_output = s8(e[42], e[43], e[44], e[45], e[46], e[47]);
98 output[0] = s1_output.0;
100 output[1] = s1_output.1;
101 output[2] = s1_output.2;
102 output[3] = s1_output.3;
103
104 output[4] = s2_output.0;
106 output[5] = s2_output.1;
107 output[6] = s2_output.2;
108 output[7] = s2_output.3;
109
110 output[8] = s3_output.0;
112 output[9] = s3_output.1;
113 output[10] = s3_output.2;
114 output[11] = s3_output.3;
115
116 output[12] = s4_output.0;
118 output[13] = s4_output.1;
119 output[14] = s4_output.2;
120 output[15] = s4_output.3;
121
122 output[16] = s5_output.0;
124 output[17] = s5_output.1;
125 output[18] = s5_output.2;
126 output[19] = s5_output.3;
127
128 output[20] = s6_output.0;
130 output[21] = s6_output.1;
131 output[22] = s6_output.2;
132 output[23] = s6_output.3;
133
134 output[24] = s7_output.0;
136 output[25] = s7_output.1;
137 output[26] = s7_output.2;
138 output[27] = s7_output.3;
139
140 output[28] = s8_output.0;
142 output[29] = s8_output.1;
143 output[30] = s8_output.2;
144 output[31] = s8_output.3;
145 let mut new_r = [ZERO; 32];
146 for (i, &src) in PO.iter().enumerate() {
147 new_r[i] = output[src as usize];
148 }
149 for i in 0..32 {
151 new_r[i] = l[i] ^ new_r[i];
152 }
153 (new_l, new_r)
154}
155
156const SUBKEY_SCHEDULE: [[usize; 48]; 16] = [
157 [
159 9, 50, 33, 59, 48, 16, 32, 56, 1, 8, 18, 41, 2, 34, 25, 24, 43, 57, 58, 0, 35, 26, 17, 40,
160 21, 27, 38, 53, 36, 3, 46, 29, 4, 52, 22, 28, 60, 20, 37, 62, 14, 19, 44, 13, 12, 61, 54,
161 30,
162 ],
163 [
165 1, 42, 25, 51, 40, 8, 24, 48, 58, 0, 10, 33, 59, 26, 17, 16, 35, 49, 50, 57, 56, 18, 9, 32,
166 13, 19, 30, 45, 28, 62, 38, 21, 27, 44, 14, 20, 52, 12, 29, 54, 6, 11, 36, 5, 4, 53, 46,
167 22,
168 ],
169 [
171 50, 26, 9, 35, 24, 57, 8, 32, 42, 49, 59, 17, 43, 10, 1, 0, 48, 33, 34, 41, 40, 2, 58, 16,
172 60, 3, 14, 29, 12, 46, 22, 5, 11, 28, 61, 4, 36, 27, 13, 38, 53, 62, 20, 52, 19, 37, 30, 6,
173 ],
174 [
176 34, 10, 58, 48, 8, 41, 57, 16, 26, 33, 43, 1, 56, 59, 50, 49, 32, 17, 18, 25, 24, 51, 42,
177 0, 44, 54, 61, 13, 27, 30, 6, 52, 62, 12, 45, 19, 20, 11, 60, 22, 37, 46, 4, 36, 3, 21, 14,
178 53,
179 ],
180 [
182 18, 59, 42, 32, 57, 25, 41, 0, 10, 17, 56, 50, 40, 43, 34, 33, 16, 1, 2, 9, 8, 35, 26, 49,
183 28, 38, 45, 60, 11, 14, 53, 36, 46, 27, 29, 3, 4, 62, 44, 6, 21, 30, 19, 20, 54, 5, 61, 37,
184 ],
185 [
187 2, 43, 26, 16, 41, 9, 25, 49, 59, 1, 40, 34, 24, 56, 18, 17, 0, 50, 51, 58, 57, 48, 10, 33,
188 12, 22, 29, 44, 62, 61, 37, 20, 30, 11, 13, 54, 19, 46, 28, 53, 5, 14, 3, 4, 38, 52, 45,
189 21,
190 ],
191 [
193 51, 56, 10, 0, 25, 58, 9, 33, 43, 50, 24, 18, 8, 40, 2, 1, 49, 34, 35, 42, 41, 32, 59, 17,
194 27, 6, 13, 28, 46, 45, 21, 4, 14, 62, 60, 38, 3, 30, 12, 37, 52, 61, 54, 19, 22, 36, 29, 5,
195 ],
196 [
198 35, 40, 59, 49, 9, 42, 58, 17, 56, 34, 8, 2, 57, 24, 51, 50, 33, 18, 48, 26, 25, 16, 43, 1,
199 11, 53, 60, 12, 30, 29, 5, 19, 61, 46, 44, 22, 54, 14, 27, 21, 36, 45, 38, 3, 6, 20, 13,
200 52,
201 ],
202 [
204 56, 32, 51, 41, 1, 34, 50, 9, 48, 26, 0, 59, 49, 16, 43, 42, 25, 10, 40, 18, 17, 8, 35, 58,
205 3, 45, 52, 4, 22, 21, 60, 11, 53, 38, 36, 14, 46, 6, 19, 13, 28, 37, 30, 62, 61, 12, 5, 44,
206 ],
207 [
209 40, 16, 35, 25, 50, 18, 34, 58, 32, 10, 49, 43, 33, 0, 56, 26, 9, 59, 24, 2, 1, 57, 48, 42,
210 54, 29, 36, 19, 6, 5, 44, 62, 37, 22, 20, 61, 30, 53, 3, 60, 12, 21, 14, 46, 45, 27, 52,
211 28,
212 ],
213 [
215 24, 0, 48, 9, 34, 2, 18, 42, 16, 59, 33, 56, 17, 49, 40, 10, 58, 43, 8, 51, 50, 41, 32, 26,
216 38, 13, 20, 3, 53, 52, 28, 46, 21, 6, 4, 45, 14, 37, 54, 44, 27, 5, 61, 30, 29, 11, 36, 12,
217 ],
218 [
220 8, 49, 32, 58, 18, 51, 2, 26, 0, 43, 17, 40, 1, 33, 24, 59, 42, 56, 57, 35, 34, 25, 16, 10,
221 22, 60, 4, 54, 37, 36, 12, 30, 5, 53, 19, 29, 61, 21, 38, 28, 11, 52, 45, 14, 13, 62, 20,
222 27,
223 ],
224 [
226 57, 33, 16, 42, 2, 35, 51, 10, 49, 56, 1, 24, 50, 17, 8, 43, 26, 40, 41, 48, 18, 9, 0, 59,
227 6, 44, 19, 38, 21, 20, 27, 14, 52, 37, 3, 13, 45, 5, 22, 12, 62, 36, 29, 61, 60, 46, 4, 11,
228 ],
229 [
231 41, 17, 0, 26, 51, 48, 35, 59, 33, 40, 50, 8, 34, 1, 57, 56, 10, 24, 25, 32, 2, 58, 49, 43,
232 53, 28, 3, 22, 5, 4, 11, 61, 36, 21, 54, 60, 29, 52, 6, 27, 46, 20, 13, 45, 44, 30, 19, 62,
233 ],
234 [
236 25, 1, 49, 10, 35, 32, 48, 43, 17, 24, 34, 57, 18, 50, 41, 40, 59, 8, 9, 16, 51, 42, 33,
237 56, 37, 12, 54, 6, 52, 19, 62, 45, 20, 5, 38, 44, 13, 36, 53, 11, 30, 4, 60, 29, 28, 14, 3,
238 46,
239 ],
240 [
242 17, 58, 41, 2, 56, 24, 40, 35, 9, 16, 26, 49, 10, 42, 33, 32, 51, 0, 1, 8, 43, 34, 25, 48,
243 29, 4, 46, 61, 44, 11, 54, 37, 12, 60, 30, 36, 5, 28, 45, 3, 22, 27, 52, 21, 20, 6, 62, 38,
244 ],
245];
246
247pub fn encrypt_simd(plaintext: u64, keys: &mut [u64x8; 64]) {
248 let ip = permute_bits_pc(&IP, plaintext, 64);
249 let mut l: [u64x8; 32] = [ZERO; 32];
250 let mut r: [u64x8; 32] = [ZERO; 32];
251 for i in 0..32 {
252 let bit_l = (ip >> (63 - i)) & 1;
253 let bit_r = (ip >> (31 - i)) & 1;
254
255 l[i] = u64x8::splat(0u64.wrapping_sub(bit_l));
256 r[i] = u64x8::splat(0u64.wrapping_sub(bit_r));
257 }
258
259 unsafe {
261 feistel_function_simd(&mut l, &mut r, keys, 0);
262 }
263 unsafe {
265 feistel_function_simd(&mut r, &mut l, keys, 1);
266 }
267 unsafe {
269 feistel_function_simd(&mut l, &mut r, keys, 2);
270 }
271 unsafe {
273 feistel_function_simd(&mut r, &mut l, keys, 3);
274 }
275 unsafe {
277 feistel_function_simd(&mut l, &mut r, keys, 4);
278 }
279 unsafe {
281 feistel_function_simd(&mut r, &mut l, keys, 5);
282 }
283 unsafe {
285 feistel_function_simd(&mut l, &mut r, keys, 6);
286 }
287 unsafe {
289 feistel_function_simd(&mut r, &mut l, keys, 7);
290 }
291 unsafe {
293 feistel_function_simd(&mut l, &mut r, keys, 8);
294 }
295 unsafe {
297 feistel_function_simd(&mut r, &mut l, keys, 9);
298 }
299 unsafe {
301 feistel_function_simd(&mut l, &mut r, keys, 10);
302 }
303 unsafe {
305 feistel_function_simd(&mut r, &mut l, keys, 11);
306 }
307 unsafe {
309 feistel_function_simd(&mut l, &mut r, keys, 12);
310 }
311 unsafe {
313 feistel_function_simd(&mut r, &mut l, keys, 13);
314 }
315 unsafe {
317 feistel_function_simd(&mut l, &mut r, keys, 14);
318 }
319 unsafe {
321 feistel_function_simd(&mut r, &mut l, keys, 15);
322 }
323
324 let keys_ptr = keys.as_mut_ptr();
326 for i in 0..64 {
327 unsafe {
328 std::ptr::write(
329 keys_ptr.add(i),
330 if IP_INVO[i] < 32 {
331 r[IP_INVO[i]]
332 } else {
333 l[IP_INVO[i] - 32]
334 },
335 );
336 }
337 }
338}
339
340#[inline(always)]
341pub unsafe fn feistel_function_simd(
342 l: &mut [u64x8; 32],
343 r: &mut [u64x8; 32],
344 keys: &[u64x8; 64],
345 round: usize,
346) {
347 let mut e0 = r[31] ^ keys[SUBKEY_SCHEDULE[round][0]];
349 let mut e1 = r[0] ^ keys[SUBKEY_SCHEDULE[round][1]];
350 let mut e2 = r[1] ^ keys[SUBKEY_SCHEDULE[round][2]];
351 let mut e3 = r[2] ^ keys[SUBKEY_SCHEDULE[round][3]];
352 let mut e4 = r[3] ^ keys[SUBKEY_SCHEDULE[round][4]];
353 let mut e5 = r[4] ^ keys[SUBKEY_SCHEDULE[round][5]];
354
355 let mut f0 = r[3] ^ keys[SUBKEY_SCHEDULE[round][6]];
357 let mut f1 = r[4] ^ keys[SUBKEY_SCHEDULE[round][7]];
358 let mut f2 = r[5] ^ keys[SUBKEY_SCHEDULE[round][8]];
359 let mut f3 = r[6] ^ keys[SUBKEY_SCHEDULE[round][9]];
360 let mut f4 = r[7] ^ keys[SUBKEY_SCHEDULE[round][10]];
361 let mut f5 = r[8] ^ keys[SUBKEY_SCHEDULE[round][11]];
362
363 let mut g0 = r[7] ^ keys[SUBKEY_SCHEDULE[round][12]];
365 let mut g1 = r[8] ^ keys[SUBKEY_SCHEDULE[round][13]];
366 let mut g2 = r[9] ^ keys[SUBKEY_SCHEDULE[round][14]];
367 let mut g3 = r[10] ^ keys[SUBKEY_SCHEDULE[round][15]];
368 let mut g4 = r[11] ^ keys[SUBKEY_SCHEDULE[round][16]];
369 let mut g5 = r[12] ^ keys[SUBKEY_SCHEDULE[round][17]];
370
371 let mut h0 = r[11] ^ keys[SUBKEY_SCHEDULE[round][18]];
373 let mut h1 = r[12] ^ keys[SUBKEY_SCHEDULE[round][19]];
374 let mut h2 = r[13] ^ keys[SUBKEY_SCHEDULE[round][20]];
375 let mut h3 = r[14] ^ keys[SUBKEY_SCHEDULE[round][21]];
376 let mut h4 = r[15] ^ keys[SUBKEY_SCHEDULE[round][22]];
377 let mut h5 = r[16] ^ keys[SUBKEY_SCHEDULE[round][23]];
378
379 {
382 let (o0, o1, o2, o3) = s1(e0, e1, e2, e3, e4, e5);
383 l[8] = l[8] ^ o0;
384 l[16] = l[16] ^ o1;
385 l[22] = l[22] ^ o2;
386 l[30] = l[30] ^ o3;
387 }
388
389 {
391 let (o0, o1, o2, o3) = s2(f0, f1, f2, f3, f4, f5);
392 l[12] = l[12] ^ o0;
393 l[27] = l[27] ^ o1;
394 l[1] = l[1] ^ o2;
395 l[17] = l[17] ^ o3;
396 }
397
398 {
400 let (o0, o1, o2, o3) = s3(g0, g1, g2, g3, g4, g5);
401 l[23] = l[23] ^ o0;
402 l[15] = l[15] ^ o1;
403 l[29] = l[29] ^ o2;
404 l[5] = l[5] ^ o3;
405 }
406
407 {
409 let (o0, o1, o2, o3) = s4(h0, h1, h2, h3, h4, h5);
410 l[25] = l[25] ^ o0;
411 l[19] = l[19] ^ o1;
412 l[9] = l[9] ^ o2;
413 l[0] = l[0] ^ o3;
414 }
415
416 e0 = r[15] ^ keys[SUBKEY_SCHEDULE[round][24]];
418 e1 = r[16] ^ keys[SUBKEY_SCHEDULE[round][25]];
419 e2 = r[17] ^ keys[SUBKEY_SCHEDULE[round][26]];
420 e3 = r[18] ^ keys[SUBKEY_SCHEDULE[round][27]];
421 e4 = r[19] ^ keys[SUBKEY_SCHEDULE[round][28]];
422 e5 = r[20] ^ keys[SUBKEY_SCHEDULE[round][29]];
423
424 f0 = r[19] ^ keys[SUBKEY_SCHEDULE[round][30]];
426 f1 = r[20] ^ keys[SUBKEY_SCHEDULE[round][31]];
427 f2 = r[21] ^ keys[SUBKEY_SCHEDULE[round][32]];
428 f3 = r[22] ^ keys[SUBKEY_SCHEDULE[round][33]];
429 f4 = r[23] ^ keys[SUBKEY_SCHEDULE[round][34]];
430 f5 = r[24] ^ keys[SUBKEY_SCHEDULE[round][35]];
431
432 g0 = r[23] ^ keys[SUBKEY_SCHEDULE[round][36]];
434 g1 = r[24] ^ keys[SUBKEY_SCHEDULE[round][37]];
435 g2 = r[25] ^ keys[SUBKEY_SCHEDULE[round][38]];
436 g3 = r[26] ^ keys[SUBKEY_SCHEDULE[round][39]];
437 g4 = r[27] ^ keys[SUBKEY_SCHEDULE[round][40]];
438 g5 = r[28] ^ keys[SUBKEY_SCHEDULE[round][41]];
439
440 h0 = r[27] ^ keys[SUBKEY_SCHEDULE[round][42]];
442 h1 = r[28] ^ keys[SUBKEY_SCHEDULE[round][43]];
443 h2 = r[29] ^ keys[SUBKEY_SCHEDULE[round][44]];
444 h3 = r[30] ^ keys[SUBKEY_SCHEDULE[round][45]];
445 h4 = r[31] ^ keys[SUBKEY_SCHEDULE[round][46]];
446 h5 = r[0] ^ keys[SUBKEY_SCHEDULE[round][47]];
447
448 {
450 let (o0, o1, o2, o3) = s5(e0, e1, e2, e3, e4, e5);
451 l[7] = l[7] ^ o0;
452 l[13] = l[13] ^ o1;
453 l[24] = l[24] ^ o2;
454 l[2] = l[2] ^ o3;
455 }
456
457 {
459 let (o0, o1, o2, o3) = s6(f0, f1, f2, f3, f4, f5);
460 l[3] = l[3] ^ o0;
461 l[28] = l[28] ^ o1;
462 l[10] = l[10] ^ o2;
463 l[18] = l[18] ^ o3;
464 }
465
466 {
468 let (o0, o1, o2, o3) = s7(g0, g1, g2, g3, g4, g5);
469 l[31] = l[31] ^ o0;
470 l[11] = l[11] ^ o1;
471 l[21] = l[21] ^ o2;
472 l[6] = l[6] ^ o3;
473 }
474
475 {
477 let (o0, o1, o2, o3) = s8(h0, h1, h2, h3, h4, h5);
478 l[4] = l[4] ^ o0;
479 l[26] = l[26] ^ o1;
480 l[14] = l[14] ^ o2;
481 l[20] = l[20] ^ o3;
482 }
483}
484
485const ALL_ONES_AVX: __m512i = unsafe { transmute([!0u64; 8]) };
486const ZERO_AVX: __m512i = unsafe { transmute([0u64; 8]) };
487
488#[inline(always)]
489pub fn encrypt_simd_avx(keys: &mut [__m512i; 64]) {
490 let mut l: [__m512i; 32] = [
493 ZERO_AVX,
494 ALL_ONES_AVX,
495 ALL_ONES_AVX,
496 ALL_ONES_AVX,
497 ALL_ONES_AVX,
498 ZERO_AVX,
499 ZERO_AVX,
500 ZERO_AVX,
501 ZERO_AVX,
502 ALL_ONES_AVX,
503 ZERO_AVX,
504 ALL_ONES_AVX,
505 ZERO_AVX,
506 ALL_ONES_AVX,
507 ZERO_AVX,
508 ALL_ONES_AVX,
509 ZERO_AVX,
510 ALL_ONES_AVX,
511 ALL_ONES_AVX,
512 ALL_ONES_AVX,
513 ALL_ONES_AVX,
514 ZERO_AVX,
515 ZERO_AVX,
516 ZERO_AVX,
517 ZERO_AVX,
518 ALL_ONES_AVX,
519 ZERO_AVX,
520 ALL_ONES_AVX,
521 ZERO_AVX,
522 ALL_ONES_AVX,
523 ZERO_AVX,
524 ALL_ONES_AVX,
525 ];
526 let mut r: [__m512i; 32] = [
527 ALL_ONES_AVX,
528 ZERO_AVX,
529 ZERO_AVX,
530 ZERO_AVX,
531 ZERO_AVX,
532 ZERO_AVX,
533 ZERO_AVX,
534 ZERO_AVX,
535 ZERO_AVX,
536 ALL_ONES_AVX,
537 ALL_ONES_AVX,
538 ZERO_AVX,
539 ZERO_AVX,
540 ALL_ONES_AVX,
541 ALL_ONES_AVX,
542 ZERO_AVX,
543 ALL_ONES_AVX,
544 ZERO_AVX,
545 ZERO_AVX,
546 ZERO_AVX,
547 ZERO_AVX,
548 ZERO_AVX,
549 ZERO_AVX,
550 ZERO_AVX,
551 ZERO_AVX,
552 ALL_ONES_AVX,
553 ALL_ONES_AVX,
554 ZERO_AVX,
555 ZERO_AVX,
556 ALL_ONES_AVX,
557 ALL_ONES_AVX,
558 ZERO_AVX,
559 ];
560 unsafe {
562 feistel_function_avx(&mut l, &mut r, keys, 0);
563 }
564 unsafe {
566 feistel_function_avx(&mut r, &mut l, keys, 1);
567 }
568 unsafe {
570 feistel_function_avx(&mut l, &mut r, keys, 2);
571 }
572 unsafe {
574 feistel_function_avx(&mut r, &mut l, keys, 3);
575 }
576 unsafe {
578 feistel_function_avx(&mut l, &mut r, keys, 4);
579 }
580 unsafe {
582 feistel_function_avx(&mut r, &mut l, keys, 5);
583 }
584 unsafe {
586 feistel_function_avx(&mut l, &mut r, keys, 6);
587 }
588 unsafe {
590 feistel_function_avx(&mut r, &mut l, keys, 7);
591 }
592 unsafe {
594 feistel_function_avx(&mut l, &mut r, keys, 8);
595 }
596 unsafe {
598 feistel_function_avx(&mut r, &mut l, keys, 9);
599 }
600 unsafe {
602 feistel_function_avx(&mut l, &mut r, keys, 10);
603 }
604 unsafe {
606 feistel_function_avx(&mut r, &mut l, keys, 11);
607 }
608 unsafe {
610 feistel_function_avx(&mut l, &mut r, keys, 12);
611 }
612 unsafe {
614 feistel_function_avx(&mut r, &mut l, keys, 13);
615 }
616 unsafe {
618 feistel_function_avx(&mut l, &mut r, keys, 14);
619 }
620 unsafe {
622 feistel_function_avx(&mut r, &mut l, keys, 15);
623 }
624
625 let keys_ptr = keys.as_mut_ptr();
627 for i in 0..64 {
628 unsafe {
629 std::ptr::write(
630 keys_ptr.add(i),
631 if IP_INVO[i] < 32 {
632 r[IP_INVO[i]]
633 } else {
634 l[IP_INVO[i] - 32]
635 },
636 );
637 }
638 }
639}
640
641#[inline(always)]
642pub unsafe fn feistel_function_avx(
643 l: &mut [__m512i; 32],
644 r: &mut [__m512i; 32],
645 keys: &[__m512i; 64],
646 round: usize,
647) {
648 unsafe {
649 let mut e0 = _mm512_xor_si512(r[31], keys[SUBKEY_SCHEDULE[round][0]]);
651 let mut e1 = _mm512_xor_si512(r[0], keys[SUBKEY_SCHEDULE[round][1]]);
652 let mut e2 = _mm512_xor_si512(r[1], keys[SUBKEY_SCHEDULE[round][2]]);
653 let mut e3 = _mm512_xor_si512(r[2], keys[SUBKEY_SCHEDULE[round][3]]);
654 let mut e4 = _mm512_xor_si512(r[3], keys[SUBKEY_SCHEDULE[round][4]]);
655 let mut e5 = _mm512_xor_si512(r[4], keys[SUBKEY_SCHEDULE[round][5]]);
656
657 let mut f0 = _mm512_xor_si512(r[3], keys[SUBKEY_SCHEDULE[round][6]]);
659 let mut f1 = _mm512_xor_si512(r[4], keys[SUBKEY_SCHEDULE[round][7]]);
660 let mut f2 = _mm512_xor_si512(r[5], keys[SUBKEY_SCHEDULE[round][8]]);
661 let mut f3 = _mm512_xor_si512(r[6], keys[SUBKEY_SCHEDULE[round][9]]);
662 let mut f4 = _mm512_xor_si512(r[7], keys[SUBKEY_SCHEDULE[round][10]]);
663 let mut f5 = _mm512_xor_si512(r[8], keys[SUBKEY_SCHEDULE[round][11]]);
664
665 let mut g0 = _mm512_xor_si512(r[7], keys[SUBKEY_SCHEDULE[round][12]]);
667 let mut g1 = _mm512_xor_si512(r[8], keys[SUBKEY_SCHEDULE[round][13]]);
668 let mut g2 = _mm512_xor_si512(r[9], keys[SUBKEY_SCHEDULE[round][14]]);
669 let mut g3 = _mm512_xor_si512(r[10], keys[SUBKEY_SCHEDULE[round][15]]);
670 let mut g4 = _mm512_xor_si512(r[11], keys[SUBKEY_SCHEDULE[round][16]]);
671 let mut g5 = _mm512_xor_si512(r[12], keys[SUBKEY_SCHEDULE[round][17]]);
672
673 let mut h0 = _mm512_xor_si512(r[11], keys[SUBKEY_SCHEDULE[round][18]]);
675 let mut h1 = _mm512_xor_si512(r[12], keys[SUBKEY_SCHEDULE[round][19]]);
676 let mut h2 = _mm512_xor_si512(r[13], keys[SUBKEY_SCHEDULE[round][20]]);
677 let mut h3 = _mm512_xor_si512(r[14], keys[SUBKEY_SCHEDULE[round][21]]);
678 let mut h4 = _mm512_xor_si512(r[15], keys[SUBKEY_SCHEDULE[round][22]]);
679 let mut h5 = _mm512_xor_si512(r[16], keys[SUBKEY_SCHEDULE[round][23]]);
680
681 {
684 let (o0, o1, o2, o3) = s1_avx(e0, e1, e2, e3, e4, e5);
685 l[8] = _mm512_xor_si512(l[8], o0);
686 l[16] = _mm512_xor_si512(l[16], o1);
687 l[22] = _mm512_xor_si512(l[22], o2);
688 l[30] = _mm512_xor_si512(l[30], o3);
689 }
690
691 {
693 let (o0, o1, o2, o3) = s2_avx(f0, f1, f2, f3, f4, f5);
694 l[12] = _mm512_xor_si512(l[12], o0);
695 l[27] = _mm512_xor_si512(l[27], o1);
696 l[1] = _mm512_xor_si512(l[1], o2);
697 l[17] = _mm512_xor_si512(l[17], o3);
698 }
699
700 {
702 let (o0, o1, o2, o3) = s3_avx(g0, g1, g2, g3, g4, g5);
703 l[23] = _mm512_xor_si512(l[23], o0);
704 l[15] = _mm512_xor_si512(l[15], o1);
705 l[29] = _mm512_xor_si512(l[29], o2);
706 l[5] = _mm512_xor_si512(l[5], o3);
707 }
708
709 {
711 let (o0, o1, o2, o3) = s4_avx(h0, h1, h2, h3, h4, h5);
712 l[25] = _mm512_xor_si512(l[25], o0);
713 l[19] = _mm512_xor_si512(l[19], o1);
714 l[9] = _mm512_xor_si512(l[9], o2);
715 l[0] = _mm512_xor_si512(l[0], o3);
716 }
717
718 e0 = _mm512_xor_si512(r[15], keys[SUBKEY_SCHEDULE[round][24]]);
720 e1 = _mm512_xor_si512(r[16], keys[SUBKEY_SCHEDULE[round][25]]);
721 e2 = _mm512_xor_si512(r[17], keys[SUBKEY_SCHEDULE[round][26]]);
722 e3 = _mm512_xor_si512(r[18], keys[SUBKEY_SCHEDULE[round][27]]);
723 e4 = _mm512_xor_si512(r[19], keys[SUBKEY_SCHEDULE[round][28]]);
724 e5 = _mm512_xor_si512(r[20], keys[SUBKEY_SCHEDULE[round][29]]);
725
726 f0 = _mm512_xor_si512(r[19], keys[SUBKEY_SCHEDULE[round][30]]);
728 f1 = _mm512_xor_si512(r[20], keys[SUBKEY_SCHEDULE[round][31]]);
729 f2 = _mm512_xor_si512(r[21], keys[SUBKEY_SCHEDULE[round][32]]);
730 f3 = _mm512_xor_si512(r[22], keys[SUBKEY_SCHEDULE[round][33]]);
731 f4 = _mm512_xor_si512(r[23], keys[SUBKEY_SCHEDULE[round][34]]);
732 f5 = _mm512_xor_si512(r[24], keys[SUBKEY_SCHEDULE[round][35]]);
733
734 g0 = _mm512_xor_si512(r[23], keys[SUBKEY_SCHEDULE[round][36]]);
736 g1 = _mm512_xor_si512(r[24], keys[SUBKEY_SCHEDULE[round][37]]);
737 g2 = _mm512_xor_si512(r[25], keys[SUBKEY_SCHEDULE[round][38]]);
738 g3 = _mm512_xor_si512(r[26], keys[SUBKEY_SCHEDULE[round][39]]);
739 g4 = _mm512_xor_si512(r[27], keys[SUBKEY_SCHEDULE[round][40]]);
740 g5 = _mm512_xor_si512(r[28], keys[SUBKEY_SCHEDULE[round][41]]);
741
742 h0 = _mm512_xor_si512(r[27], keys[SUBKEY_SCHEDULE[round][42]]);
744 h1 = _mm512_xor_si512(r[28], keys[SUBKEY_SCHEDULE[round][43]]);
745 h2 = _mm512_xor_si512(r[29], keys[SUBKEY_SCHEDULE[round][44]]);
746 h3 = _mm512_xor_si512(r[30], keys[SUBKEY_SCHEDULE[round][45]]);
747 h4 = _mm512_xor_si512(r[31], keys[SUBKEY_SCHEDULE[round][46]]);
748 h5 = _mm512_xor_si512(r[0], keys[SUBKEY_SCHEDULE[round][47]]);
749
750 {
752 let (o0, o1, o2, o3) = s5_avx(e0, e1, e2, e3, e4, e5);
753 l[7] = _mm512_xor_si512(l[7], o0);
754 l[13] = _mm512_xor_si512(l[13], o1);
755 l[24] = _mm512_xor_si512(l[24], o2);
756 l[2] = _mm512_xor_si512(l[2], o3);
757 }
758
759 {
761 let (o0, o1, o2, o3) = s6_avx(f0, f1, f2, f3, f4, f5);
762 l[3] = _mm512_xor_si512(l[3], o0);
763 l[28] = _mm512_xor_si512(l[28], o1);
764 l[10] = _mm512_xor_si512(l[10], o2);
765 l[18] = _mm512_xor_si512(l[18], o3);
766 }
767
768 {
770 let (o0, o1, o2, o3) = s7_avx(g0, g1, g2, g3, g4, g5);
771 l[31] = _mm512_xor_si512(l[31], o0);
772 l[11] = _mm512_xor_si512(l[11], o1);
773 l[21] = _mm512_xor_si512(l[21], o2);
774 l[6] = _mm512_xor_si512(l[6], o3);
775 }
776
777 {
779 let (o0, o1, o2, o3) = s8_avx(h0, h1, h2, h3, h4, h5);
780 l[4] = _mm512_xor_si512(l[4], o0);
781 l[26] = _mm512_xor_si512(l[26], o1);
782 l[14] = _mm512_xor_si512(l[14], o2);
783 l[20] = _mm512_xor_si512(l[20], o3);
784 }
785 }
786}
787
788#[inline(always)]
789pub unsafe fn feistel_function_avx_(
790 l: &mut [__m512i; 32],
791 r: &mut [__m512i; 32],
792 keys: &[__m512i; 64],
793) {
794 unsafe {
795 let mut e0 = _mm512_xor_si512(r[31], keys[13]);
797 let mut e1 = _mm512_xor_si512(r[0], keys[16]);
798 let mut e2 = _mm512_xor_si512(r[1], keys[10]);
799 let mut e3 = _mm512_xor_si512(r[2], keys[23]);
800 let mut e4 = _mm512_xor_si512(r[3], keys[0]);
801 let mut e5 = _mm512_xor_si512(r[4], keys[4]);
802
803 let mut f0 = _mm512_xor_si512(r[3], keys[2]);
804 let mut f1 = _mm512_xor_si512(r[4], keys[27]);
805 let mut f2 = _mm512_xor_si512(r[5], keys[14]);
806 let mut f3 = _mm512_xor_si512(r[6], keys[5]);
807 let mut f4 = _mm512_xor_si512(r[7], keys[20]);
808 let mut f5 = _mm512_xor_si512(r[8], keys[9]);
809
810 {
811 let (o0, o1, o2, o3) = s1_avx(e0, e1, e2, e3, e4, e5);
812 let (p0, p1, p2, p3) = s2_avx(f0, f1, f2, f3, f4, f5);
813
814 l[8] = _mm512_xor_si512(l[8], o0);
815 l[16] = _mm512_xor_si512(l[16], o1);
816 l[22] = _mm512_xor_si512(l[22], o2);
817 l[30] = _mm512_xor_si512(l[30], o3);
818
819 l[12] = _mm512_xor_si512(l[12], p0);
820 l[27] = _mm512_xor_si512(l[27], p1);
821 l[1] = _mm512_xor_si512(l[1], p2);
822 l[17] = _mm512_xor_si512(l[17], p3);
823 }
824
825 e0 = _mm512_xor_si512(r[7], keys[22]);
827 e1 = _mm512_xor_si512(r[8], keys[18]);
828 e2 = _mm512_xor_si512(r[9], keys[11]);
829 e3 = _mm512_xor_si512(r[10], keys[3]);
830 e4 = _mm512_xor_si512(r[11], keys[25]);
831 e5 = _mm512_xor_si512(r[12], keys[7]);
832
833 f0 = _mm512_xor_si512(r[11], keys[15]);
834 f1 = _mm512_xor_si512(r[12], keys[6]);
835 f2 = _mm512_xor_si512(r[13], keys[26]);
836 f3 = _mm512_xor_si512(r[14], keys[19]);
837 f4 = _mm512_xor_si512(r[15], keys[12]);
838 f5 = _mm512_xor_si512(r[16], keys[1]);
839
840 {
841 let (o0, o1, o2, o3) = s3_avx(e0, e1, e2, e3, e4, e5);
842 let (p0, p1, p2, p3) = s4_avx(f0, f1, f2, f3, f4, f5);
843
844 l[23] = _mm512_xor_si512(l[23], o0);
845 l[15] = _mm512_xor_si512(l[15], o1);
846 l[29] = _mm512_xor_si512(l[29], o2);
847 l[5] = _mm512_xor_si512(l[5], o3);
848
849 l[25] = _mm512_xor_si512(l[25], p0);
850 l[19] = _mm512_xor_si512(l[19], p1);
851 l[9] = _mm512_xor_si512(l[9], p2);
852 l[0] = _mm512_xor_si512(l[0], p3);
853 }
854
855 e0 = _mm512_xor_si512(r[15], keys[7]);
857 e1 = _mm512_xor_si512(r[16], keys[31]);
858 e2 = _mm512_xor_si512(r[17], keys[21]);
859 e3 = _mm512_xor_si512(r[18], keys[13]);
860 e4 = _mm512_xor_si512(r[19], keys[24]);
861 e5 = _mm512_xor_si512(r[20], keys[2]);
862
863 f0 = _mm512_xor_si512(r[19], keys[3]);
864 f1 = _mm512_xor_si512(r[20], keys[28]);
865 f2 = _mm512_xor_si512(r[21], keys[10]);
866 f3 = _mm512_xor_si512(r[22], keys[18]);
867 f4 = _mm512_xor_si512(r[23], keys[5]);
868 f5 = _mm512_xor_si512(r[24], keys[26]);
869
870 {
871 let (o0, o1, o2, o3) = s5_avx(e0, e1, e2, e3, e4, e5);
872 let (p0, p1, p2, p3) = s6_avx(f0, f1, f2, f3, f4, f5);
873
874 l[7] = _mm512_xor_si512(l[7], o0);
875 l[13] = _mm512_xor_si512(l[13], o1);
876 l[24] = _mm512_xor_si512(l[24], o2);
877 l[2] = _mm512_xor_si512(l[2], o3);
878
879 l[3] = _mm512_xor_si512(l[3], p0);
880 l[28] = _mm512_xor_si512(l[28], p1);
881 l[10] = _mm512_xor_si512(l[10], p2);
882 l[18] = _mm512_xor_si512(l[18], p3);
883 }
884
885 e0 = _mm512_xor_si512(r[23], keys[14]);
887 e1 = _mm512_xor_si512(r[24], keys[20]);
888 e2 = _mm512_xor_si512(r[25], keys[6]);
889 e3 = _mm512_xor_si512(r[26], keys[11]);
890 e4 = _mm512_xor_si512(r[27], keys[0]);
891 e5 = _mm512_xor_si512(r[28], keys[22]);
892
893 f0 = _mm512_xor_si512(r[27], keys[8]);
894 f1 = _mm512_xor_si512(r[28], keys[17]);
895 f2 = _mm512_xor_si512(r[29], keys[4]);
896 f3 = _mm512_xor_si512(r[30], keys[19]);
897 f4 = _mm512_xor_si512(r[31], keys[9]);
898 f5 = _mm512_xor_si512(r[0], keys[1]);
899
900 {
901 let (o0, o1, o2, o3) = s7_avx(e0, e1, e2, e3, e4, e5);
902 let (p0, p1, p2, p3) = s8_avx(f0, f1, f2, f3, f4, f5);
903
904 l[31] = _mm512_xor_si512(l[31], o0);
905 l[11] = _mm512_xor_si512(l[11], o1);
906 l[21] = _mm512_xor_si512(l[21], o2);
907 l[6] = _mm512_xor_si512(l[6], o3);
908
909 l[4] = _mm512_xor_si512(l[4], p0);
910 l[26] = _mm512_xor_si512(l[26], p1);
911 l[14] = _mm512_xor_si512(l[14], p2);
912 l[20] = _mm512_xor_si512(l[20], p3);
913 }
914 }
915}
916
917fn permute_bits_pc(p_box: &[u64], input: u64, input_length: usize) -> u64 {
918 let p_box_length = p_box.len();
919 let mut output: u64 = 0;
920 for i in 0..p_box_length {
921 output |= permute_bits::<u64>(input, input_length, p_box[i] as usize, p_box_length, i + 1);
922 }
923 output
924}
925
926fn permute_bits<T>(
927 input: T,
928 input_length: usize,
929 input_index: usize,
930 output_length: usize,
931 output_index: usize,
932) -> T
933where
934 T: Copy
935 + Shl<usize, Output = T>
936 + Shr<usize, Output = T>
937 + BitAnd<Output = T>
938 + BitOr<Output = T>
939 + From<u64>,
940{
941 ((input >> (input_length - input_index)) & T::from(1)) << (output_length - output_index)
942}