target-alpha: fix extlh instruction
[armpft.git] / d3des.c
blob60c840ed53fa647e2668bbe22c965c31bc6682bc
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.
7 * These changes are:
8 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
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.
15 /* D3DES (V5.09) -
17 * A portable, public domain, version of the Data Encryption Standard.
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.
25 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
26 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
29 #include "d3des.h"
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 *);
36 static unsigned long KnL[32] = { 0L };
38 static const unsigned short bytebit[8] = {
39 01, 02, 04, 010, 020, 040, 0100, 0200 };
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 };
49 /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
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 };
57 static const unsigned char totrot[16] = {
58 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
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 };
66 /* Thanks to James Gillogly & Phil Karn! */
67 void deskey(unsigned char *key, int edf)
69 register int i, j, l, m, n;
70 unsigned char pc1m[56], pcr[56];
71 unsigned long kn[32];
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;
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];
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];
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];
98 cookey(kn);
99 return;
102 static void cookey(register unsigned long *raw1)
104 register unsigned long *cook, *raw0;
105 unsigned long dough[32];
106 register int i;
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);
120 usekey(dough);
121 return;
124 void cpkey(register unsigned long *into)
126 register unsigned long *from, *endp;
128 from = KnL, endp = &KnL[32];
129 while( from < endp ) *into++ = *from++;
130 return;
133 void usekey(register unsigned long *from)
135 register unsigned long *to, *endp;
137 to = KnL, endp = &KnL[32];
138 while( to < endp ) *to++ = *from++;
139 return;
142 void des(unsigned char *inblock, unsigned char *outblock)
144 unsigned long work[2];
146 scrunch(inblock, work);
147 desfunc(work, KnL);
148 unscrun(work, outblock);
149 return;
152 static void scrunch(register unsigned char *outof, register unsigned long *into)
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;
165 static void unscrun(register unsigned long *outof, register unsigned char *into)
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;
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 };
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 };
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 };
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 };
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 };
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 };
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 };
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 };
322 static void desfunc(register unsigned long *block, register unsigned long *keys)
324 register unsigned long fval, work, right, leftt;
325 register int round;
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;
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;
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;
396 /* Validation sets:
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
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
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
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
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
423 * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
424 **********************************************************************/