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