1use bitsliced_op::{ALL_ONES, transpose_64x64};
2use wide::u64x8;
3
4use crate::{
5 des::{compute_pc1, create_subkeys, encrypt},
6 des_optimized::{compute_pc1_optimized, create_subkeys_optimized, encrypt_optimized},
7};
8
9pub mod benchmark;
10mod constants;
11pub mod des;
12pub mod des_optimized;
13pub mod sbox_optimized;
14mod utils;
15
16pub const ZERO: u64x8 = u64x8::ZERO;
17
18pub fn des(plaintext: u64, key: u64) -> u64 {
19 let (c0, d0) = compute_pc1(key);
20 let subkeys = create_subkeys(c0, d0);
21 let encrypted = encrypt(plaintext, subkeys);
22 encrypted
23}
24
25pub fn bitsliced_des_simd(plaintext: u64, keys: &[[u64; 64]; 8]) -> [[u64; 64]; 8] {
26 let mut k_slice = transpose(keys);
27 let (mut c0, mut d0) = compute_pc1_optimized(&mut k_slice);
28 let subkeys = create_subkeys_optimized(&mut c0, &mut d0);
29
30 encrypt_optimized(plaintext, subkeys, &mut k_slice);
31 let ciphertext = transpose_back(&k_slice);
32 ciphertext
33}
34
35pub fn bitsliced_des_inline_simd(plaintext: u64, keys: &mut [u64x8; 64]) {
37 let (mut c0, mut d0) = compute_pc1_optimized(keys);
38 let subkeys = create_subkeys_optimized(&mut c0, &mut d0);
39
40 encrypt_optimized(plaintext, subkeys, keys);
41}
42
43pub fn bitsliced_netntlmv1_simd(plaintext: u64, keys: &[[u64; 64]; 8]) -> [[u64; 64]; 8] {
45 let transposed = transpose(keys);
46 let mut keys = convert_to_key(&transposed);
47 bitsliced_des_inline_simd(plaintext, &mut keys);
48 let ciphertext = transpose_back(&keys);
49 ciphertext
50}
51
52pub fn bitsliced_netntlmv1_inline_simd(plaintext: u64, keys: &mut [u64x8; 64]) {
54 convert_to_key_inline(keys);
55 bitsliced_des_inline_simd(plaintext, keys);
56}
57
58const DES_KEY_PERM: [i8; 64] = [
59 0, 1, 2, 3, 4, 5, 6, -1, 7, 8, 9, 10, 11, 12, 13, -1, 14, 15, 16, 17, 18, 19, 20, -1, 21, 22,
60 23, 24, 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, 34, -1, 35, 36, 37, 38, 39, 40, 41, -1, 42, 43,
61 44, 45, 46, 47, 48, -1, 49, 50, 51, 52, 53, 54, 55, -1,
62];
63
64fn convert_to_key(plaintexts: &[u64x8; 64]) -> [u64x8; 64] {
65 let mut out = [ZERO; 64];
66 for i in 0..64 {
67 let src = DES_KEY_PERM[i];
68 if src >= 0 {
69 out[i] = plaintexts[(src as usize) + 8];
70 } else {
71 out[i] = ALL_ONES;
72 }
73 }
74 out
75}
76
77fn convert_to_key_inline(plaintexts: &mut [u64x8; 64]) {
78 let mut tmp = [ZERO; 56];
79 for i in 8..64 {
80 tmp[i - 8] = plaintexts[i];
81 }
82 for i in 0..64 {
83 let src = DES_KEY_PERM[i];
84 if src >= 0 {
85 plaintexts[i] = tmp[src as usize];
86 } else {
87 plaintexts[i] = ALL_ONES;
88 }
89 }
90}
91
92fn transpose(input: &[[u64; 64]; 8]) -> [u64x8; 64] {
93 let mut out: [u64x8; 64] = [u64x8::ZERO; 64];
94 for k in 0..8 {
95 let tmp = input[k];
96 let tmp = transpose_64x64(&tmp);
97
98 for r in 0..64 {
99 out[r].as_mut_array()[k] = tmp[r];
100 }
101 }
102 out
103}
104
105fn transpose_back(input: &[u64x8; 64]) -> [[u64; 64]; 8] {
106 let mut out = [[0u64; 64]; 8];
107
108 for j in 0..64 {
109 let tmp = input[j].as_array();
110 out[0][j] = tmp[0];
111 out[1][j] = tmp[1];
112 out[2][j] = tmp[2];
113 out[3][j] = tmp[3];
114 out[4][j] = tmp[4];
115 out[5][j] = tmp[5];
116 out[6][j] = tmp[6];
117 out[7][j] = tmp[7];
118 }
119 for k in 0..8 {
120 let tmp = out[k];
121 out[k] = transpose_64x64(&tmp);
122 }
123
124 out
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
131
132 #[test]
133 fn test_encrypt_works_correctly() {
134 let ciphertext = des(0x0123456789ABCDEF, 0x133457799BBCDFF1);
136 assert_eq!(ciphertext, 0x85E813540F0AB405);
137 }
138
139 #[test]
140 fn test_encrypt_optimized_works_correctly() {
141 let k = 0x133457799BBCDFF1u64;
143 let mut keys = [[k; 64]; 8];
144 let ciphertexts = bitsliced_des_simd(0x0123456789ABCDEF, &mut keys);
145 assert_eq!(ciphertexts[0][0], 0x85E813540F0AB405);
146 assert_eq!(ciphertexts[0][63], 0x85E813540F0AB405);
147 }
148
149 #[test]
150 fn test_encrypt_optimized_inline_works_correctly() {
151 let k = 0x133457799BBCDFF1u64;
153 let mut keys = [[k; 64]; 8];
154 let mut transposed = transpose(&keys);
155 bitsliced_des_inline_simd(0x0123456789ABCDEF, &mut transposed);
156 let ciphertexts = transpose_back(&transposed);
157 assert_eq!(ciphertexts[0][0], 0x85E813540F0AB405);
158 assert_eq!(ciphertexts[0][63], 0x85E813540F0AB405);
159 }
160
161 #[test]
162 fn test_netntlmv1_encrypt_works_correctly() {
163 let k = 0x8846F7EAEE8FB1u64;
164 let keys = [[k; 64]; 8];
165 let ciphertexts = bitsliced_netntlmv1_simd(0x1122334455667788, &keys);
166 assert_eq!(ciphertexts[0][0], 0x727B4E35F947129E);
167 assert_eq!(ciphertexts[0][63], 0x727B4E35F947129E);
168 }
169
170 #[test]
171 fn test_netntlmv1_inline_encrypt_works_correctly() {
172 let k = 0x8846F7EAEE8FB1u64;
173 let keys = [[k; 64]; 8];
174 let mut transposed = transpose(&keys);
175 bitsliced_netntlmv1_inline_simd(0x1122334455667788, &mut transposed);
176 let ciphertexts = transpose_back(&transposed);
177 assert_eq!(ciphertexts[0][0], 0x727B4E35F947129E);
178 assert_eq!(ciphertexts[0][63], 0x727B4E35F947129E);
179 }
180}