1 /*
2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 4898461 6604496
27 * @summary basic test for symmetric ciphers with padding
28 * @author Valerie Peng
29 * @library ..
30 * @key randomness
31 * @modules jdk.crypto.cryptoki
32 * @run main/othervm TestSymmCiphers
33 * @run main/othervm TestSymmCiphers sm
34 */
35
36 import java.io.ByteArrayOutputStream;
37 import java.nio.ByteBuffer;
38 import java.security.AlgorithmParameters;
39 import java.security.NoSuchAlgorithmException;
40 import java.security.Provider;
41 import java.util.Random;
42 import javax.crypto.Cipher;
43 import javax.crypto.KeyGenerator;
44 import javax.crypto.SecretKey;
45
46 public class TestSymmCiphers extends PKCS11Test {
47
48 private static class CI { // class for holding Cipher Information
49
50 String transformation;
51 String keyAlgo;
52 int dataSize;
53
54 CI(String transformation, String keyAlgo, int dataSize) {
55 this.transformation = transformation;
56 this.keyAlgo = keyAlgo;
57 this.dataSize = dataSize;
58 }
59 }
60 private static final CI[] TEST_LIST = {
61 new CI("ARCFOUR", "ARCFOUR", 400),
62 new CI("RC4", "RC4", 401),
63 new CI("DES/CBC/NoPadding", "DES", 400),
64 new CI("DESede/CBC/NoPadding", "DESede", 160),
65 new CI("AES/CBC/NoPadding", "AES", 4800),
66 new CI("Blowfish/CBC/NoPadding", "Blowfish", 24),
67 new CI("DES/cbc/PKCS5Padding", "DES", 6401),
68 new CI("DESede/CBC/PKCS5Padding", "DESede", 402),
69 new CI("AES/CBC/PKCS5Padding", "AES", 30),
70 new CI("Blowfish/CBC/PKCS5Padding", "Blowfish", 19),
71 new CI("DES/ECB/NoPadding", "DES", 400),
72 new CI("DESede/ECB/NoPadding", "DESede", 160),
73 new CI("AES/ECB/NoPadding", "AES", 4800),
74 new CI("DES/ECB/PKCS5Padding", "DES", 32),
75 new CI("DES/ECB/PKCS5Padding", "DES", 6400),
76 new CI("DESede/ECB/PKCS5Padding", "DESede", 400),
77 new CI("AES/ECB/PKCS5Padding", "AES", 64),
78
79 new CI("DES", "DES", 6400),
80 new CI("DESede", "DESede", 408),
81 new CI("AES", "AES", 128),
82
83 new CI("AES/CTR/NoPadding", "AES", 3200)
84
85 };
86 private static StringBuffer debugBuf = new StringBuffer();
87
88 @Override
89 public void main(Provider p) throws Exception {
90 // NSS reports CKR_DEVICE_ERROR when the data passed to
91 // its EncryptUpdate/DecryptUpdate is not multiple of blocks
92 int firstBlkSize = 16;
93 boolean status = true;
94 Random random = new Random();
95 try {
96 for (int i = 0; i < TEST_LIST.length; i++) {
97 CI currTest = TEST_LIST[i];
98 System.out.println("===" + currTest.transformation + "===");
99 try {
100 KeyGenerator kg =
101 KeyGenerator.getInstance(currTest.keyAlgo, p);
102 SecretKey key = kg.generateKey();
103 Cipher c1 = Cipher.getInstance(currTest.transformation, p);
104 Cipher c2 = Cipher.getInstance(currTest.transformation,
105 "SunJCE");
106
107 byte[] plainTxt = new byte[currTest.dataSize];
108 random.nextBytes(plainTxt);
109 System.out.println("Testing inLen = " + plainTxt.length);
110
111 c2.init(Cipher.ENCRYPT_MODE, key);
112 AlgorithmParameters params = c2.getParameters();
113 byte[] answer = c2.doFinal(plainTxt);
114 System.out.println("Encryption tests: START");
115 test(c1, Cipher.ENCRYPT_MODE, key, params, firstBlkSize,
116 plainTxt, answer);
117 System.out.println("Encryption tests: DONE");
118 c2.init(Cipher.DECRYPT_MODE, key, params);
119 byte[] answer2 = c2.doFinal(answer);
120 System.out.println("Decryption tests: START");
121 test(c1, Cipher.DECRYPT_MODE, key, params, firstBlkSize,
122 answer, answer2);
123 System.out.println("Decryption tests: DONE");
124 } catch (NoSuchAlgorithmException nsae) {
125 System.out.println("Skipping unsupported algorithm: " +
126 nsae);
127 }
128 }
129 } catch (Exception ex) {
130 // print out debug info when exception is encountered
131 if (debugBuf != null) {
132 System.out.println(debugBuf.toString());
133 debugBuf = new StringBuffer();
134 }
135 throw ex;
136 }
137 }
138
139 private static void test(Cipher cipher, int mode, SecretKey key,
140 AlgorithmParameters params, int firstBlkSize,
141 byte[] in, byte[] answer) throws Exception {
142 // test setup
143 long startTime, endTime;
144 cipher.init(mode, key, params);
145 int outLen = cipher.getOutputSize(in.length);
146 //debugOut("Estimated output size = " + outLen + "\n");
147
148 // test data preparation
149 ByteBuffer inBuf = ByteBuffer.allocate(in.length);
150 inBuf.put(in);
151 inBuf.position(0);
152 ByteBuffer inDirectBuf = ByteBuffer.allocateDirect(in.length);
153 inDirectBuf.put(in);
154 inDirectBuf.position(0);
155 ByteBuffer outBuf = ByteBuffer.allocate(outLen);
156 ByteBuffer outDirectBuf = ByteBuffer.allocateDirect(outLen);
157
158 // test#1: byte[] in + byte[] out
159 //debugOut("Test#1:\n");
160
161 ByteArrayOutputStream baos = new ByteArrayOutputStream();
162
163 startTime = System.nanoTime();
164 byte[] temp = cipher.update(in, 0, firstBlkSize);
165 if (temp != null && temp.length > 0) {
166 baos.write(temp, 0, temp.length);
167 }
168 temp = cipher.doFinal(in, firstBlkSize, in.length - firstBlkSize);
169 if (temp != null && temp.length > 0) {
170 baos.write(temp, 0, temp.length);
171 }
172 byte[] testOut1 = baos.toByteArray();
173 endTime = System.nanoTime();
174 perfOut("stream InBuf + stream OutBuf: " +
175 (endTime - startTime));
176 match(testOut1, answer);
177
178 // test#2: Non-direct Buffer in + non-direct Buffer out
179 //debugOut("Test#2:\n");
180 //debugOut("inputBuf: " + inBuf + "\n");
181 //debugOut("outputBuf: " + outBuf + "\n");
182
183 startTime = System.nanoTime();
184 cipher.update(inBuf, outBuf);
185 cipher.doFinal(inBuf, outBuf);
186 endTime = System.nanoTime();
187 perfOut("non-direct InBuf + non-direct OutBuf: " +
188 (endTime - startTime));
189 match(outBuf, answer);
190
191 // test#3: Direct Buffer in + direc Buffer out
192 //debugOut("Test#3:\n");
193 //debugOut("(pre) inputBuf: " + inDirectBuf + "\n");
194 //debugOut("(pre) outputBuf: " + outDirectBuf + "\n");
195
196 startTime = System.nanoTime();
197 cipher.update(inDirectBuf, outDirectBuf);
198 cipher.doFinal(inDirectBuf, outDirectBuf);
199 endTime = System.nanoTime();
200 perfOut("direct InBuf + direct OutBuf: " +
201 (endTime - startTime));
202
203 //debugOut("(post) inputBuf: " + inDirectBuf + "\n");
204 //debugOut("(post) outputBuf: " + outDirectBuf + "\n");
205 match(outDirectBuf, answer);
206
207 // test#4: Direct Buffer in + non-direct Buffer out
208 //debugOut("Test#4:\n");
209 inDirectBuf.position(0);
210 outBuf.position(0);
211 //debugOut("inputBuf: " + inDirectBuf + "\n");
212 //debugOut("outputBuf: " + outBuf + "\n");
213
214 startTime = System.nanoTime();
215 cipher.update(inDirectBuf, outBuf);
216 cipher.doFinal(inDirectBuf, outBuf);
217 endTime = System.nanoTime();
218 perfOut("direct InBuf + non-direct OutBuf: " +
219 (endTime - startTime));
220 match(outBuf, answer);
221
222 // test#5: Non-direct Buffer in + direct Buffer out
223 //debugOut("Test#5:\n");
224 inBuf.position(0);
225 outDirectBuf.position(0);
226
227 //debugOut("(pre) inputBuf: " + inBuf + "\n");
228 //debugOut("(pre) outputBuf: " + outDirectBuf + "\n");
229
230 startTime = System.nanoTime();
231 cipher.update(inBuf, outDirectBuf);
232 cipher.doFinal(inBuf, outDirectBuf);
233 endTime = System.nanoTime();
234 perfOut("non-direct InBuf + direct OutBuf: " +
235 (endTime - startTime));
236
237 //debugOut("(post) inputBuf: " + inBuf + "\n");
238 //debugOut("(post) outputBuf: " + outDirectBuf + "\n");
239 match(outDirectBuf, answer);
240
241 debugBuf = null;
242 }
243
244 private static void perfOut(String msg) {
245 if (debugBuf != null) {
246 debugBuf.append("PERF>" + msg);
247 }
248 }
249
250 private static void debugOut(String msg) {
251 if (debugBuf != null) {
252 debugBuf.append(msg);
253 }
254 }
255
256 private static void match(byte[] b1, byte[] b2) throws Exception {
257 if (b1.length != b2.length) {
258 debugOut("got len : " + b1.length + "\n");
259 debugOut("expect len: " + b2.length + "\n");
260 throw new Exception("mismatch - different length! got: " + b1.length + ", expect: " + b2.length + "\n");
261 } else {
262 for (int i = 0; i < b1.length; i++) {
263 if (b1[i] != b2[i]) {
264 debugOut("got : " + toString(b1) + "\n");
265 debugOut("expect: " + toString(b2) + "\n");
266 throw new Exception("mismatch");
267 }
268 }
269 }
270 }
271
272 private static void match(ByteBuffer bb, byte[] answer) throws Exception {
273 byte[] bbTemp = new byte[bb.position()];
274 bb.position(0);
275 bb.get(bbTemp, 0, bbTemp.length);
276 match(bbTemp, answer);
277 }
278
279 public static void main(String[] args) throws Exception {
280 main(new TestSymmCiphers(), args);
281 }
282 }