• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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