|
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 SecureRandom supports multiple getInstance method including |
|
29 * getInstanceStrong() method. This test verifies a set of possible |
|
30 * cases for getInstance with different SecureRandom mechanism |
|
31 * supported in Java. |
|
32 * @run main GetInstanceTest |
|
33 */ |
|
34 import java.security.NoSuchAlgorithmException; |
|
35 import java.security.NoSuchProviderException; |
|
36 import java.security.SecureRandom; |
|
37 import java.security.SecureRandomParameters; |
|
38 import java.security.DrbgParameters; |
|
39 |
|
40 import static java.security.DrbgParameters.Capability.*; |
|
41 |
|
42 import java.security.Security; |
|
43 import java.util.Arrays; |
|
44 |
|
45 import jdk.testlibrary.Asserts; |
|
46 |
|
47 public class GetInstanceTest { |
|
48 |
|
49 private static final boolean PASS = true; |
|
50 private static final String INVALID_ALGO = "INVALID"; |
|
51 private static final String SUN_PROVIDER = "SUN"; |
|
52 private static final String INVALID_PROVIDER = "INVALID"; |
|
53 private static final String STRONG_ALG_SEC_PROP |
|
54 = "securerandom.strongAlgorithms"; |
|
55 private static final String DRBG_CONFIG = "securerandom.drbg.config"; |
|
56 private static final String DRBG_CONFIG_VALUE |
|
57 = Security.getProperty(DRBG_CONFIG); |
|
58 |
|
59 public static void main(String[] args) throws Exception { |
|
60 |
|
61 boolean success = true; |
|
62 // Only accepted failure is NoSuchAlgorithmException. |
|
63 // For any other failure the test case will fail here. |
|
64 SecureRandom sr = matchExc(() -> SecureRandom.getInstanceStrong(), |
|
65 PASS, NoSuchAlgorithmException.class, |
|
66 "PASS - Undefined security Property " |
|
67 + "'securerandom.strongAlgorithms'"); |
|
68 System.out.format("Current platform supports mechanism: '%s' through " |
|
69 + "provider: '%s' for the method getInstanceStrong().", |
|
70 sr.getAlgorithm(), sr.getProvider().getName()); |
|
71 |
|
72 // DRBG name should appear with "securerandom.strongAlgorithms" |
|
73 // security property. |
|
74 String origDRBGConfig = Security.getProperty(STRONG_ALG_SEC_PROP); |
|
75 if (!origDRBGConfig.contains("DRBG")) { |
|
76 throw new RuntimeException("DRBG is not associated with default " |
|
77 + "strong algorithm through security Property: " |
|
78 + "'securerandom.strongAlgorithms'."); |
|
79 } |
|
80 Security.setProperty(STRONG_ALG_SEC_PROP, "DRBG:SUN"); |
|
81 sr = matchExc(() -> SecureRandom.getInstanceStrong(), |
|
82 PASS, NoSuchAlgorithmException.class, |
|
83 "PASS - Undefined security Property " |
|
84 + "'securerandom.strongAlgorithms'"); |
|
85 checkAttributes(sr, "DRBG"); |
|
86 Security.setProperty(STRONG_ALG_SEC_PROP, origDRBGConfig); |
|
87 |
|
88 for (String mech : new String[]{ |
|
89 "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG", INVALID_ALGO,}) { |
|
90 System.out.printf("%nTest SecureRandom mechanism: '%s'", mech); |
|
91 try { |
|
92 if (isDRBG(mech)) { |
|
93 Security.setProperty(DRBG_CONFIG, mech); |
|
94 } |
|
95 verifyInstance(mech); |
|
96 } catch (Exception e) { |
|
97 e.printStackTrace(System.out); |
|
98 success = false; |
|
99 } finally { |
|
100 Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); |
|
101 } |
|
102 } |
|
103 if (!success) { |
|
104 throw new RuntimeException("At least one test failed."); |
|
105 } |
|
106 } |
|
107 |
|
108 private static void verifyInstance(String mech) throws Exception { |
|
109 |
|
110 String srAlgo = isDRBG(mech) ? "DRBG" : mech; |
|
111 |
|
112 // Test for getInstance(algorithm) method. |
|
113 // It should pass for all case other than invalid algorithm name. |
|
114 // If it fails then the expected exception type should be |
|
115 // NoSuchAlgorithmException. Any other Exception type occured will be |
|
116 // treated as failure. |
|
117 checkAttributes( |
|
118 matchExc(() -> SecureRandom.getInstance(srAlgo), !(nsa(mech)), |
|
119 NoSuchAlgorithmException.class, |
|
120 String.format("PASS - It is expected to fail for" |
|
121 + " getInstance(algorithm) when algorithm: '%s'" |
|
122 + " is null or invalid.", mech)), mech); |
|
123 // Test for getInstance(algorithm, provider) method. |
|
124 checkAttributes( |
|
125 matchExc(() -> SecureRandom.getInstance(srAlgo, |
|
126 Security.getProvider(SUN_PROVIDER)), |
|
127 !(nsa(mech)), |
|
128 NoSuchAlgorithmException.class, |
|
129 String.format("PASS - It is expected to fail for" |
|
130 + " getInstance(algorithm, provider) when" |
|
131 + " algorithm:'%s' is null or invalid.", mech)), |
|
132 mech); |
|
133 // Test for getInstance(algorithm, providerName) method. |
|
134 checkAttributes( |
|
135 matchExc(() -> SecureRandom.getInstance(srAlgo, SUN_PROVIDER), |
|
136 !(nsa(mech)), NoSuchAlgorithmException.class, |
|
137 String.format("PASS - It is expected to fail for " |
|
138 + "getInstance(algorithm, providerName) when " |
|
139 + "algorithm: '%s' is null or invalid.", mech)), |
|
140 mech); |
|
141 // Test for getInstance(algorithm, providerName) method. |
|
142 checkAttributes( |
|
143 matchExc(() -> SecureRandom.getInstance( |
|
144 srAlgo, INVALID_PROVIDER), |
|
145 !PASS, NoSuchProviderException.class, |
|
146 String.format("PASS - It is expected to fail for " |
|
147 + "getInstance(algorithm, providerName) when " |
|
148 + "provider name: '%s' is invalid and " |
|
149 + "algorithm: '%s'", INVALID_PROVIDER, mech)), |
|
150 mech); |
|
151 |
|
152 // Run the test for a set of SecureRandomParameters |
|
153 for (SecureRandomParameters param : Arrays.asList(null, |
|
154 DrbgParameters.instantiation(-1, NONE, null))) { |
|
155 |
|
156 System.out.printf("%nRunning DRBG param getInstance() methods " |
|
157 + "for algorithm: %s and DRBG param type: %s", mech, |
|
158 (param != null) ? param.getClass().getName() : param); |
|
159 |
|
160 // Following Test are applicable for new DRBG methods only. |
|
161 // Test for getInstance(algorithm, params) method. |
|
162 // Tests are expected to pass for DRBG type with valid parameter |
|
163 // If it fails the expected exception type is derived from |
|
164 // getExcType(mech, param) method. If exception type is not |
|
165 // expected then the test will be considered as failure. |
|
166 checkAttributes( |
|
167 matchExc(() -> SecureRandom.getInstance(srAlgo, param), |
|
168 (isDRBG(mech)) && (isValidDRBGParam(param)), |
|
169 getExcType(mech, param), |
|
170 String.format("PASS - It is expected to fail " |
|
171 + "for getInstance(algorithm, params) " |
|
172 + "for algorithm: %s and parameter: %s", |
|
173 mech, param)), |
|
174 mech); |
|
175 // Test for getInstance(algorithm, params, provider) method. |
|
176 checkAttributes( |
|
177 matchExc(() -> SecureRandom.getInstance(srAlgo, param, |
|
178 Security.getProvider(SUN_PROVIDER)), |
|
179 (isDRBG(mech)) && (isValidDRBGParam(param)), |
|
180 getExcType(mech, param), |
|
181 String.format("PASS - It is expected to fail " |
|
182 + "for getInstance(algorithm, params, " |
|
183 + "provider) for algorithm: %s and " |
|
184 + "parameter: %s", mech, param)), |
|
185 mech); |
|
186 // Test for getInstance(algorithm, params, providerName) method. |
|
187 checkAttributes( |
|
188 matchExc(() -> SecureRandom.getInstance(srAlgo, param, |
|
189 SUN_PROVIDER), |
|
190 (isDRBG(mech)) && (isValidDRBGParam(param)), |
|
191 getExcType(mech, param), |
|
192 String.format("PASS - It is expected to fail " |
|
193 + "for getInstance(algorithm, params, " |
|
194 + "providerName) for algorithm: %s and " |
|
195 + "parameter: %s", mech, param)), mech); |
|
196 // getInstance(algorithm, params, providerName) when |
|
197 // providerName is invalid |
|
198 checkAttributes( |
|
199 matchExc(() -> SecureRandom.getInstance(srAlgo, param, |
|
200 INVALID_PROVIDER), |
|
201 !PASS, ((param == null) |
|
202 ? IllegalArgumentException.class |
|
203 : NoSuchProviderException.class), |
|
204 String.format("PASS - It is expected to fail " |
|
205 + "for getInstance(algorithm, params, " |
|
206 + "providerName) when param is null or" |
|
207 + " provider: %s is invalid for " |
|
208 + "algorithm: '%s'", INVALID_PROVIDER, |
|
209 mech)), mech); |
|
210 // getInstance(algorithm, params, provider) when provider=null |
|
211 checkAttributes( |
|
212 matchExc(() -> SecureRandom.getInstance(srAlgo, param, |
|
213 (String) null), |
|
214 !PASS, IllegalArgumentException.class, |
|
215 String.format("PASS - It is expected to fail " |
|
216 + "for getInstance(algorithm, params, " |
|
217 + "providerName) when provider name " |
|
218 + "is null")), mech); |
|
219 // getInstance(algorithm, params, providerName) when |
|
220 // providerName is empty. |
|
221 checkAttributes( |
|
222 matchExc(() -> SecureRandom.getInstance( |
|
223 srAlgo, param, ""), |
|
224 !PASS, IllegalArgumentException.class, |
|
225 String.format("PASS - It is expected to fail " |
|
226 + "for getInstance(algorithm, params, " |
|
227 + "providerName) when provider name " |
|
228 + "is empty")), mech); |
|
229 } |
|
230 } |
|
231 |
|
232 private static boolean isValidDRBGParam(SecureRandomParameters param) { |
|
233 return (param instanceof DrbgParameters.Instantiation); |
|
234 } |
|
235 |
|
236 /** |
|
237 * If the mechanism should occur NoSuchAlgorithmException. |
|
238 */ |
|
239 private static boolean nsa(String mech) { |
|
240 return mech.equals(INVALID_ALGO); |
|
241 } |
|
242 |
|
243 /** |
|
244 * Verify if the mechanism is DRBG type. |
|
245 * @param mech Mechanism name |
|
246 * @return True if the mechanism name is DRBG type else False. |
|
247 */ |
|
248 private static boolean isDRBG(String mech) { |
|
249 return mech.contains("_DRBG"); |
|
250 } |
|
251 |
|
252 /** |
|
253 * Type of exception expected for a SecureRandom instance when exception |
|
254 * occurred while calling getInstance method with a fixed set of parameter. |
|
255 * @param mech Mechanism used to create a SecureRandom instance |
|
256 * @param param Parameter to getInstance() method |
|
257 * @return Exception type expected |
|
258 */ |
|
259 private static Class getExcType(String mech, SecureRandomParameters param) { |
|
260 return ((isDRBG(mech) && !isValidDRBGParam(param)) || param == null) |
|
261 ? IllegalArgumentException.class |
|
262 : NoSuchAlgorithmException.class; |
|
263 } |
|
264 |
|
265 private interface RunnableCode { |
|
266 |
|
267 SecureRandom run() throws Exception; |
|
268 } |
|
269 |
|
270 /** |
|
271 * Execute a given code block and verify, if the exception type is expected. |
|
272 * @param r Code block to run |
|
273 * @param ex Expected exception type |
|
274 * @param shouldPass If the code execution expected to pass without failure |
|
275 * @param msg Message to log in case of expected failure |
|
276 */ |
|
277 private static SecureRandom matchExc(RunnableCode r, boolean shouldPass, |
|
278 Class ex, String msg) { |
|
279 SecureRandom sr = null; |
|
280 try { |
|
281 sr = r.run(); |
|
282 if (!shouldPass) { |
|
283 throw new RuntimeException("Excecution should fail here."); |
|
284 } |
|
285 } catch (Exception e) { |
|
286 System.out.printf("%nOccured exception: %s - Expected exception: %s" |
|
287 + " : ", e.getClass(), ex.getCanonicalName()); |
|
288 if (ex.isAssignableFrom(e.getClass())) { |
|
289 System.out.printf("%n%s : Expected Exception: %s : ", |
|
290 e.getClass(), msg); |
|
291 } else if (shouldPass) { |
|
292 throw new RuntimeException(e); |
|
293 } else { |
|
294 System.out.printf("%nIgnore the following exception: %s%n", |
|
295 e.getMessage()); |
|
296 } |
|
297 } |
|
298 return sr; |
|
299 } |
|
300 |
|
301 /** |
|
302 * Check specific attributes of a SecureRandom instance. |
|
303 */ |
|
304 private static void checkAttributes(SecureRandom sr, String mech) { |
|
305 if (sr == null) { |
|
306 return; |
|
307 } |
|
308 Asserts.assertEquals(sr.getAlgorithm(), (isDRBG(mech) ? "DRBG" : mech)); |
|
309 Asserts.assertEquals(sr.getProvider().getName(), SUN_PROVIDER); |
|
310 } |
|
311 |
|
312 } |