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