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