1 /*
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.
6  *
7  * These changes are Copyright (C) 1998 Olivetti & Oracle Research Laboratory
8  *
9  * This software is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  */
13 
14 /* D3DES (V5.09) -
15  *
16  * A portable, public domain, version of the Data Encryption Standard.
17  *
18  * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
19  * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
20  * code;  Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
21  * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
22  * for humouring me on.
23  *
24  * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
25  * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
26  */
27 
28 #include "d3des.h"
29 
30 static void scrunch(unsigned char *, unsigned long *);
31 static void unscrun(unsigned long *, unsigned char *);
32 static void desfunc(unsigned long *, unsigned long *);
33 static void cookey(unsigned long *);
34 
35 static unsigned long KnL[32] = { 0L };
36 static unsigned long KnR[32] = { 0L };
37 static unsigned long Kn3[32] = { 0L };
38 static unsigned char Df_Key[24] = {
39 	0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
40 	0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
41 	0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
42 
43 static unsigned short bytebit[8]	= {
44 	01, 02, 04, 010, 020, 040, 0100, 0200 };
45 
46 static unsigned long bigbyte[24] = {
47 	0x800000L,	0x400000L,	0x200000L,	0x100000L,
48 	0x80000L,	0x40000L,	0x20000L,	0x10000L,
49 	0x8000L,	0x4000L,	0x2000L,	0x1000L,
50 	0x800L, 	0x400L, 	0x200L, 	0x100L,
51 	0x80L,		0x40L,		0x20L,		0x10L,
52 	0x8L,		0x4L,		0x2L,		0x1L	};
53 
54 /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
55 
56 static unsigned char pc1[56] = {
57 	56, 48, 40, 32, 24, 16,  8,	 0, 57, 49, 41, 33, 25, 17,
58 	 9,  1, 58, 50, 42, 34, 26,	18, 10,  2, 59, 51, 43, 35,
59 	62, 54, 46, 38, 30, 22, 14,	 6, 61, 53, 45, 37, 29, 21,
60 	13,  5, 60, 52, 44, 36, 28,	20, 12,  4, 27, 19, 11,  3 };
61 
62 static unsigned char totrot[16] = {
63 	1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
64 
65 static unsigned char pc2[48] = {
66 	13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
67 	22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
68 	40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
69 	43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
70 
deskey(key,edf)71 void deskey(key, edf)	/* Thanks to James Gillogly & Phil Karn! */
72 unsigned char *key;
73 short edf;
74 {
75 	register int i, j, l, m, n;
76 	unsigned char pc1m[56], pcr[56];
77 	unsigned long kn[32];
78 
79 	for ( j = 0; j < 56; j++ ) {
80 		l = pc1[j];
81 		m = l & 07;
82 		pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
83 		}
84 	for( i = 0; i < 16; i++ ) {
85 		if( edf == DE1 ) m = (15 - i) << 1;
86 		else m = i << 1;
87 		n = m + 1;
88 		kn[m] = kn[n] = 0L;
89 		for( j = 0; j < 28; j++ ) {
90 			l = j + totrot[i];
91 			if( l < 28 ) pcr[j] = pc1m[l];
92 			else pcr[j] = pc1m[l - 28];
93 			}
94 		for( j = 28; j < 56; j++ ) {
95 		    l = j + totrot[i];
96 		    if( l < 56 ) pcr[j] = pc1m[l];
97 		    else pcr[j] = pc1m[l - 28];
98 		    }
99 		for( j = 0; j < 24; j++ ) {
100 			if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
101 			if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
102 			}
103 		}
104 	cookey(kn);
105 	return;
106 	}
107 
cookey(raw1)108 static void cookey(raw1)
109 register unsigned long *raw1;
110 {
111 	register unsigned long *cook, *raw0;
112 	unsigned long dough[32];
113 	register int i;
114 
115 	cook = dough;
116 	for( i = 0; i < 16; i++, raw1++ ) {
117 		raw0 = raw1++;
118 		*cook	 = (*raw0 & 0x00fc0000L) << 6;
119 		*cook	|= (*raw0 & 0x00000fc0L) << 10;
120 		*cook	|= (*raw1 & 0x00fc0000L) >> 10;
121 		*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
122 		*cook	 = (*raw0 & 0x0003f000L) << 12;
123 		*cook	|= (*raw0 & 0x0000003fL) << 16;
124 		*cook	|= (*raw1 & 0x0003f000L) >> 4;
125 		*cook++ |= (*raw1 & 0x0000003fL);
126 		}
127 	usekey(dough);
128 	return;
129 	}
130 
cpkey(into)131 void cpkey(into)
132 register unsigned long *into;
133 {
134 	register unsigned long *from, *endp;
135 
136 	from = KnL, endp = &KnL[32];
137 	while( from < endp ) *into++ = *from++;
138 	return;
139 	}
140 
usekey(from)141 void usekey(from)
142 register unsigned long *from;
143 {
144 	register unsigned long *to, *endp;
145 
146 	to = KnL, endp = &KnL[32];
147 	while( to < endp ) *to++ = *from++;
148 	return;
149 	}
150 
des(inblock,outblock)151 void des(inblock, outblock)
152 unsigned char *inblock, *outblock;
153 {
154 	unsigned long work[2];
155 
156 	scrunch(inblock, work);
157 	desfunc(work, KnL);
158 	unscrun(work, outblock);
159 	return;
160 	}
161 
scrunch(outof,into)162 static void scrunch(outof, into)
163 register unsigned char *outof;
164 register unsigned long *into;
165 {
166 	*into	 = (*outof++ & 0xffL) << 24;
167 	*into	|= (*outof++ & 0xffL) << 16;
168 	*into	|= (*outof++ & 0xffL) << 8;
169 	*into++ |= (*outof++ & 0xffL);
170 	*into	 = (*outof++ & 0xffL) << 24;
171 	*into	|= (*outof++ & 0xffL) << 16;
172 	*into	|= (*outof++ & 0xffL) << 8;
173 	*into	|= (*outof   & 0xffL);
174 	return;
175 	}
176 
unscrun(outof,into)177 static void unscrun(outof, into)
178 register unsigned long *outof;
179 register unsigned char *into;
180 {
181 	*into++ = (*outof >> 24) & 0xffL;
182 	*into++ = (*outof >> 16) & 0xffL;
183 	*into++ = (*outof >>  8) & 0xffL;
184 	*into++ =  *outof++	 & 0xffL;
185 	*into++ = (*outof >> 24) & 0xffL;
186 	*into++ = (*outof >> 16) & 0xffL;
187 	*into++ = (*outof >>  8) & 0xffL;
188 	*into	=  *outof	 & 0xffL;
189 	return;
190 	}
191 
192 static unsigned long SP1[64] = {
193 	0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
194 	0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
195 	0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
196 	0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
197 	0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
198 	0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
199 	0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
200 	0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
201 	0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
202 	0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
203 	0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
204 	0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
205 	0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
206 	0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
207 	0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
208 	0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
209 
210 static unsigned long SP2[64] = {
211 	0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
212 	0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
213 	0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
214 	0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
215 	0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
216 	0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
217 	0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
218 	0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
219 	0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
220 	0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
221 	0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
222 	0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
223 	0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
224 	0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
225 	0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
226 	0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
227 
228 static unsigned long SP3[64] = {
229 	0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
230 	0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
231 	0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
232 	0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
233 	0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
234 	0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
235 	0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
236 	0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
237 	0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
238 	0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
239 	0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
240 	0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
241 	0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
242 	0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
243 	0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
244 	0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
245 
246 static unsigned long SP4[64] = {
247 	0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
248 	0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
249 	0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
250 	0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
251 	0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
252 	0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
253 	0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
254 	0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
255 	0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
256 	0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
257 	0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
258 	0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
259 	0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
260 	0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
261 	0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
262 	0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
263 
264 static unsigned long SP5[64] = {
265 	0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
266 	0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
267 	0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
268 	0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
269 	0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
270 	0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
271 	0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
272 	0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
273 	0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
274 	0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
275 	0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
276 	0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
277 	0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
278 	0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
279 	0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
280 	0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
281 
282 static unsigned long SP6[64] = {
283 	0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
284 	0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
285 	0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
286 	0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
287 	0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
288 	0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
289 	0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
290 	0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
291 	0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
292 	0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
293 	0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
294 	0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
295 	0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
296 	0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
297 	0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
298 	0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
299 
300 static unsigned long SP7[64] = {
301 	0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
302 	0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
303 	0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
304 	0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
305 	0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
306 	0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
307 	0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
308 	0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
309 	0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
310 	0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
311 	0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
312 	0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
313 	0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
314 	0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
315 	0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
316 	0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
317 
318 static unsigned long SP8[64] = {
319 	0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
320 	0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
321 	0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
322 	0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
323 	0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
324 	0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
325 	0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
326 	0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
327 	0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
328 	0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
329 	0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
330 	0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
331 	0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
332 	0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
333 	0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
334 	0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
335 
desfunc(block,keys)336 static void desfunc(block, keys)
337 register unsigned long *block, *keys;
338 {
339 	register unsigned long fval, work, right, leftt;
340 	register int round;
341 
342 	leftt = block[0];
343 	right = block[1];
344 	work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
345 	right ^= work;
346 	leftt ^= (work << 4);
347 	work = ((leftt >> 16) ^ right) & 0x0000ffffL;
348 	right ^= work;
349 	leftt ^= (work << 16);
350 	work = ((right >> 2) ^ leftt) & 0x33333333L;
351 	leftt ^= work;
352 	right ^= (work << 2);
353 	work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
354 	leftt ^= work;
355 	right ^= (work << 8);
356 	right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
357 	work = (leftt ^ right) & 0xaaaaaaaaL;
358 	leftt ^= work;
359 	right ^= work;
360 	leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
361 
362 	for( round = 0; round < 8; round++ ) {
363 		work  = (right << 28) | (right >> 4);
364 		work ^= *keys++;
365 		fval  = SP7[ work		 & 0x3fL];
366 		fval |= SP5[(work >>  8) & 0x3fL];
367 		fval |= SP3[(work >> 16) & 0x3fL];
368 		fval |= SP1[(work >> 24) & 0x3fL];
369 		work  = right ^ *keys++;
370 		fval |= SP8[ work		 & 0x3fL];
371 		fval |= SP6[(work >>  8) & 0x3fL];
372 		fval |= SP4[(work >> 16) & 0x3fL];
373 		fval |= SP2[(work >> 24) & 0x3fL];
374 		leftt ^= fval;
375 		work  = (leftt << 28) | (leftt >> 4);
376 		work ^= *keys++;
377 		fval  = SP7[ work		 & 0x3fL];
378 		fval |= SP5[(work >>  8) & 0x3fL];
379 		fval |= SP3[(work >> 16) & 0x3fL];
380 		fval |= SP1[(work >> 24) & 0x3fL];
381 		work  = leftt ^ *keys++;
382 		fval |= SP8[ work		 & 0x3fL];
383 		fval |= SP6[(work >>  8) & 0x3fL];
384 		fval |= SP4[(work >> 16) & 0x3fL];
385 		fval |= SP2[(work >> 24) & 0x3fL];
386 		right ^= fval;
387 		}
388 
389 	right = (right << 31) | (right >> 1);
390 	work = (leftt ^ right) & 0xaaaaaaaaL;
391 	leftt ^= work;
392 	right ^= work;
393 	leftt = (leftt << 31) | (leftt >> 1);
394 	work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
395 	right ^= work;
396 	leftt ^= (work << 8);
397 	work = ((leftt >> 2) ^ right) & 0x33333333L;
398 	right ^= work;
399 	leftt ^= (work << 2);
400 	work = ((right >> 16) ^ leftt) & 0x0000ffffL;
401 	leftt ^= work;
402 	right ^= (work << 16);
403 	work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
404 	leftt ^= work;
405 	right ^= (work << 4);
406 	*block++ = right;
407 	*block = leftt;
408 	return;
409 	}
410 
411 /* Validation sets:
412  *
413  * Single-length key, single-length plaintext -
414  * Key	  : 0123 4567 89ab cdef
415  * Plain  : 0123 4567 89ab cde7
416  * Cipher : c957 4425 6a5e d31d
417  *
418  * Double-length key, single-length plaintext -
419  * Key	  : 0123 4567 89ab cdef fedc ba98 7654 3210
420  * Plain  : 0123 4567 89ab cde7
421  * Cipher : 7f1d 0a77 826b 8aff
422  *
423  * Double-length key, double-length plaintext -
424  * Key	  : 0123 4567 89ab cdef fedc ba98 7654 3210
425  * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff
426  * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
427  *
428  * Triple-length key, single-length plaintext -
429  * Key	  : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
430  * Plain  : 0123 4567 89ab cde7
431  * Cipher : de0b 7c06 ae5e 0ed5
432  *
433  * Triple-length key, double-length plaintext -
434  * Key	  : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
435  * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff
436  * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
437  *
438  * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
439  **********************************************************************/
440