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