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.
31
static void scrunch(unsigned char *, unsigned long *);
32
static void unscrun(unsigned long *, unsigned char *);
33
static void desfunc(unsigned long *, unsigned long *);
34
static void cookey(unsigned long *);
36
static unsigned long KnL[32] = { 0L };
38
static unsigned long KnR[32] = { 0L };
39
static unsigned long Kn3[32] = { 0L };
40
static unsigned char Df_Key[24] = {
41
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
42
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
43
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
46
static unsigned short bytebit[8] = {
47
01, 02, 04, 010, 020, 040, 0100, 0200 };
49
static unsigned long bigbyte[24] = {
50
0x800000L, 0x400000L, 0x200000L, 0x100000L,
51
0x80000L, 0x40000L, 0x20000L, 0x10000L,
52
0x8000L, 0x4000L, 0x2000L, 0x1000L,
53
0x800L, 0x400L, 0x200L, 0x100L,
54
0x80L, 0x40L, 0x20L, 0x10L,
55
0x8L, 0x4L, 0x2L, 0x1L };
57
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
59
static unsigned char pc1[56] = {
60
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
61
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
63
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
65
static unsigned char totrot[16] = {
66
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
68
static unsigned char pc2[48] = {
69
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
70
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
71
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
72
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
74
void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
78
register int i, j, l, m, n;
79
unsigned char pc1m[56], pcr[56];
82
for ( j = 0; j < 56; j++ ) {
85
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
87
for( i = 0; i < 16; i++ ) {
88
if( edf == DE1 ) m = (15 - i) << 1;
92
for( j = 0; j < 28; j++ ) {
94
if( l < 28 ) pcr[j] = pc1m[l];
95
else pcr[j] = pc1m[l - 28];
97
for( j = 28; j < 56; j++ ) {
99
if( l < 56 ) pcr[j] = pc1m[l];
100
else pcr[j] = pc1m[l - 28];
102
for( j = 0; j < 24; j++ ) {
103
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
104
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
111
static void cookey(raw1)
112
register unsigned long *raw1;
114
register unsigned long *cook, *raw0;
115
unsigned long dough[32];
119
for( i = 0; i < 16; i++, raw1++ ) {
121
*cook = (*raw0 & 0x00fc0000L) << 6;
122
*cook |= (*raw0 & 0x00000fc0L) << 10;
123
*cook |= (*raw1 & 0x00fc0000L) >> 10;
124
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
125
*cook = (*raw0 & 0x0003f000L) << 12;
126
*cook |= (*raw0 & 0x0000003fL) << 16;
127
*cook |= (*raw1 & 0x0003f000L) >> 4;
128
*cook++ |= (*raw1 & 0x0000003fL);
135
register unsigned long *into;
137
register unsigned long *from, *endp;
139
from = KnL, endp = &KnL[32];
140
while( from < endp ) *into++ = *from++;
145
register unsigned long *from;
147
register unsigned long *to, *endp;
149
to = KnL, endp = &KnL[32];
150
while( to < endp ) *to++ = *from++;
154
void des(inblock, outblock)
155
unsigned char *inblock, *outblock;
157
unsigned long work[2];
159
scrunch(inblock, work);
161
unscrun(work, outblock);
165
static void scrunch(outof, into)
166
register unsigned char *outof;
167
register unsigned long *into;
169
*into = (*outof++ & 0xffL) << 24;
170
*into |= (*outof++ & 0xffL) << 16;
171
*into |= (*outof++ & 0xffL) << 8;
172
*into++ |= (*outof++ & 0xffL);
173
*into = (*outof++ & 0xffL) << 24;
174
*into |= (*outof++ & 0xffL) << 16;
175
*into |= (*outof++ & 0xffL) << 8;
176
*into |= (*outof & 0xffL);
180
static void unscrun(outof, into)
181
register unsigned long *outof;
182
register unsigned char *into;
184
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
185
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
186
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
187
*into++ = (unsigned char)( *outof++ & 0xffL);
188
*into++ = (unsigned char)((*outof >> 24) & 0xffL);
189
*into++ = (unsigned char)((*outof >> 16) & 0xffL);
190
*into++ = (unsigned char)((*outof >> 8) & 0xffL);
191
*into = (unsigned char)( *outof & 0xffL);
195
static unsigned long SP1[64] = {
196
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
197
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
198
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
199
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
200
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
201
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
202
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
203
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
204
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
205
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
206
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
207
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
208
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
209
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
210
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
211
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
213
static unsigned long SP2[64] = {
214
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
215
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
216
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
217
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
218
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
219
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
220
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
221
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
222
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
223
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
224
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
225
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
226
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
227
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
228
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
229
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
231
static unsigned long SP3[64] = {
232
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
233
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
234
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
235
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
236
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
237
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
238
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
239
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
240
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
241
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
242
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
243
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
244
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
245
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
246
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
247
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
249
static unsigned long SP4[64] = {
250
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
251
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
252
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
253
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
254
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
255
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
256
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
257
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
258
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
259
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
260
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
261
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
262
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
263
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
264
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
265
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
267
static unsigned long SP5[64] = {
268
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
269
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
270
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
271
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
272
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
273
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
274
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
275
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
276
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
277
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
278
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
279
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
280
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
281
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
282
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
283
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
285
static unsigned long SP6[64] = {
286
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
287
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
288
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
289
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
290
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
291
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
292
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
293
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
294
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
295
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
296
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
297
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
298
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
299
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
300
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
301
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
303
static unsigned long SP7[64] = {
304
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
305
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
306
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
307
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
308
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
309
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
310
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
311
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
312
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
313
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
314
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
315
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
316
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
317
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
318
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
319
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
321
static unsigned long SP8[64] = {
322
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
323
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
324
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
325
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
326
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
327
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
328
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
329
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
330
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
331
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
332
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
333
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
334
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
335
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
336
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
337
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
339
static void desfunc(block, keys)
340
register unsigned long *block, *keys;
342
register unsigned long fval, work, right, leftt;
347
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
349
leftt ^= (work << 4);
350
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
352
leftt ^= (work << 16);
353
work = ((right >> 2) ^ leftt) & 0x33333333L;
355
right ^= (work << 2);
356
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
358
right ^= (work << 8);
359
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
360
work = (leftt ^ right) & 0xaaaaaaaaL;
363
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
365
for( round = 0; round < 8; round++ ) {
366
work = (right << 28) | (right >> 4);
368
fval = SP7[ work & 0x3fL];
369
fval |= SP5[(work >> 8) & 0x3fL];
370
fval |= SP3[(work >> 16) & 0x3fL];
371
fval |= SP1[(work >> 24) & 0x3fL];
372
work = right ^ *keys++;
373
fval |= SP8[ work & 0x3fL];
374
fval |= SP6[(work >> 8) & 0x3fL];
375
fval |= SP4[(work >> 16) & 0x3fL];
376
fval |= SP2[(work >> 24) & 0x3fL];
378
work = (leftt << 28) | (leftt >> 4);
380
fval = SP7[ work & 0x3fL];
381
fval |= SP5[(work >> 8) & 0x3fL];
382
fval |= SP3[(work >> 16) & 0x3fL];
383
fval |= SP1[(work >> 24) & 0x3fL];
384
work = leftt ^ *keys++;
385
fval |= SP8[ work & 0x3fL];
386
fval |= SP6[(work >> 8) & 0x3fL];
387
fval |= SP4[(work >> 16) & 0x3fL];
388
fval |= SP2[(work >> 24) & 0x3fL];
392
right = (right << 31) | (right >> 1);
393
work = (leftt ^ right) & 0xaaaaaaaaL;
396
leftt = (leftt << 31) | (leftt >> 1);
397
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
399
leftt ^= (work << 8);
400
work = ((leftt >> 2) ^ right) & 0x33333333L;
402
leftt ^= (work << 2);
403
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
405
right ^= (work << 16);
406
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
408
right ^= (work << 4);
416
* Single-length key, single-length plaintext -
417
* Key : 0123 4567 89ab cdef
418
* Plain : 0123 4567 89ab cde7
419
* Cipher : c957 4425 6a5e d31d
421
* Double-length key, single-length plaintext -
422
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
423
* Plain : 0123 4567 89ab cde7
424
* Cipher : 7f1d 0a77 826b 8aff
426
* Double-length key, double-length plaintext -
427
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
428
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
429
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
431
* Triple-length key, single-length plaintext -
432
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
433
* Plain : 0123 4567 89ab cde7
434
* Cipher : de0b 7c06 ae5e 0ed5
436
* Triple-length key, double-length plaintext -
437
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
438
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
439
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
441
* d3des V5.0a rwo 9208.07 18:44 Graven Imagery
442
**********************************************************************/