initial checkin
[org.ibex.nanogoat.git] / src / org / bouncycastle / crypto / engines / DESEngine.java
1 package org.bouncycastle.crypto.engines;
2
3 import java.lang.IllegalStateException;
4
5 import org.bouncycastle.crypto.BlockCipher;
6 import org.bouncycastle.crypto.CipherParameters;
7 import org.bouncycastle.crypto.DataLengthException;
8 import org.bouncycastle.crypto.params.KeyParameter;
9
10 /**
11  * a class that provides a basic DES engine.
12  */
13 public class DESEngine
14     implements BlockCipher
15 {
16     protected static final int  BLOCK_SIZE = 8;
17
18     private int[]               workingKey = null;
19
20     /**
21      * standard constructor.
22      */
23     public DESEngine()
24     {
25     }
26
27     /**
28      * initialise a DES cipher.
29      *
30      * @param forEncryption whether or not we are for encryption.
31      * @param params the parameters required to set up the cipher.
32      * @exception IllegalArgumentException if the params argument is
33      * inappropriate.
34      */
35     public void init(
36         boolean           encrypting,
37         CipherParameters  params)
38     {
39         if (params instanceof KeyParameter)
40         {
41             workingKey = generateWorkingKey(encrypting,
42                                   ((KeyParameter)params).getKey());
43
44             return;
45         }
46
47         throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
48     }
49
50     public String getAlgorithmName()
51     {
52         return "DES";
53     }
54
55     public int getBlockSize()
56     {
57         return BLOCK_SIZE;
58     }
59
60     public int processBlock(
61         byte[] in,
62         int inOff,
63         byte[] out,
64         int outOff)
65     {
66         if (workingKey == null)
67         {
68             throw new IllegalStateException("DES engine not initialised");
69         }
70
71         if ((inOff + BLOCK_SIZE) > in.length)
72         {
73             throw new DataLengthException("input buffer too short");
74         }
75
76         if ((outOff + BLOCK_SIZE) > out.length)
77         {
78             throw new DataLengthException("output buffer too short");
79         }
80
81         desFunc(workingKey, in, inOff, out, outOff);
82
83         return BLOCK_SIZE;
84     }
85
86     public void reset()
87     {
88     }
89
90     /**
91      * what follows is mainly taken from "Applied Cryptography", by
92      * Bruce Schneier, however it also bears great resemblance to Richard
93      * Outerbridge's D3DES...
94      */
95
96     static short[]    Df_Key =
97         {
98             0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
99             0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
100             0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
101         };
102
103     static short[]    bytebit =
104         {
105             0200, 0100, 040, 020, 010, 04, 02, 01
106         };
107
108     static int[]    bigbyte =
109         {
110             0x800000, 0x400000, 0x200000, 0x100000,
111             0x80000,  0x40000,  0x20000,  0x10000,
112             0x8000,      0x4000,   0x2000,   0x1000,
113             0x800,    0x400,    0x200,    0x100,
114             0x80,      0x40,        0x20,     0x10,
115             0x8,      0x4,      0x2,      0x1
116         };
117
118     /*
119      * Use the key schedule specified in the Standard (ANSI X3.92-1981).
120      */
121
122     static byte[]    pc1 =
123         {
124             56, 48, 40, 32, 24, 16,  8,   0, 57, 49, 41, 33, 25, 17,
125              9,  1, 58, 50, 42, 34, 26,  18, 10,  2, 59, 51, 43, 35,
126             62, 54, 46, 38, 30, 22, 14,   6, 61, 53, 45, 37, 29, 21,
127             13,  5, 60, 52, 44, 36, 28,  20, 12,  4, 27, 19, 11,  3
128         };
129
130     static byte[] totrot =
131         {
132             1, 2, 4, 6, 8, 10, 12, 14,
133             15, 17, 19, 21, 23, 25, 27, 28
134         };
135
136     static byte[] pc2 =
137         {
138             13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
139             22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
140             40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
141             43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
142         };
143
144     static int[] SP1 = {
145         0x01010400, 0x00000000, 0x00010000, 0x01010404,
146         0x01010004, 0x00010404, 0x00000004, 0x00010000,
147         0x00000400, 0x01010400, 0x01010404, 0x00000400,
148         0x01000404, 0x01010004, 0x01000000, 0x00000004,
149         0x00000404, 0x01000400, 0x01000400, 0x00010400,
150         0x00010400, 0x01010000, 0x01010000, 0x01000404,
151         0x00010004, 0x01000004, 0x01000004, 0x00010004,
152         0x00000000, 0x00000404, 0x00010404, 0x01000000,
153         0x00010000, 0x01010404, 0x00000004, 0x01010000,
154         0x01010400, 0x01000000, 0x01000000, 0x00000400,
155         0x01010004, 0x00010000, 0x00010400, 0x01000004,
156         0x00000400, 0x00000004, 0x01000404, 0x00010404,
157         0x01010404, 0x00010004, 0x01010000, 0x01000404,
158         0x01000004, 0x00000404, 0x00010404, 0x01010400,
159         0x00000404, 0x01000400, 0x01000400, 0x00000000,
160         0x00010004, 0x00010400, 0x00000000, 0x01010004
161     };
162
163     static int[] SP2 = {
164         0x80108020, 0x80008000, 0x00008000, 0x00108020,
165         0x00100000, 0x00000020, 0x80100020, 0x80008020,
166         0x80000020, 0x80108020, 0x80108000, 0x80000000,
167         0x80008000, 0x00100000, 0x00000020, 0x80100020,
168         0x00108000, 0x00100020, 0x80008020, 0x00000000,
169         0x80000000, 0x00008000, 0x00108020, 0x80100000,
170         0x00100020, 0x80000020, 0x00000000, 0x00108000,
171         0x00008020, 0x80108000, 0x80100000, 0x00008020,
172         0x00000000, 0x00108020, 0x80100020, 0x00100000,
173         0x80008020, 0x80100000, 0x80108000, 0x00008000,
174         0x80100000, 0x80008000, 0x00000020, 0x80108020,
175         0x00108020, 0x00000020, 0x00008000, 0x80000000,
176         0x00008020, 0x80108000, 0x00100000, 0x80000020,
177         0x00100020, 0x80008020, 0x80000020, 0x00100020,
178         0x00108000, 0x00000000, 0x80008000, 0x00008020,
179         0x80000000, 0x80100020, 0x80108020, 0x00108000
180     };
181
182     static int[] SP3 = {
183         0x00000208, 0x08020200, 0x00000000, 0x08020008,
184         0x08000200, 0x00000000, 0x00020208, 0x08000200,
185         0x00020008, 0x08000008, 0x08000008, 0x00020000,
186         0x08020208, 0x00020008, 0x08020000, 0x00000208,
187         0x08000000, 0x00000008, 0x08020200, 0x00000200,
188         0x00020200, 0x08020000, 0x08020008, 0x00020208,
189         0x08000208, 0x00020200, 0x00020000, 0x08000208,
190         0x00000008, 0x08020208, 0x00000200, 0x08000000,
191         0x08020200, 0x08000000, 0x00020008, 0x00000208,
192         0x00020000, 0x08020200, 0x08000200, 0x00000000,
193         0x00000200, 0x00020008, 0x08020208, 0x08000200,
194         0x08000008, 0x00000200, 0x00000000, 0x08020008,
195         0x08000208, 0x00020000, 0x08000000, 0x08020208,
196         0x00000008, 0x00020208, 0x00020200, 0x08000008,
197         0x08020000, 0x08000208, 0x00000208, 0x08020000,
198         0x00020208, 0x00000008, 0x08020008, 0x00020200
199     };
200
201     static int[] SP4 = {
202         0x00802001, 0x00002081, 0x00002081, 0x00000080,
203         0x00802080, 0x00800081, 0x00800001, 0x00002001,
204         0x00000000, 0x00802000, 0x00802000, 0x00802081,
205         0x00000081, 0x00000000, 0x00800080, 0x00800001,
206         0x00000001, 0x00002000, 0x00800000, 0x00802001,
207         0x00000080, 0x00800000, 0x00002001, 0x00002080,
208         0x00800081, 0x00000001, 0x00002080, 0x00800080,
209         0x00002000, 0x00802080, 0x00802081, 0x00000081,
210         0x00800080, 0x00800001, 0x00802000, 0x00802081,
211         0x00000081, 0x00000000, 0x00000000, 0x00802000,
212         0x00002080, 0x00800080, 0x00800081, 0x00000001,
213         0x00802001, 0x00002081, 0x00002081, 0x00000080,
214         0x00802081, 0x00000081, 0x00000001, 0x00002000,
215         0x00800001, 0x00002001, 0x00802080, 0x00800081,
216         0x00002001, 0x00002080, 0x00800000, 0x00802001,
217         0x00000080, 0x00800000, 0x00002000, 0x00802080
218     };
219
220     static int[] SP5 = {
221         0x00000100, 0x02080100, 0x02080000, 0x42000100,
222         0x00080000, 0x00000100, 0x40000000, 0x02080000,
223         0x40080100, 0x00080000, 0x02000100, 0x40080100,
224         0x42000100, 0x42080000, 0x00080100, 0x40000000,
225         0x02000000, 0x40080000, 0x40080000, 0x00000000,
226         0x40000100, 0x42080100, 0x42080100, 0x02000100,
227         0x42080000, 0x40000100, 0x00000000, 0x42000000,
228         0x02080100, 0x02000000, 0x42000000, 0x00080100,
229         0x00080000, 0x42000100, 0x00000100, 0x02000000,
230         0x40000000, 0x02080000, 0x42000100, 0x40080100,
231         0x02000100, 0x40000000, 0x42080000, 0x02080100,
232         0x40080100, 0x00000100, 0x02000000, 0x42080000,
233         0x42080100, 0x00080100, 0x42000000, 0x42080100,
234         0x02080000, 0x00000000, 0x40080000, 0x42000000,
235         0x00080100, 0x02000100, 0x40000100, 0x00080000,
236         0x00000000, 0x40080000, 0x02080100, 0x40000100
237     };
238
239     static int[] SP6 = {
240         0x20000010, 0x20400000, 0x00004000, 0x20404010,
241         0x20400000, 0x00000010, 0x20404010, 0x00400000,
242         0x20004000, 0x00404010, 0x00400000, 0x20000010,
243         0x00400010, 0x20004000, 0x20000000, 0x00004010,
244         0x00000000, 0x00400010, 0x20004010, 0x00004000,
245         0x00404000, 0x20004010, 0x00000010, 0x20400010,
246         0x20400010, 0x00000000, 0x00404010, 0x20404000,
247         0x00004010, 0x00404000, 0x20404000, 0x20000000,
248         0x20004000, 0x00000010, 0x20400010, 0x00404000,
249         0x20404010, 0x00400000, 0x00004010, 0x20000010,
250         0x00400000, 0x20004000, 0x20000000, 0x00004010,
251         0x20000010, 0x20404010, 0x00404000, 0x20400000,
252         0x00404010, 0x20404000, 0x00000000, 0x20400010,
253         0x00000010, 0x00004000, 0x20400000, 0x00404010,
254         0x00004000, 0x00400010, 0x20004010, 0x00000000,
255         0x20404000, 0x20000000, 0x00400010, 0x20004010
256     };
257
258     static int[] SP7 = {
259         0x00200000, 0x04200002, 0x04000802, 0x00000000,
260         0x00000800, 0x04000802, 0x00200802, 0x04200800,
261         0x04200802, 0x00200000, 0x00000000, 0x04000002,
262         0x00000002, 0x04000000, 0x04200002, 0x00000802,
263         0x04000800, 0x00200802, 0x00200002, 0x04000800,
264         0x04000002, 0x04200000, 0x04200800, 0x00200002,
265         0x04200000, 0x00000800, 0x00000802, 0x04200802,
266         0x00200800, 0x00000002, 0x04000000, 0x00200800,
267         0x04000000, 0x00200800, 0x00200000, 0x04000802,
268         0x04000802, 0x04200002, 0x04200002, 0x00000002,
269         0x00200002, 0x04000000, 0x04000800, 0x00200000,
270         0x04200800, 0x00000802, 0x00200802, 0x04200800,
271         0x00000802, 0x04000002, 0x04200802, 0x04200000,
272         0x00200800, 0x00000000, 0x00000002, 0x04200802,
273         0x00000000, 0x00200802, 0x04200000, 0x00000800,
274         0x04000002, 0x04000800, 0x00000800, 0x00200002
275     };
276
277     static int[] SP8 = {
278         0x10001040, 0x00001000, 0x00040000, 0x10041040,
279         0x10000000, 0x10001040, 0x00000040, 0x10000000,
280         0x00040040, 0x10040000, 0x10041040, 0x00041000,
281         0x10041000, 0x00041040, 0x00001000, 0x00000040,
282         0x10040000, 0x10000040, 0x10001000, 0x00001040,
283         0x00041000, 0x00040040, 0x10040040, 0x10041000,
284         0x00001040, 0x00000000, 0x00000000, 0x10040040,
285         0x10000040, 0x10001000, 0x00041040, 0x00040000,
286         0x00041040, 0x00040000, 0x10041000, 0x00001000,
287         0x00000040, 0x10040040, 0x00001000, 0x00041040,
288         0x10001000, 0x00000040, 0x10000040, 0x10040000,
289         0x10040040, 0x10000000, 0x00040000, 0x10001040,
290         0x00000000, 0x10041040, 0x00040040, 0x10000040,
291         0x10040000, 0x10001000, 0x10001040, 0x00000000,
292         0x10041040, 0x00041000, 0x00041000, 0x00001040,
293         0x00001040, 0x00040040, 0x10000000, 0x10041000
294     };
295
296     /**
297      * generate an integer based working key based on our secret key
298      * and what we processing we are planning to do.
299      *
300      * Acknowledgements for this routine go to James Gillogly & Phil Karn.
301      *         (whoever, and wherever they are!).
302      */
303     protected int[] generateWorkingKey(
304         boolean encrypting,
305         byte[]  key)
306     {
307         int[]       newKey = new int[32];
308         boolean[]   pc1m = new boolean[56],
309                     pcr = new boolean[56];
310
311         for (int j = 0; j < 56; j++ )
312         {
313             int    l = pc1[j];
314
315             pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
316         }
317
318         for (int i = 0; i < 16; i++)
319         {
320             int    l, m, n;
321
322             if (encrypting)
323             {
324                 m = i << 1;
325             }
326             else
327             {
328                 m = (15 - i) << 1;
329             }
330
331             n = m + 1;
332             newKey[m] = newKey[n] = 0;
333
334             for (int j = 0; j < 28; j++)
335             {
336                 l = j + totrot[i];
337                 if ( l < 28 )
338                 {
339                     pcr[j] = pc1m[l];
340                 }
341                 else
342                 {
343                     pcr[j] = pc1m[l - 28];
344                 }
345             }
346
347             for (int j = 28; j < 56; j++)
348             {
349                 l = j + totrot[i];
350                 if (l < 56 )
351                 {
352                     pcr[j] = pc1m[l];
353                 }
354                 else
355                 {
356                     pcr[j] = pc1m[l - 28];
357                 }
358             }
359
360             for (int j = 0; j < 24; j++)
361             {
362                 if (pcr[pc2[j]])
363                 {
364                     newKey[m] |= bigbyte[j];
365                 }
366
367                 if (pcr[pc2[j + 24]])
368                 {
369                     newKey[n] |= bigbyte[j];
370                 }
371             }
372         }
373
374         //
375         // store the processed key
376         //
377         for (int i = 0; i != 32; i += 2)
378         {
379             int    i1, i2;
380
381             i1 = newKey[i];
382             i2 = newKey[i + 1];
383
384             newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
385                                    | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
386
387             newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
388                                    | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
389         }
390
391         return newKey;
392     }
393
394     /**
395      * the DES engine.
396      */
397     protected void desFunc(
398         int[]   wKey,
399         byte[]  in,
400         int     inOff,
401         byte[]  out,
402         int     outOff)
403     {
404         int     work, right, left;
405
406         left     = (in[inOff + 0] & 0xff) << 24;
407         left    |= (in[inOff + 1] & 0xff) << 16;
408         left    |= (in[inOff + 2] & 0xff) << 8;
409         left    |= (in[inOff + 3] & 0xff);
410
411         right     = (in[inOff + 4] & 0xff) << 24;
412         right    |= (in[inOff + 5] & 0xff) << 16;
413         right    |= (in[inOff + 6] & 0xff) << 8;
414         right    |= (in[inOff + 7] & 0xff);
415
416         work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
417         right ^= work;
418         left ^= (work << 4);
419         work = ((left >>> 16) ^ right) & 0x0000ffff;
420         right ^= work;
421         left ^= (work << 16);
422         work = ((right >>> 2) ^ left) & 0x33333333;
423         left ^= work;
424         right ^= (work << 2);
425         work = ((right >>> 8) ^ left) & 0x00ff00ff;
426         left ^= work;
427         right ^= (work << 8);
428         right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
429         work = (left ^ right) & 0xaaaaaaaa;
430         left ^= work;
431         right ^= work;
432         left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
433
434         for (int round = 0; round < 8; round++)
435         {
436             int     fval;
437
438             work  = (right << 28) | (right >>> 4);
439             work ^= wKey[round * 4 + 0];
440             fval  = SP7[ work      & 0x3f];
441             fval |= SP5[(work >>>  8) & 0x3f];
442             fval |= SP3[(work >>> 16) & 0x3f];
443             fval |= SP1[(work >>> 24) & 0x3f];
444             work  = right ^ wKey[round * 4 + 1];
445             fval |= SP8[ work      & 0x3f];
446             fval |= SP6[(work >>>  8) & 0x3f];
447             fval |= SP4[(work >>> 16) & 0x3f];
448             fval |= SP2[(work >>> 24) & 0x3f];
449             left ^= fval;
450             work  = (left << 28) | (left >>> 4);
451             work ^= wKey[round * 4 + 2];
452             fval  = SP7[ work      & 0x3f];
453             fval |= SP5[(work >>>  8) & 0x3f];
454             fval |= SP3[(work >>> 16) & 0x3f];
455             fval |= SP1[(work >>> 24) & 0x3f];
456             work  = left ^ wKey[round * 4 + 3];
457             fval |= SP8[ work      & 0x3f];
458             fval |= SP6[(work >>>  8) & 0x3f];
459             fval |= SP4[(work >>> 16) & 0x3f];
460             fval |= SP2[(work >>> 24) & 0x3f];
461             right ^= fval;
462         }
463
464         right = (right << 31) | (right >>> 1);
465         work = (left ^ right) & 0xaaaaaaaa;
466         left ^= work;
467         right ^= work;
468         left = (left << 31) | (left >>> 1);
469         work = ((left >>> 8) ^ right) & 0x00ff00ff;
470         right ^= work;
471         left ^= (work << 8);
472         work = ((left >>> 2) ^ right) & 0x33333333;
473         right ^= work;
474         left ^= (work << 2);
475         work = ((right >>> 16) ^ left) & 0x0000ffff;
476         left ^= work;
477         right ^= (work << 16);
478         work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
479         left ^= work;
480         right ^= (work << 4);
481
482         out[outOff + 0] = (byte)((right >>> 24) & 0xff);
483         out[outOff + 1] = (byte)((right >>> 16) & 0xff);
484         out[outOff + 2] = (byte)((right >>>  8) & 0xff);
485         out[outOff + 3] = (byte)( right         & 0xff);
486         out[outOff + 4] = (byte)((left >>> 24) & 0xff);
487         out[outOff + 5] = (byte)((left >>> 16) & 0xff);
488         out[outOff + 6] = (byte)((left >>>  8) & 0xff);
489         out[outOff + 7] = (byte)( left         & 0xff);
490     }
491 }