1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19 * @author Vera Y. Petrashkova
20 */
21
22package javax.crypto;
23
24import java.security.spec.AlgorithmParameterSpec;
25import java.security.InvalidAlgorithmParameterException;
26import java.security.InvalidKeyException;
27import java.security.Key;
28import java.security.NoSuchAlgorithmException;
29import java.security.SecureRandom;
30import java.security.AlgorithmParameters;
31import java.nio.ByteBuffer;
32
33import junit.framework.TestCase;
34
35
36/**
37 * Tests for <code>CipherSpi</code> class constructors and methods.
38 */
39
40public class CipherSpiTest extends TestCase {
41
42    /**
43     * Constructor for CipherSpiTests.
44     *
45     * @param arg0
46     */
47    public CipherSpiTest(String arg0) {
48        super(arg0);
49    }
50
51    /**
52     * Test for <code>CipherSpi</code> constructor
53     * Assertion: constructs CipherSpi
54     */
55    public void testCipherSpiTests01() throws IllegalBlockSizeException,
56            BadPaddingException, ShortBufferException {
57
58        CipherSpi cSpi = new myCipherSpi();
59        assertEquals("BlockSize is not 0", cSpi.engineGetBlockSize(), 0);
60        assertEquals("OutputSize is not 0", cSpi.engineGetOutputSize(1), 0);
61        byte[] bb = cSpi.engineGetIV();
62        assertEquals("Length of result byte array is not 0", bb.length, 0);
63        assertNull("Not null result", cSpi.engineGetParameters());
64        byte[] bb1 = new byte[10];
65        byte[] bb2 = new byte[10];
66        bb = cSpi.engineUpdate(bb1, 1, 2);
67        assertEquals("Incorrect result of engineUpdate(byte, int, int)",
68                bb.length, 2);
69        bb = cSpi.engineDoFinal(bb1, 1, 2);
70        assertEquals("Incorrect result of engineDoFinal(byte, int, int)", 2,
71                bb.length);
72        assertEquals(
73                "Incorrect result of engineUpdate(byte, int, int, byte, int)",
74                cSpi.engineUpdate(bb1, 1, 2, bb2, 7), 2);
75        assertEquals(
76                "Incorrect result of engineDoFinal(byte, int, int, byte, int)",
77                2, cSpi.engineDoFinal(bb1, 1, 2, bb2, 0));
78    }
79
80    /**
81     * Test for <code>engineGetKeySize(Key)</code> method
82     * Assertion: It throws UnsupportedOperationException if it is not overridden
83     */
84    public void testCipherSpi02() throws Exception {
85        CipherSpi cSpi = new myCipherSpi();
86        try {
87            cSpi.engineGetKeySize(null);
88            fail("UnsupportedOperationException must be thrown");
89        } catch (UnsupportedOperationException e) {
90        }
91    }
92
93    /**
94     * Test for <code>engineWrap(Key)</code> method
95     * Assertion: It throws UnsupportedOperationException if it is not overridden
96     */
97    public void testCipherSpi03() throws Exception {
98        CipherSpi cSpi = new myCipherSpi();
99        try {
100            cSpi.engineWrap(null);
101            fail("UnsupportedOperationException must be thrown");
102        } catch (UnsupportedOperationException e) {
103        }
104    }
105
106    /**
107     * Test for <code>engineUnwrap(byte[], String, int)</code> method
108     * Assertion: It throws UnsupportedOperationException if it is not overridden
109     */
110    public void testCipherSpi04() throws Exception {
111        CipherSpi cSpi = new myCipherSpi();
112        try {
113            cSpi.engineUnwrap(new byte[0], "", 0);
114            fail("UnsupportedOperationException must be thrown");
115        } catch (UnsupportedOperationException e) {
116        }
117    }
118
119    /**
120     * Test for <code>engineUpdate(ByteBuffer, ByteBuffer)</code> method
121     * Assertions:
122     * throws NullPointerException if one of these buffers is null;
123     * throws ShortBufferException is there is no space in output to hold result
124     */
125    public void testCipherSpi05() throws ShortBufferException {
126        CipherSpi cSpi = new myCipherSpi();
127        byte[] bb = { (byte) 0, (byte) 1, (byte) 2, (byte) 3, (byte) 4,
128                (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 9, (byte) 10 };
129        int pos = 5;
130        int len = bb.length;
131        ByteBuffer bbNull = null;
132        ByteBuffer bb1 = ByteBuffer.allocate(len);
133        bb1.put(bb);
134        bb1.position(0);
135        try {
136            cSpi.engineUpdate(bbNull, bb1);
137            fail("NullPointerException must be thrown");
138        } catch (NullPointerException e) {
139        }
140        try {
141            cSpi.engineUpdate(bb1, bbNull);
142            fail("NullPointerException must be thrown");
143        } catch (NullPointerException e) {
144        }
145        ByteBuffer bb2 = ByteBuffer.allocate(bb.length);
146        bb1.position(len);
147        assertEquals("Incorrect number of stored bytes", 0, cSpi.engineUpdate(
148                bb1, bb2));
149
150        bb1.position(0);
151        bb2.position(len - 2);
152        try {
153            cSpi.engineUpdate(bb1, bb2);
154            fail("ShortBufferException bust be thrown. Output buffer remaining: "
155                    .concat(Integer.toString(bb2.remaining())));
156        } catch (ShortBufferException e) {
157        }
158        bb1.position(10);
159        bb2.position(0);
160        assertTrue("Incorrect number of stored bytes", cSpi.engineUpdate(bb1,
161                bb2) > 0);
162        bb1.position(bb.length);
163        cSpi.engineUpdate(bb1, bb2);
164
165        bb1.position(pos);
166        bb2.position(0);
167        int res = cSpi.engineUpdate(bb1, bb2);
168        assertTrue("Incorrect result", res > 0);
169    }
170
171    /**
172     * Test for <code>engineDoFinal(ByteBuffer, ByteBuffer)</code> method
173     * Assertions:
174     * throws NullPointerException if one of these buffers is null;
175     * throws ShortBufferException is there is no space in output to hold result
176     */
177    public void testCipherSpi06() throws BadPaddingException,
178            ShortBufferException, IllegalBlockSizeException {
179        CipherSpi cSpi = new myCipherSpi();
180        int len = 10;
181        byte[] bbuf = new byte[len];
182        for (int i = 0; i < bbuf.length; i++) {
183            bbuf[i] = (byte) i;
184        }
185        ByteBuffer bb1 = ByteBuffer.wrap(bbuf);
186        ByteBuffer bbNull = null;
187        try {
188            cSpi.engineDoFinal(bbNull, bb1);
189            fail("NullPointerException must be thrown");
190        } catch (NullPointerException e) {
191        }
192        try {
193            cSpi.engineDoFinal(bb1, bbNull);
194            fail("NullPointerException must be thrown");
195        } catch (NullPointerException e) {
196        }
197        ByteBuffer bb2 = ByteBuffer.allocate(len);
198        bb1.position(bb1.limit());
199        assertEquals("Incorrect result", 0, cSpi.engineDoFinal(bb1, bb2));
200
201        bb1.position(0);
202        bb2.position(len - 2);
203        try {
204            cSpi.engineDoFinal(bb1, bb2);
205            fail("ShortBufferException must be thrown. Output buffer remaining: "
206                    .concat(Integer.toString(bb2.remaining())));
207        } catch (ShortBufferException e) {
208        }
209        int pos = 5;
210        bb1.position(pos);
211        bb2.position(0);
212        assertTrue("Incorrect result", cSpi.engineDoFinal(bb1, bb2) > 0);
213    }
214}
215
216/**
217 * Additional class for CipherGeneratorSpi constructor verification
218 */
219
220class myCipherSpi extends CipherSpi {
221    private byte[] initV;
222
223    private static byte[] resV = { (byte) 7, (byte) 6, (byte) 5, (byte) 4,
224            (byte) 3, (byte) 2, (byte) 1, (byte) 0 };
225
226    public myCipherSpi() {
227        this.initV = new byte[0];
228    }
229
230    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
231    }
232
233    protected void engineSetPadding(String padding)
234            throws NoSuchPaddingException {
235    }
236
237    protected int engineGetBlockSize() {
238        return 0;
239    }
240
241    protected int engineGetOutputSize(int inputLen) {
242        return 0;
243    }
244
245    protected byte[] engineGetIV() {
246        return new byte[0];
247    }
248
249    protected AlgorithmParameters engineGetParameters() {
250        return null;
251    }
252
253    protected void engineInit(int opmode, Key key, SecureRandom random)
254            throws InvalidKeyException {
255    }
256
257    protected void engineInit(int opmode, Key key,
258            AlgorithmParameterSpec params, SecureRandom random)
259            throws InvalidKeyException, InvalidAlgorithmParameterException {
260    }
261
262    protected void engineInit(int opmode, Key key, AlgorithmParameters params,
263            SecureRandom random) throws InvalidKeyException,
264            InvalidAlgorithmParameterException {
265    }
266
267    protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
268        if (initV.length < inputLen) {
269            initV = new byte[inputLen];
270        }
271        for (int i = 0; i < inputLen; i++) {
272            initV[i] = input[inputOffset + i];
273        }
274        return initV;
275    }
276
277    protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
278            byte[] output, int outputOffset) throws ShortBufferException {
279        byte[] res = engineUpdate(input, inputOffset, inputLen);
280        int t = res.length;
281        if ((output.length - outputOffset) < t) {
282            throw new ShortBufferException("Update");
283        }
284        for (int i = 0; i < t; i++) {
285            output[i + outputOffset] = initV[i];
286        }
287        return t;
288    }
289
290    protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
291            throws IllegalBlockSizeException, BadPaddingException {
292        if (resV.length > inputLen) {
293            byte[] bb = new byte[inputLen];
294            for (int i = 0; i < inputLen; i++) {
295                bb[i] = resV[i];
296            }
297            return bb;
298        }
299        return resV;
300    }
301
302    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
303            byte[] output, int outputOffset) throws ShortBufferException,
304            IllegalBlockSizeException, BadPaddingException {
305        byte[] res = engineDoFinal(input, inputOffset, inputLen);
306
307        int t = res.length;
308        if ((output.length - outputOffset) < t) {
309            throw new ShortBufferException("DoFinal");
310        }
311        for (int i = 0; i < t; i++) {
312            output[i + outputOffset] = res[i];
313        }
314        return t;
315    }
316
317
318    protected int engineUpdate(ByteBuffer input, ByteBuffer output)
319            throws ShortBufferException {
320        return super.engineUpdate(input, output);
321    }
322
323    protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
324            throws ShortBufferException, IllegalBlockSizeException,
325            BadPaddingException {
326        return super.engineDoFinal(input, output);
327    }
328}
329