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