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