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