1const IP: [u8; 64] = [
5 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
6 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
7 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
8 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7,
9];
10
11const FP: [u8; 64] = [
12 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
13 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
14 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
15 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25,
16];
17
18const E: [u8; 48] = [
19 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13,
20 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
21 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1,
22];
23
24const P: [u8; 32] = [
25 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
26 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,
27];
28
29const PC1: [u8; 56] = [
30 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
31 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
32 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
33 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4,
34];
35
36const PC2: [u8; 48] = [
37 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
38 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
39 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
40 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32,
41];
42
43const SHIFTS: [u8; 16] = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1];
44
45const SBOX: [[u8; 64]; 8] = [
46 [
47 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
48 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
49 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
50 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
51 ],
52 [
53 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
54 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
55 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
56 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
57 ],
58 [
59 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
60 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
61 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
62 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
63 ],
64 [
65 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
66 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
67 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
68 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
69 ],
70 [
71 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
72 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
73 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
74 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
75 ],
76 [
77 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
78 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
79 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
80 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
81 ],
82 [
83 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
84 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
85 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
86 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
87 ],
88 [
89 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
90 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
91 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
92 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
93 ],
94];
95
96#[derive(Copy, Clone)]
97pub struct DesKey {
98 subkeys: [u64; 16],
99}
100
101fn permute(input: u64, in_bits: u32, table: &[u8]) -> u64 {
102 let mut out = 0u64;
103 for (i, &p) in table.iter().enumerate() {
104 let bit = (input >> (in_bits - p as u32)) & 1;
105 out |= bit << (table.len() - 1 - i);
106 }
107 out
108}
109
110fn sbox_substitute(x: u64) -> u32 {
111 let mut out = 0u32;
112 for i in 0..8 {
113 let six = ((x >> (42 - 6 * i)) & 0x3f) as usize;
114 let row = ((six & 0x20) >> 4) | (six & 1);
115 let col = (six >> 1) & 0x0f;
116 out = (out << 4) | SBOX[i][row * 16 + col] as u32;
117 }
118 out
119}
120
121pub fn des_setkey(key: &[u8; 8]) -> DesKey {
122 let mut k = 0u64;
123 for &b in key.iter() { k = (k << 8) | b as u64; }
124 let pc1 = permute(k, 64, &PC1);
125 let mut c = ((pc1 >> 28) & 0x0fff_ffff) as u32;
126 let mut d = (pc1 & 0x0fff_ffff) as u32;
127 let mut subkeys = [0u64; 16];
128 for r in 0..16 {
129 let s = SHIFTS[r] as u32;
130 c = ((c << s) | (c >> (28 - s))) & 0x0fff_ffff;
131 d = ((d << s) | (d >> (28 - s))) & 0x0fff_ffff;
132 let cd = ((c as u64) << 28) | d as u64;
133 subkeys[r] = permute(cd, 56, &PC2);
134 }
135 DesKey { subkeys }
136}
137
138pub fn des_do(l_in: u32, r_in: u32, count: u32, saltbits: u32, key: &DesKey) -> (u32, u32) {
141 let block = ((l_in as u64) << 32) | r_in as u64;
142 let ip = permute(block, 64, &IP);
143 let mut l = (ip >> 32) as u32;
144 let mut r = ip as u32;
145 for _ in 0..count {
146 for round in 0..16 {
147 let mut e = permute(r as u64, 32, &E);
148 if saltbits != 0 {
149 let hi = (e >> 24) as u32;
150 let lo = (e & 0x00ff_ffff) as u32;
151 let f = (hi ^ lo) & saltbits;
152 e = (((hi ^ f) as u64) << 24) | (lo ^ f) as u64;
153 }
154 let x = e ^ key.subkeys[round];
155 let s = sbox_substitute(x) as u64;
156 let p = permute(s, 32, &P) as u32;
157 let nl = r;
158 let nr = l ^ p;
159 l = nl;
160 r = nr;
161 }
162 core::mem::swap(&mut l, &mut r);
164 }
165 let pre = ((l as u64) << 32) | r as u64;
166 let fp = permute(pre, 64, &FP);
167 ((fp >> 32) as u32, fp as u32)
168}
169
170pub fn des_cipher_block(key: &DesKey, input: &[u8; 8], count: u32, saltbits: u32) -> [u8; 8] {
171 let l = u32::from_be_bytes([input[0], input[1], input[2], input[3]]);
172 let r = u32::from_be_bytes([input[4], input[5], input[6], input[7]]);
173 let (lo, ro) = des_do(l, r, count, saltbits, key);
174 let mut out = [0u8; 8];
175 out[0..4].copy_from_slice(&lo.to_be_bytes());
176 out[4..8].copy_from_slice(&ro.to_be_bytes());
177 out
178}
179
180pub fn setup_salt(salt: u32) -> u32 {
181 let mut saltbits = 0u32;
182 let mut saltbit = 1u32;
183 let mut obit = 0x0080_0000u32;
184 for _ in 0..24 {
185 if salt & saltbit != 0 { saltbits |= obit; }
186 saltbit <<= 1;
187 obit >>= 1;
188 }
189 saltbits
190}
191
192fn ascii_to_bin(ch: u8) -> u32 {
193 let sch = ch as i8 as i32;
194 let mut retval = sch - '.' as i32;
195 if sch >= 'A' as i32 {
196 retval = sch - ('A' as i32 - 12);
197 if sch >= 'a' as i32 {
198 retval = sch - ('a' as i32 - 38);
199 }
200 }
201 (retval & 0x3f) as u32
202}
203
204const ASCII64: &[u8; 64] = b"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
205
206fn ascii_is_unsafe(ch: u8) -> bool {
207 ch == 0 || ch == b'\n' || ch == b':'
208}
209
210fn read_setting_char(s: *const u8, i: usize) -> u8 {
211 unsafe { *s.add(i) }
212}
213
214pub unsafe fn crypt_des(key: *const u8, setting: *const u8, output: *mut u8) -> usize {
217 if key.is_null() || setting.is_null() || output.is_null() { return 0; }
218 let mut keybuf = [0u8; 8];
219 let mut kp = key;
220 for i in 0..8 {
221 keybuf[i] = (*kp) << 1;
222 if *kp != 0 { kp = kp.add(1); }
223 }
224 let mut ekey = des_setkey(&keybuf);
225
226 let count: u32;
227 let salt: u32;
228 let mut outpos: usize;
229 if *setting == b'_' {
230 let mut c = 0u32;
231 for i in 1..5 {
232 let ch = read_setting_char(setting, i);
233 let v = ascii_to_bin(ch);
234 if ASCII64[v as usize] != ch { return 0; }
235 c |= v << ((i - 1) * 6);
236 }
237 if c == 0 { return 0; }
238 count = c;
239 let mut s = 0u32;
240 for i in 5..9 {
241 let ch = read_setting_char(setting, i);
242 let v = ascii_to_bin(ch);
243 if ASCII64[v as usize] != ch { return 0; }
244 s |= v << ((i - 5) * 6);
245 }
246 salt = s;
247 while *kp != 0 {
248 keybuf = des_cipher_block(&ekey, &keybuf, 1, 0);
249 for i in 0..8 {
250 if *kp == 0 { break; }
251 keybuf[i] ^= (*kp) << 1;
252 kp = kp.add(1);
253 }
254 ekey = des_setkey(&keybuf);
255 }
256 for i in 0..9 { *output.add(i) = *setting.add(i); }
257 *output.add(9) = 0;
258 outpos = 9;
259 } else {
260 count = 25;
261 let s0 = *setting;
262 let s1 = *setting.add(1);
263 if s1 == 0 || ascii_is_unsafe(s0) || ascii_is_unsafe(s1) { return 0; }
264 salt = (ascii_to_bin(s1) << 6) | ascii_to_bin(s0);
265 *output = s0;
266 *output.add(1) = s1;
267 outpos = 2;
268 }
269
270 let (r0, r1) = des_do(0, 0, count, setup_salt(salt), &ekey);
271
272 let mut l = r0 >> 8;
273 *output.add(outpos) = ASCII64[((l >> 18) & 0x3f) as usize]; outpos += 1;
274 *output.add(outpos) = ASCII64[((l >> 12) & 0x3f) as usize]; outpos += 1;
275 *output.add(outpos) = ASCII64[((l >> 6) & 0x3f) as usize]; outpos += 1;
276 *output.add(outpos) = ASCII64[(l & 0x3f) as usize]; outpos += 1;
277 l = (r0 << 16) | ((r1 >> 16) & 0xffff);
278 *output.add(outpos) = ASCII64[((l >> 18) & 0x3f) as usize]; outpos += 1;
279 *output.add(outpos) = ASCII64[((l >> 12) & 0x3f) as usize]; outpos += 1;
280 *output.add(outpos) = ASCII64[((l >> 6) & 0x3f) as usize]; outpos += 1;
281 *output.add(outpos) = ASCII64[(l & 0x3f) as usize]; outpos += 1;
282 l = r1 << 2;
283 *output.add(outpos) = ASCII64[((l >> 12) & 0x3f) as usize]; outpos += 1;
284 *output.add(outpos) = ASCII64[((l >> 6) & 0x3f) as usize]; outpos += 1;
285 *output.add(outpos) = ASCII64[(l & 0x3f) as usize]; outpos += 1;
286 *output.add(outpos) = 0;
287 outpos
288}
289
290static mut ENCRYPT_KEY: DesKey = DesKey { subkeys: [0; 16] };
291
292#[no_mangle]
293pub unsafe extern "C" fn setkey(key: *const c_char) {
294 if key.is_null() { return; }
295 let mut bkey = [0u8; 8];
296 let mut kp = key as *const u8;
297 for i in 0..8 {
298 let mut v = 0u8;
299 for j in (0..8).rev() {
300 v |= ((*kp as u8) & 1) << j;
301 kp = kp.add(1);
302 }
303 bkey[i] = v;
304 }
305 ENCRYPT_KEY = des_setkey(&bkey);
306}
307
308#[no_mangle]
309pub unsafe extern "C" fn encrypt(block: *mut c_char, edflag: c_int) {
310 if block.is_null() { return; }
311 let mut b = [0u32; 2];
312 let mut p = block as *const u8;
313 for i in 0..2 {
314 let mut v = 0u32;
315 for j in (0..32).rev() {
316 v |= ((*p & 1) as u32) << j;
317 p = p.add(1);
318 }
319 b[i] = v;
320 }
321 let mut key = ENCRYPT_KEY;
322 if edflag != 0 {
323 let mut rev = [0u64; 16];
324 for i in 0..16 { rev[i] = ENCRYPT_KEY.subkeys[15 - i]; }
325 key = DesKey { subkeys: rev };
326 }
327 let (lo, ro) = des_do(b[0], b[1], 1, 0, &key);
328 b[0] = lo;
329 b[1] = ro;
330 let mut q = block as *mut u8;
331 for i in 0..2 {
332 for j in (0..32).rev() {
333 *q = ((b[i] >> j) & 1) as u8;
334 q = q.add(1);
335 }
336 }
337}