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