2 * This is D3DES (V5.09) by Richard Outerbridge with the double and
3 * triple-length support removed for use in VNC. Also the bytebit[] array
4 * has been reversed so that the most significant bit in each byte of the
5 * key is ignored, not the least significant.
8 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * A portable, public domain, version of the Data Encryption Standard.
19 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
20 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
21 * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
22 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
23 * for humouring me on.
25 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
26 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
34 static void scrunch (unsigned char *, unsigned long *);
35 static void unscrun (unsigned long *, unsigned char *);
36 static void desfunc (unsigned long *, unsigned long *);
37 static void cookey (unsigned long *);
39 static unsigned long KnL[32] = { 0L };
41 //static unsigned long KnR[32] = { 0L };
42 //static unsigned long Kn3[32] = { 0L };
44 * static unsigned char Df_Key[24] = {
45 * 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
46 * 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
47 * 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
50 static uint16_t bytebit[8] = {
51 01, 02, 04, 010, 020, 040, 0100, 0200
54 static unsigned long bigbyte[24] = {
55 0x800000L, 0x400000L, 0x200000L, 0x100000L,
56 0x80000L, 0x40000L, 0x20000L, 0x10000L,
57 0x8000L, 0x4000L, 0x2000L, 0x1000L,
58 0x800L, 0x400L, 0x200L, 0x100L,
59 0x80L, 0x40L, 0x20L, 0x10L,
60 0x8L, 0x4L, 0x2L, 0x1L
63 /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
65 static unsigned char pc1[56] = {
66 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
67 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
68 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
69 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
72 static unsigned char totrot[16] = {
73 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
76 static unsigned char pc2[48] = {
77 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
78 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
79 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
80 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
84 deskey (unsigned char *key, int32_t edf)
85 { /* Thanks to James Gillogly & Phil Karn! */
86 register int32_t i, j, l, m, n;
87 unsigned char pc1m[56], pcr[56];
90 for (j = 0; j < 56; j++) {
93 pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
95 for (i = 0; i < 16; i++) {
102 for (j = 0; j < 28; j++) {
107 pcr[j] = pc1m[l - 28];
109 for (j = 28; j < 56; j++) {
114 pcr[j] = pc1m[l - 28];
116 for (j = 0; j < 24; j++) {
119 if (pcr[pc2[j + 24]])
128 cookey (register unsigned long *raw1)
130 register unsigned long *cook, *raw0;
131 unsigned long dough[32];
135 for (i = 0; i < 16; i++, raw1++) {
137 *cook = (*raw0 & 0x00fc0000L) << 6;
138 *cook |= (*raw0 & 0x00000fc0L) << 10;
139 *cook |= (*raw1 & 0x00fc0000L) >> 10;
140 *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
141 *cook = (*raw0 & 0x0003f000L) << 12;
142 *cook |= (*raw0 & 0x0000003fL) << 16;
143 *cook |= (*raw1 & 0x0003f000L) >> 4;
144 *cook++ |= (*raw1 & 0x0000003fL);
151 cpkey (register unsigned long *into)
153 register unsigned long *from, *endp;
155 from = KnL, endp = &KnL[32];
162 usekey (register unsigned long *from)
164 register unsigned long *to, *endp;
166 to = KnL, endp = &KnL[32];
173 des (unsigned char *inblock, unsigned char *outblock)
175 unsigned long work[2];
177 scrunch (inblock, work);
179 unscrun (work, outblock);
184 scrunch (register unsigned char *outof, register unsigned long *into)
186 *into = (*outof++ & 0xffL) << 24;
187 *into |= (*outof++ & 0xffL) << 16;
188 *into |= (*outof++ & 0xffL) << 8;
189 *into++ |= (*outof++ & 0xffL);
190 *into = (*outof++ & 0xffL) << 24;
191 *into |= (*outof++ & 0xffL) << 16;
192 *into |= (*outof++ & 0xffL) << 8;
193 *into |= (*outof & 0xffL);
198 unscrun (register unsigned long *outof, register unsigned char *into)
200 *into++ = (*outof >> 24) & 0xffL;
201 *into++ = (*outof >> 16) & 0xffL;
202 *into++ = (*outof >> 8) & 0xffL;
203 *into++ = *outof++ & 0xffL;
204 *into++ = (*outof >> 24) & 0xffL;
205 *into++ = (*outof >> 16) & 0xffL;
206 *into++ = (*outof >> 8) & 0xffL;
207 *into = *outof & 0xffL;
211 static unsigned long SP1[64] = {
212 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
213 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
214 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
215 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
216 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
217 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
218 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
219 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
220 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
221 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
222 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
223 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
224 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
225 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
226 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
227 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L
230 static unsigned long SP2[64] = {
231 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
232 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
233 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
234 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
235 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
236 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
237 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
238 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
239 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
240 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
241 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
242 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
243 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
244 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
245 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
246 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L
249 static unsigned long SP3[64] = {
250 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
251 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
252 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
253 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
254 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
255 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
256 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
257 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
258 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
259 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
260 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
261 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
262 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
263 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
264 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
265 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L
268 static unsigned long SP4[64] = {
269 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
270 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
271 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
272 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
273 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
274 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
275 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
276 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
277 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
278 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
279 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
280 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
281 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
282 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
283 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
284 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L
287 static unsigned long SP5[64] = {
288 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
289 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
290 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
291 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
292 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
293 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
294 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
295 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
296 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
297 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
298 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
299 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
300 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
301 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
302 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
303 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L
306 static unsigned long SP6[64] = {
307 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
308 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
309 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
310 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
311 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
312 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
313 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
314 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
315 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
316 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
317 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
318 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
319 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
320 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
321 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
322 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L
325 static unsigned long SP7[64] = {
326 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
327 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
328 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
329 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
330 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
331 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
332 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
333 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
334 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
335 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
336 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
337 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
338 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
339 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
340 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
341 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L
344 static unsigned long SP8[64] = {
345 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
346 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
347 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
348 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
349 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
350 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
351 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
352 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
353 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
354 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
355 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
356 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
357 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
358 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
359 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
360 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L
364 desfunc (register unsigned long *block, register unsigned long *keys)
366 register unsigned long fval, work, right, leftt;
367 register int32_t round;
371 work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
373 leftt ^= (work << 4);
374 work = ((leftt >> 16) ^ right) & 0x0000ffffL;
376 leftt ^= (work << 16);
377 work = ((right >> 2) ^ leftt) & 0x33333333L;
379 right ^= (work << 2);
380 work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
382 right ^= (work << 8);
383 right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
384 work = (leftt ^ right) & 0xaaaaaaaaL;
387 leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
389 for (round = 0; round < 8; round++) {
390 work = (right << 28) | (right >> 4);
392 fval = SP7[work & 0x3fL];
393 fval |= SP5[(work >> 8) & 0x3fL];
394 fval |= SP3[(work >> 16) & 0x3fL];
395 fval |= SP1[(work >> 24) & 0x3fL];
396 work = right ^ *keys++;
397 fval |= SP8[work & 0x3fL];
398 fval |= SP6[(work >> 8) & 0x3fL];
399 fval |= SP4[(work >> 16) & 0x3fL];
400 fval |= SP2[(work >> 24) & 0x3fL];
402 work = (leftt << 28) | (leftt >> 4);
404 fval = SP7[work & 0x3fL];
405 fval |= SP5[(work >> 8) & 0x3fL];
406 fval |= SP3[(work >> 16) & 0x3fL];
407 fval |= SP1[(work >> 24) & 0x3fL];
408 work = leftt ^ *keys++;
409 fval |= SP8[work & 0x3fL];
410 fval |= SP6[(work >> 8) & 0x3fL];
411 fval |= SP4[(work >> 16) & 0x3fL];
412 fval |= SP2[(work >> 24) & 0x3fL];
416 right = (right << 31) | (right >> 1);
417 work = (leftt ^ right) & 0xaaaaaaaaL;
420 leftt = (leftt << 31) | (leftt >> 1);
421 work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
423 leftt ^= (work << 8);
424 work = ((leftt >> 2) ^ right) & 0x33333333L;
426 leftt ^= (work << 2);
427 work = ((right >> 16) ^ leftt) & 0x0000ffffL;
429 right ^= (work << 16);
430 work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
432 right ^= (work << 4);
440 * Single-length key, single-length plaintext -
441 * Key : 0123 4567 89ab cdef
442 * Plain : 0123 4567 89ab cde7
443 * Cipher : c957 4425 6a5e d31d
445 * Double-length key, single-length plaintext -
446 * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
447 * Plain : 0123 4567 89ab cde7
448 * Cipher : 7f1d 0a77 826b 8aff
450 * Double-length key, double-length plaintext -
451 * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
452 * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
453 * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
455 * Triple-length key, single-length plaintext -
456 * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
457 * Plain : 0123 4567 89ab cde7
458 * Cipher : de0b 7c06 ae5e 0ed5
460 * Triple-length key, double-length plaintext -
461 * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
462 * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
463 * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
465 * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
466 **********************************************************************/