1package org.bouncycastle.crypto.engines;
2
3import org.bouncycastle.crypto.CipherParameters;
4import org.bouncycastle.crypto.DataLengthException;
5import org.bouncycastle.crypto.OutputLengthException;
6import org.bouncycastle.crypto.params.KeyParameter;
7
8/**
9 * a class that provides a basic DESede (or Triple DES) engine.
10 */
11public class DESedeEngine
12    extends DESEngine
13{
14    protected static final int  BLOCK_SIZE = 8;
15
16    private int[]               workingKey1 = null;
17    private int[]               workingKey2 = null;
18    private int[]               workingKey3 = null;
19
20    private boolean             forEncryption;
21
22    /**
23     * standard constructor.
24     */
25    public DESedeEngine()
26    {
27    }
28
29    /**
30     * initialise a DESede cipher.
31     *
32     * @param encrypting whether or not we are for encryption.
33     * @param params the parameters required to set up the cipher.
34     * @exception IllegalArgumentException if the params argument is
35     * inappropriate.
36     */
37    public void init(
38        boolean           encrypting,
39        CipherParameters  params)
40    {
41        if (!(params instanceof KeyParameter))
42        {
43            throw new IllegalArgumentException("invalid parameter passed to DESede init - " + params.getClass().getName());
44        }
45
46        byte[] keyMaster = ((KeyParameter)params).getKey();
47
48        if (keyMaster.length != 24 && keyMaster.length != 16)
49        {
50            throw new IllegalArgumentException("key size must be 16 or 24 bytes.");
51        }
52
53        this.forEncryption = encrypting;
54
55        byte[] key1 = new byte[8];
56        System.arraycopy(keyMaster, 0, key1, 0, key1.length);
57        workingKey1 = generateWorkingKey(encrypting, key1);
58
59        byte[] key2 = new byte[8];
60        System.arraycopy(keyMaster, 8, key2, 0, key2.length);
61        workingKey2 = generateWorkingKey(!encrypting, key2);
62
63        if (keyMaster.length == 24)
64        {
65            byte[] key3 = new byte[8];
66            System.arraycopy(keyMaster, 16, key3, 0, key3.length);
67            workingKey3 = generateWorkingKey(encrypting, key3);
68        }
69        else    // 16 byte key
70        {
71            workingKey3 = workingKey1;
72        }
73    }
74
75    public String getAlgorithmName()
76    {
77        return "DESede";
78    }
79
80    public int getBlockSize()
81    {
82        return BLOCK_SIZE;
83    }
84
85    public int processBlock(
86        byte[] in,
87        int inOff,
88        byte[] out,
89        int outOff)
90    {
91        if (workingKey1 == null)
92        {
93            throw new IllegalStateException("DESede engine not initialised");
94        }
95
96        if ((inOff + BLOCK_SIZE) > in.length)
97        {
98            throw new DataLengthException("input buffer too short");
99        }
100
101        if ((outOff + BLOCK_SIZE) > out.length)
102        {
103            throw new OutputLengthException("output buffer too short");
104        }
105
106        byte[] temp = new byte[BLOCK_SIZE];
107
108        if (forEncryption)
109        {
110            desFunc(workingKey1, in, inOff, temp, 0);
111            desFunc(workingKey2, temp, 0, temp, 0);
112            desFunc(workingKey3, temp, 0, out, outOff);
113        }
114        else
115        {
116            desFunc(workingKey3, in, inOff, temp, 0);
117            desFunc(workingKey2, temp, 0, temp, 0);
118            desFunc(workingKey1, temp, 0, out, outOff);
119        }
120
121        return BLOCK_SIZE;
122    }
123
124    public void reset()
125    {
126    }
127}
128