289
|
1 |
/*
|
|
2 |
* Copyright 2008 Sun Microsystems, Inc. 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 modi
|
|
6 |
fy it
|
|
7 |
* under the terms of the GNU General Public License version 2 onl
|
|
8 |
y, as
|
|
9 |
* published by the Free Software Foundation.
|
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, bu
|
|
12 |
t WITHOUT
|
|
13 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABIL
|
|
14 |
ITY or
|
|
15 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public L
|
|
16 |
icense
|
|
17 |
* version 2 for more details (a copy is included in the LICENSE f
|
|
18 |
ile that
|
|
19 |
* accompanied this code).
|
|
20 |
*
|
|
21 |
* You should have received a copy of the GNU General Public Licen
|
|
22 |
se version
|
|
23 |
* 2 along with this work; if not, write to the Free Software Foun
|
|
24 |
dation,
|
|
25 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
26 |
*
|
|
27 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, San
|
|
28 |
ta Clara,
|
|
29 |
* CA 95054 USA or visit www.sun.com if you need additional inform
|
|
30 |
ation or
|
|
31 |
* have any questions.
|
|
32 |
*/
|
|
33 |
|
|
34 |
/**
|
|
35 |
* @test %I% %E%
|
|
36 |
* @bug 4898461
|
|
37 |
* @summary basic test for symmetric ciphers with padding
|
|
38 |
* @author Valerie Peng
|
|
39 |
* @library ..
|
|
40 |
*/
|
|
41 |
import java.io.*;
|
|
42 |
import java.nio.*;
|
|
43 |
import java.util.*;
|
|
44 |
|
|
45 |
import java.security.*;
|
|
46 |
import java.security.spec.AlgorithmParameterSpec;
|
|
47 |
|
|
48 |
import javax.crypto.*;
|
|
49 |
import javax.crypto.spec.IvParameterSpec;
|
|
50 |
|
|
51 |
public class TestSymmCiphers extends PKCS11Test {
|
|
52 |
|
|
53 |
private static class CI { // class for holding Cipher Information
|
|
54 |
|
|
55 |
String transformation;
|
|
56 |
String keyAlgo;
|
|
57 |
int dataSize;
|
|
58 |
|
|
59 |
CI(String transformation, String keyAlgo, int dataSize) {
|
|
60 |
this.transformation = transformation;
|
|
61 |
this.keyAlgo = keyAlgo;
|
|
62 |
this.dataSize = dataSize;
|
|
63 |
}
|
|
64 |
}
|
|
65 |
private static final CI[] TEST_LIST = {
|
|
66 |
new CI("ARCFOUR", "ARCFOUR", 400),
|
|
67 |
new CI("RC4", "RC4", 401),
|
|
68 |
new CI("DES/CBC/NoPadding", "DES", 400),
|
|
69 |
new CI("DESede/CBC/NoPadding", "DESede", 160),
|
|
70 |
new CI("AES/CBC/NoPadding", "AES", 4800),
|
|
71 |
new CI("Blowfish/CBC/NoPadding", "Blowfish", 24),
|
|
72 |
new CI("DES/cbc/PKCS5Padding", "DES", 6401),
|
|
73 |
new CI("DESede/CBC/PKCS5Padding", "DESede", 402),
|
|
74 |
new CI("AES/CBC/PKCS5Padding", "AES", 30),
|
|
75 |
new CI("Blowfish/CBC/PKCS5Padding", "Blowfish", 19),
|
|
76 |
new CI("DES/ECB/NoPadding", "DES", 400),
|
|
77 |
new CI("DESede/ECB/NoPadding", "DESede", 160),
|
|
78 |
new CI("AES/ECB/NoPadding", "AES", 4800),
|
|
79 |
new CI("DES/ECB/PKCS5Padding", "DES", 32),
|
|
80 |
new CI("DES/ECB/PKCS5Padding", "DES", 6400),
|
|
81 |
new CI("DESede/ECB/PKCS5Padding", "DESede", 400),
|
|
82 |
new CI("AES/ECB/PKCS5Padding", "AES", 64),
|
|
83 |
new CI("DES", "DES", 6400),
|
|
84 |
new CI("DESede", "DESede", 408),
|
|
85 |
new CI("AES", "AES", 128)
|
|
86 |
};
|
|
87 |
private static StringBuffer debugBuf = new StringBuffer();
|
|
88 |
|
|
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());
|
|
281 |
}
|
|
282 |
}
|