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