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* @version $Revision$
21*/
22
23package org.apache.harmony.crypto.tests.javax.crypto;
24
25import java.security.spec.AlgorithmParameterSpec;
26import java.security.InvalidAlgorithmParameterException;
27import java.security.InvalidKeyException;
28import java.security.Key;
29import java.security.NoSuchAlgorithmException;
30import java.security.SecureRandom;
31import java.security.AlgorithmParameters;
32import javax.crypto.BadPaddingException;
33import javax.crypto.IllegalBlockSizeException;
34import javax.crypto.NoSuchPaddingException;
35import javax.crypto.ShortBufferException;
36import javax.crypto.CipherSpi;
37import java.nio.ByteBuffer;
38
39import junit.framework.TestCase;
40
41
42/**
43 * Tests for <code>CipherSpi</code> class constructors and methods.
44 *
45 */
46public class CipherSpiTest extends TestCase {
47    class Mock_CipherSpi extends myCipherSpi {
48
49        @Override
50        protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
51                throws IllegalBlockSizeException, BadPaddingException {
52            return super.engineDoFinal(input, inputOffset, inputLen);
53        }
54
55        @Override
56        protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
57                int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
58                BadPaddingException {
59            return super.engineDoFinal(input, inputOffset, inputLen, output, outputOffset);
60        }
61
62        @Override
63        protected int engineGetBlockSize() {
64            return super.engineGetBlockSize();
65        }
66
67        @Override
68        protected byte[] engineGetIV() {
69            return super.engineGetIV();
70        }
71
72        @Override
73        protected int engineGetOutputSize(int inputLen) {
74            return super.engineGetOutputSize(inputLen);
75        }
76
77        @Override
78        protected AlgorithmParameters engineGetParameters() {
79            return super.engineGetParameters();
80        }
81
82        @Override
83        protected void engineInit(int opmode, Key key, SecureRandom random)
84                throws InvalidKeyException {
85            super.engineInit(opmode, key, random);
86        }
87
88        @Override
89        protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
90                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
91            super.engineInit(opmode, key, params, random);
92        }
93
94        @Override
95        protected void engineInit(int opmode, Key key, AlgorithmParameters params,
96                SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
97            super.engineInit(opmode, key, params, random);
98        }
99
100        @Override
101        protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
102            super.engineSetMode(mode);
103        }
104
105        @Override
106        protected void engineSetPadding(String padding) throws NoSuchPaddingException {
107            super.engineSetPadding(padding);
108        }
109
110        @Override
111        protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
112            return super.engineUpdate(input, inputOffset, inputLen);
113        }
114
115        @Override
116        protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
117                int outputOffset) throws ShortBufferException {
118            return super.engineUpdate(input, inputOffset, inputLen, output, outputOffset);
119        }
120
121        @Override
122        protected int engineGetKeySize(Key key) throws InvalidKeyException {
123            return super.engineGetKeySize(key);
124        }
125
126        @Override
127        protected byte[] engineWrap(Key key) throws InvalidKeyException, IllegalBlockSizeException {
128            return super.engineWrap(key);
129        }
130
131        @Override
132        protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType)
133                throws InvalidKeyException, NoSuchAlgorithmException {
134            return super.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
135        }
136    }
137
138    /**
139     * Test for <code>CipherSpi</code> constructor
140     * Assertion: constructs CipherSpi
141     */
142    public void testCipherSpiTests01() throws IllegalBlockSizeException,
143            BadPaddingException, ShortBufferException {
144
145        Mock_CipherSpi cSpi = new Mock_CipherSpi();
146        assertEquals("BlockSize is not 0", cSpi.engineGetBlockSize(), 0);
147        assertEquals("OutputSize is not 0", cSpi.engineGetOutputSize(1), 0);
148        byte[] bb = cSpi.engineGetIV();
149        assertEquals("Length of result byte array is not 0", bb.length, 0);
150        assertNull("Not null result", cSpi.engineGetParameters());
151        byte[] bb1 = new byte[10];
152        byte[] bb2 = new byte[10];
153        bb = cSpi.engineUpdate(bb1, 1, 2);
154        assertEquals("Incorrect result of engineUpdate(byte, int, int)",
155                bb.length, 2);
156        bb = cSpi.engineDoFinal(bb1, 1, 2);
157        assertEquals("Incorrect result of engineDoFinal(byte, int, int)", 2,
158                bb.length);
159        assertEquals(
160                "Incorrect result of engineUpdate(byte, int, int, byte, int)",
161                cSpi.engineUpdate(bb1, 1, 2, bb2, 7), 2);
162        assertEquals(
163                "Incorrect result of engineDoFinal(byte, int, int, byte, int)",
164                2, cSpi.engineDoFinal(bb1, 1, 2, bb2, 0));
165    }
166
167    /**
168     * Test for <code>engineGetKeySize(Key)</code> method
169     * Assertion: It throws UnsupportedOperationException if it is not overridden
170     */
171    public void testCipherSpi02() throws Exception {
172        Mock_CipherSpi cSpi = new Mock_CipherSpi();
173        try {
174            cSpi.engineGetKeySize(null);
175            fail("UnsupportedOperationException must be thrown");
176        } catch (UnsupportedOperationException e) {
177        }
178    }
179
180    /**
181     * Test for <code>engineWrap(Key)</code> method
182     * Assertion: It throws UnsupportedOperationException if it is not overridden
183     */
184    public void testCipherSpi03() throws Exception {
185        Mock_CipherSpi cSpi = new Mock_CipherSpi();
186        try {
187            cSpi.engineWrap(null);
188            fail("UnsupportedOperationException must be thrown");
189        } catch (UnsupportedOperationException e) {
190        }
191    }
192
193    /**
194     * Test for <code>engineUnwrap(byte[], String, int)</code> method
195     * Assertion: It throws UnsupportedOperationException if it is not overridden
196     */
197    public void testCipherSpi04() throws Exception {
198        Mock_CipherSpi cSpi = new Mock_CipherSpi();
199        try {
200            cSpi.engineUnwrap(new byte[0], "", 0);
201            fail("UnsupportedOperationException must be thrown");
202        } catch (UnsupportedOperationException e) {
203        }
204    }
205
206    /**
207     * Test for <code>engineUpdate(ByteBuffer, ByteBuffer)</code> method
208     * Assertions:
209     * throws NullPointerException if one of these buffers is null;
210     * throws ShortBufferException is there is no space in output to hold result
211     */
212    public void testCipherSpi05() throws ShortBufferException {
213        Mock_CipherSpi cSpi = new Mock_CipherSpi();
214        byte[] bb = { (byte) 0, (byte) 1, (byte) 2, (byte) 3, (byte) 4,
215                (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 9, (byte) 10 };
216        int pos = 5;
217        int len = bb.length;
218        ByteBuffer bbNull = null;
219        ByteBuffer bb1 = ByteBuffer.allocate(len);
220        bb1.put(bb);
221        bb1.position(0);
222        try {
223            cSpi.engineUpdate(bbNull, bb1);
224            fail("NullPointerException must be thrown");
225        } catch (NullPointerException e) {
226        }
227        try {
228            cSpi.engineUpdate(bb1, bbNull);
229            fail("NullPointerException must be thrown");
230        } catch (NullPointerException e) {
231        }
232        ByteBuffer bb2 = ByteBuffer.allocate(bb.length);
233        bb1.position(len);
234        assertEquals("Incorrect number of stored bytes", 0, cSpi.engineUpdate(
235                bb1, bb2));
236
237        bb1.position(0);
238        bb2.position(len - 2);
239        try {
240            cSpi.engineUpdate(bb1, bb2);
241            fail("ShortBufferException bust be thrown. Output buffer remaining: "
242                    .concat(Integer.toString(bb2.remaining())));
243        } catch (ShortBufferException e) {
244        }
245        bb1.position(10);
246        bb2.position(0);
247        assertTrue("Incorrect number of stored bytes", cSpi.engineUpdate(bb1,
248                bb2) > 0);
249        bb1.position(bb.length);
250        cSpi.engineUpdate(bb1, bb2);
251
252        bb1.position(pos);
253        bb2.position(0);
254        int res = cSpi.engineUpdate(bb1, bb2);
255        assertTrue("Incorrect result", res > 0);
256    }
257
258    /**
259     * Test for <code>engineDoFinal(ByteBuffer, ByteBuffer)</code> method
260     * Assertions:
261     * throws NullPointerException if one of these buffers is null;
262     * throws ShortBufferException is there is no space in output to hold result
263     */
264    public void testCipherSpi06() throws BadPaddingException,
265            ShortBufferException, IllegalBlockSizeException {
266        Mock_CipherSpi cSpi = new Mock_CipherSpi();
267        int len = 10;
268        byte[] bbuf = new byte[len];
269        for (int i = 0; i < bbuf.length; i++) {
270            bbuf[i] = (byte) i;
271        }
272        ByteBuffer bb1 = ByteBuffer.wrap(bbuf);
273        ByteBuffer bbNull = null;
274        try {
275            cSpi.engineDoFinal(bbNull, bb1);
276            fail("NullPointerException must be thrown");
277        } catch (NullPointerException e) {
278        }
279        try {
280            cSpi.engineDoFinal(bb1, bbNull);
281            fail("NullPointerException must be thrown");
282        } catch (NullPointerException e) {
283        }
284        ByteBuffer bb2 = ByteBuffer.allocate(len);
285        bb1.position(bb1.limit());
286        assertEquals("Incorrect result", 0, cSpi.engineDoFinal(bb1, bb2));
287
288        bb1.position(0);
289        bb2.position(len - 2);
290        try {
291            cSpi.engineDoFinal(bb1, bb2);
292            fail("ShortBufferException must be thrown. Output buffer remaining: "
293                    .concat(Integer.toString(bb2.remaining())));
294        } catch (ShortBufferException e) {
295        }
296        int pos = 5;
297        bb1.position(pos);
298        bb2.position(0);
299        assertTrue("Incorrect result", cSpi.engineDoFinal(bb1, bb2) > 0);
300    }
301}
302/**
303 *
304 * Additional class for CipherGeneratorSpi constructor verification
305 */
306
307class myCipherSpi extends CipherSpi {
308    private byte[] initV;
309
310    private static byte[] resV = { (byte) 7, (byte) 6, (byte) 5, (byte) 4,
311            (byte) 3, (byte) 2, (byte) 1, (byte) 0 };
312
313    public myCipherSpi() {
314        this.initV = new byte[0];
315    }
316
317    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
318    }
319
320    protected void engineSetPadding(String padding)
321            throws NoSuchPaddingException {
322    }
323
324    protected int engineGetBlockSize() {
325        return 0;
326    }
327
328    protected int engineGetOutputSize(int inputLen) {
329        return 0;
330    }
331
332    protected byte[] engineGetIV() {
333        return new byte[0];
334    }
335
336    protected AlgorithmParameters engineGetParameters() {
337        return null;
338    }
339
340    protected void engineInit(int opmode, Key key, SecureRandom random)
341            throws InvalidKeyException {
342    }
343
344    protected void engineInit(int opmode, Key key,
345            AlgorithmParameterSpec params, SecureRandom random)
346            throws InvalidKeyException, InvalidAlgorithmParameterException {
347    }
348
349    protected void engineInit(int opmode, Key key, AlgorithmParameters params,
350            SecureRandom random) throws InvalidKeyException,
351            InvalidAlgorithmParameterException {
352    }
353
354    protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
355        if (initV.length < inputLen) {
356            initV = new byte[inputLen];
357        }
358        for (int i = 0; i < inputLen; i++) {
359            initV[i] = input[inputOffset + i];
360        }
361        return initV;
362    }
363
364    protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
365            byte[] output, int outputOffset) throws ShortBufferException {
366        byte []res = engineUpdate(input, inputOffset, inputLen);
367        int t = res.length;
368        if ((output.length - outputOffset) < t) {
369            throw new ShortBufferException("Update");
370        }
371        for (int i = 0; i < t; i++) {
372            output[i + outputOffset] = initV[i];
373        }
374        return t;
375    }
376
377    protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
378            throws IllegalBlockSizeException, BadPaddingException {
379        if (resV.length > inputLen) {
380            byte[] bb = new byte[inputLen];
381            for (int i = 0; i < inputLen; i++) {
382                bb[i] = resV[i];
383            }
384            return bb;
385        }
386        return resV;
387    }
388
389    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
390            byte[] output, int outputOffset) throws ShortBufferException,
391            IllegalBlockSizeException, BadPaddingException {
392        byte[] res = engineDoFinal(input, inputOffset, inputLen);
393
394        int t = res.length;
395        if ((output.length - outputOffset) < t) {
396            throw new ShortBufferException("DoFinal");
397        }
398        for (int i = 0; i < t; i++) {
399            output[i + outputOffset] = res[i];
400        }
401        return t;
402    }
403
404
405    protected int engineUpdate(ByteBuffer input, ByteBuffer output)
406    throws ShortBufferException {
407        return super.engineUpdate(input, output);
408    }
409    protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
410    throws ShortBufferException, IllegalBlockSizeException,
411    BadPaddingException {
412        return super.engineDoFinal(input, output);
413    }
414}
415