Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/security/SecureRandom/ApiTest.java
41149 views
1
/*
2
* Copyright (c) 2016, 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 8141039
27
* @library /lib/testlibrary
28
* @summary This test do API coverage for SecureRandom. It covers most of
29
* supported operations along with possible positive and negative
30
* parameters for DRBG mechanism.
31
* @run main/othervm ApiTest Hash_DRBG
32
* @run main/othervm ApiTest HMAC_DRBG
33
* @run main/othervm ApiTest CTR_DRBG
34
* @run main/othervm ApiTest SHA1PRNG
35
* @run main/othervm ApiTest NATIVE
36
*/
37
import java.security.NoSuchAlgorithmException;
38
import java.security.SecureRandom;
39
import java.security.Security;
40
import java.security.SecureRandomParameters;
41
import java.security.DrbgParameters;
42
import java.security.DrbgParameters.Instantiation;
43
import java.security.DrbgParameters.Capability;
44
import javax.crypto.Cipher;
45
46
public class ApiTest {
47
48
private static final boolean SHOULD_PASS = true;
49
private static final long SEED = 1l;
50
private static final String INVALID_ALGO = "INVALID";
51
private static final String DRBG_CONFIG = "securerandom.drbg.config";
52
private static final String DRBG_CONFIG_VALUE
53
= Security.getProperty(DRBG_CONFIG);
54
55
public static void main(String[] args) throws Exception {
56
System.setProperty("java.security.egd", "file:/dev/urandom");
57
58
if (args == null || args.length < 1) {
59
throw new RuntimeException("No mechanism available to run test.");
60
}
61
String mech
62
= "NATIVE".equals(args[0]) ? supportedNativeAlgo() : args[0];
63
String[] algs = null;
64
boolean success = true;
65
66
try {
67
if (!isDRBG(mech)) {
68
SecureRandom random = SecureRandom.getInstance(mech);
69
verifyAPI(random, mech);
70
return;
71
} else if (mech.equals("CTR_DRBG")) {
72
algs = new String[]{"AES-128", "AES-192", "AES-256",
73
INVALID_ALGO};
74
} else if (mech.equals("Hash_DRBG") || mech.equals("HMAC_DRBG")) {
75
algs = new String[]{"SHA-224", "SHA-256", "SHA-512/224",
76
"SHA-512/256", "SHA-384", "SHA-512", INVALID_ALGO};
77
} else {
78
throw new RuntimeException(
79
String.format("Not a valid mechanism '%s'", mech));
80
}
81
runForEachMech(mech, algs);
82
} catch (Exception e) {
83
e.printStackTrace(System.out);
84
success = false;
85
}
86
87
if (!success) {
88
throw new RuntimeException("At least one test failed.");
89
}
90
}
91
92
/**
93
* Run the test for a DRBG mechanism with a possible set of parameter
94
* combination.
95
* @param mech DRBG mechanism name
96
* @param algs Algorithm supported by each mechanism
97
* @throws Exception
98
*/
99
private static void runForEachMech(String mech, String[] algs)
100
throws Exception {
101
for (String alg : algs) {
102
runForEachAlg(mech, alg);
103
}
104
}
105
106
private static void runForEachAlg(String mech, String alg)
107
throws Exception {
108
for (int strength : new int[]{-1, 0, 1, 223, 224,
109
192, 255, 256}) {
110
for (Capability cp : Capability.values()) {
111
for (byte[] pr : new byte[][]{null, new byte[]{},
112
"personal".getBytes()}) {
113
SecureRandomParameters param
114
= DrbgParameters.instantiation(strength, cp, pr);
115
runForEachParam(mech, alg, param);
116
}
117
}
118
}
119
}
120
121
private static void runForEachParam(String mech, String alg,
122
SecureRandomParameters param) throws Exception {
123
124
for (boolean df : new Boolean[]{true, false}) {
125
try {
126
Security.setProperty(DRBG_CONFIG, mech + "," + alg + ","
127
+ (df ? "use_df" : "no_df"));
128
System.out.printf("%nParameter for SecureRandom "
129
+ "mechanism: %s is (param:%s, algo:%s, df:%s)",
130
mech, param, alg, df);
131
SecureRandom sr = SecureRandom.getInstance("DRBG", param);
132
verifyAPI(sr, mech);
133
} catch (NoSuchAlgorithmException e) {
134
// Verify exception status for current test.
135
checkException(getDefaultAlg(mech, alg), param, e);
136
} finally {
137
Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE);
138
}
139
}
140
}
141
142
/**
143
* Returns the algorithm supported for input mechanism.
144
* @param mech Mechanism name
145
* @param alg Algorithm name
146
* @return Algorithm name
147
*/
148
private static String getDefaultAlg(String mech, String alg)
149
throws NoSuchAlgorithmException {
150
if (alg == null) {
151
switch (mech) {
152
case "Hash_DRBG":
153
case "HMAC_DRBG":
154
return "SHA-256";
155
case "CTR_DRBG":
156
return (Cipher.getMaxAllowedKeyLength("AES") < 256)
157
? "AES-128" : "AES-256";
158
default:
159
throw new RuntimeException("Mechanism not supported");
160
}
161
}
162
return alg;
163
}
164
165
/**
166
* Verify the exception type either it is expected to occur or not.
167
* @param alg Algorithm name
168
* @param param DRBG parameter
169
* @param e Exception to verify
170
* @throws NoSuchAlgorithmException
171
*/
172
private static void checkException(String alg, SecureRandomParameters param,
173
NoSuchAlgorithmException e) throws NoSuchAlgorithmException {
174
175
int strength = ((Instantiation) param).getStrength();
176
boolean error = true;
177
switch (alg) {
178
case INVALID_ALGO:
179
error = false;
180
break;
181
case "SHA-224":
182
case "SHA-512/224":
183
if (strength > 192) {
184
error = false;
185
}
186
break;
187
case "SHA-256":
188
case "SHA-512/256":
189
case "SHA-384":
190
case "SHA-512":
191
if (strength > 256) {
192
error = false;
193
}
194
break;
195
case "AES-128":
196
case "AES-192":
197
case "AES-256":
198
int algoStrength = Integer.parseInt(alg.substring("AES-".length()));
199
int maxAESStrength = Cipher.getMaxAllowedKeyLength("AES");
200
if (strength > algoStrength
201
|| algoStrength > maxAESStrength) {
202
error = false;
203
}
204
break;
205
}
206
if (error) {
207
throw new RuntimeException("Unknown :", e);
208
}
209
}
210
211
/**
212
* Find if the mechanism is a DRBG mechanism.
213
* @param mech Mechanism name
214
* @return True for DRBG mechanism else False
215
*/
216
private static boolean isDRBG(String mech) {
217
return mech.contains("_DRBG");
218
}
219
220
/**
221
* Find the name of supported native mechanism name for current platform.
222
*/
223
private static String supportedNativeAlgo() {
224
String nativeSr = "Windows-PRNG";
225
try {
226
SecureRandom.getInstance(nativeSr);
227
} catch (NoSuchAlgorithmException e) {
228
nativeSr = "NativePRNG";
229
}
230
return nativeSr;
231
}
232
233
/**
234
* Test a possible set of SecureRandom API for a SecureRandom instance.
235
* @param random SecureRandom instance
236
* @param mech Mechanism used to create SecureRandom instance
237
*/
238
private static void verifyAPI(SecureRandom random, String mech)
239
throws Exception {
240
241
System.out.printf("%nTest SecureRandom mechanism: %s for provider: %s",
242
mech, random.getProvider().getName());
243
byte[] output = new byte[2];
244
245
// Generate random number.
246
random.nextBytes(output);
247
248
// Seed the SecureRandom with a generated seed value of lesser size.
249
byte[] seed = random.generateSeed(1);
250
random.setSeed(seed);
251
random.nextBytes(output);
252
253
// Seed the SecureRandom with a fixed seed value.
254
random.setSeed(SEED);
255
random.nextBytes(output);
256
257
// Seed the SecureRandom with a larger seed value.
258
seed = random.generateSeed(128);
259
random.setSeed(seed);
260
random.nextBytes(output);
261
262
// Additional operation only supported for DRBG based SecureRandom.
263
// Execute the code block and expect to pass for DRBG. If it will fail
264
// then it should fail with specified exception type. Else the case
265
// will be considered as a test case failure.
266
matchExc(() -> {
267
random.reseed();
268
random.nextBytes(output);
269
},
270
isDRBG(mech),
271
UnsupportedOperationException.class,
272
String.format("PASS - Unsupported reseed() method for "
273
+ "SecureRandom Algorithm %s ", mech));
274
275
matchExc(() -> {
276
random.reseed(DrbgParameters.reseed(false, new byte[]{}));
277
random.nextBytes(output);
278
},
279
isDRBG(mech),
280
UnsupportedOperationException.class,
281
String.format("PASS - Unsupported reseed(param) method for "
282
+ "SecureRandom Algorithm %s ", mech));
283
284
matchExc(() -> {
285
random.reseed(DrbgParameters.reseed(true, new byte[]{}));
286
random.nextBytes(output);
287
},
288
isDRBG(mech),
289
!isSupportPR(mech, random) ? IllegalArgumentException.class
290
: UnsupportedOperationException.class,
291
String.format("PASS - Unsupported or illegal reseed(param) "
292
+ "method for SecureRandom Algorithm %s ", mech));
293
294
matchExc(() -> random.nextBytes(output,
295
DrbgParameters.nextBytes(-1, false, new byte[]{})),
296
isDRBG(mech),
297
UnsupportedOperationException.class,
298
String.format("PASS - Unsupported nextBytes(out, nextByteParam)"
299
+ " method for SecureRandom Algorithm %s ", mech));
300
301
matchExc(() -> random.nextBytes(output,
302
DrbgParameters.nextBytes(-1, true, new byte[]{})),
303
isDRBG(mech),
304
!isSupportPR(mech, random) ? IllegalArgumentException.class
305
: UnsupportedOperationException.class,
306
String.format("PASS - Unsupported or illegal "
307
+ "nextBytes(out, nextByteParam) method for "
308
+ "SecureRandom Algorithm %s ", mech));
309
310
matchExc(() -> {
311
random.reseed(null);
312
random.nextBytes(output);
313
},
314
!SHOULD_PASS,
315
IllegalArgumentException.class,
316
"PASS - Test is expected to fail when parameter for reseed() "
317
+ "is null");
318
319
matchExc(() -> random.nextBytes(output, null),
320
!SHOULD_PASS,
321
IllegalArgumentException.class,
322
"PASS - Test is expected to fail when parameter for nextBytes()"
323
+ " is null");
324
325
}
326
327
private static boolean isSupportPR(String mech, SecureRandom random) {
328
return (isDRBG(mech) && ((Instantiation) random.getParameters())
329
.getCapability()
330
.supportsPredictionResistance());
331
}
332
333
private interface RunnableCode {
334
335
void run() throws Exception;
336
}
337
338
/**
339
* Execute a given code block and verify, if the exception type is expected.
340
* @param r Code block to run
341
* @param ex Expected exception type
342
* @param shouldPass If the code execution expected to pass without failure
343
* @param msg Message to log in case of expected failure
344
*/
345
private static void matchExc(RunnableCode r, boolean shouldPass, Class ex,
346
String msg) {
347
try {
348
r.run();
349
if (!shouldPass) {
350
throw new RuntimeException("Excecution should fail here.");
351
}
352
} catch (Exception e) {
353
System.out.printf("%nOccured exception: %s - Expected exception: "
354
+ "%s : ", e.getClass(), ex.getCanonicalName());
355
if (ex.isAssignableFrom(e.getClass())) {
356
System.out.printf("%n%s : Expected Exception occured: %s : ",
357
e.getClass(), msg);
358
} else if (shouldPass) {
359
throw new RuntimeException(e);
360
} else {
361
System.out.printf("Ignore the following exception: %s%n",
362
e.getMessage());
363
}
364
}
365
}
366
}
367
368