1 /* 2 * Copyright (c) 2013, 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 6425477 8141039 27 * @summary Better support for generation of high entropy random numbers 28 * @run main StrongSecureRandom 29 */ 30 import java.security.*; 31 import java.util.*; 32 33 /** 34 * This test assumes that the standard Sun providers are installed. 35 */ 36 public class StrongSecureRandom { 37 38 private static final String os = System.getProperty("os.name", "unknown"); 39 private static final String DRBG_CONFIG = "securerandom.drbg.config"; 40 private static final String DRBG_CONFIG_VALUE 41 = Security.getProperty(DRBG_CONFIG); 42 43 private static void testDefaultEgd() throws Exception { 44 // No SecurityManager installed. 45 String s = Security.getProperty("securerandom.source"); 46 47 System.out.println("Testing: default EGD: " + s); 48 if (!s.equals("file:/dev/random")) { 49 throw new Exception("Default is not 'file:/dev/random'"); 50 } 51 } 52 53 /** 54 * Verify if the mechanism is DRBG type. 55 * @param mech Mechanism name 56 * @return True if the mechanism name is DRBG type else False. 57 */ 58 private static boolean isDRBG(String mech) { 59 return mech.contains("_DRBG"); 60 } 61 62 private static void testSecureRandomImpl(String algo, boolean drbg) 63 throws Exception { 64 65 byte[] ba; 66 final String secureRandomSource 67 = Security.getProperty("securerandom.source"); 68 try { 69 String urandom = "file:/dev/urandom"; 70 71 System.out.println("Testing new SeedGenerator and EGD"); 72 73 Security.setProperty("securerandom.source", urandom); 74 if (!Security.getProperty("securerandom.source").equals(urandom)) { 75 throw new Exception("Couldn't set securerandom.source"); 76 } 77 78 /* 79 * Take out a large number of bytes in hopes of blocking. 80 * Don't expect this to happen, unless something is broken on Linux 81 */ 82 SecureRandom sr = null; 83 if (drbg) { 84 Security.setProperty(DRBG_CONFIG, algo); 85 sr = SecureRandom.getInstance("DRBG"); 86 } else { 87 sr = SecureRandom.getInstance(algo); 88 } 89 if (!sr.getAlgorithm().equals(isDRBG(algo) ? "DRBG" : algo)) { 90 throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); 91 } 92 93 ba = sr.generateSeed(4096); 94 sr.nextBytes(ba); 95 sr.setSeed(ba); 96 } finally { 97 Security.setProperty("securerandom.source", secureRandomSource); 98 Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE); 99 } 100 } 101 102 private static void testNativePRNGImpls() throws Exception { 103 SecureRandom sr; 104 byte[] ba; 105 106 System.out.println("Testing new NativePRNGImpls"); 107 108 if (os.startsWith("Windows")) { 109 System.out.println("Skip windows testing."); 110 return; 111 } 112 113 System.out.println("Testing regular"); 114 sr = SecureRandom.getInstance("NativePRNG"); 115 if (!sr.getAlgorithm().equals("NativePRNG")) { 116 throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); 117 } 118 ba = sr.generateSeed(1); 119 sr.nextBytes(ba); 120 sr.setSeed(ba); 121 122 System.out.println("Testing NonBlocking"); 123 sr = SecureRandom.getInstance("NativePRNGNonBlocking"); 124 if (!sr.getAlgorithm().equals("NativePRNGNonBlocking")) { 125 throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); 126 } 127 ba = sr.generateSeed(1); 128 sr.nextBytes(ba); 129 sr.setSeed(ba); 130 131 if (os.equals("Linux")) { 132 System.out.println("Skip Linux blocking test."); 133 return; 134 } 135 136 System.out.println("Testing Blocking"); 137 sr = SecureRandom.getInstance("NativePRNGBlocking"); 138 if (!sr.getAlgorithm().equals("NativePRNGBlocking")) { 139 throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm()); 140 } 141 ba = sr.generateSeed(1); 142 sr.nextBytes(ba); 143 sr.setSeed(ba); 144 } 145 146 private static void testStrongInstance(boolean expected) throws Exception { 147 148 boolean result; 149 150 try { 151 SecureRandom.getInstanceStrong(); 152 result = true; 153 } catch (NoSuchAlgorithmException e) { 154 result = false; 155 } 156 157 if (expected != result) { 158 throw new Exception("Received: " + result); 159 } 160 } 161 162 /* 163 * This test assumes that the standard providers are installed. 164 */ 165 private static void testProperty(String property, boolean expected) 166 throws Exception { 167 168 System.out.println("Testing: '" + property + "' " + expected); 169 final String origStrongAlgoProp 170 = Security.getProperty("securerandom.strongAlgorithms"); 171 try { 172 Security.setProperty("securerandom.strongAlgorithms", property); 173 testStrongInstance(expected); 174 } finally { 175 Security.setProperty( 176 "securerandom.strongAlgorithms", origStrongAlgoProp); 177 } 178 } 179 180 private static void testProperties() throws Exception { 181 // Sets securerandom.strongAlgorithms, and then tests various combos. 182 testProperty("", false); 183 184 testProperty("SHA1PRNG", true); 185 testProperty(" SHA1PRNG", true); 186 testProperty("SHA1PRNG ", true); 187 testProperty(" SHA1PRNG ", true); 188 189 // Impls are case-insenstive, providers are sensitive. 190 testProperty("SHA1PRNG:SUN", true); 191 testProperty("Sha1PRNG:SUN", true); 192 testProperty("SHA1PRNG:Sun", false); 193 194 testProperty(" SHA1PRNG:SUN", true); 195 testProperty("SHA1PRNG:SUN ", true); 196 testProperty(" SHA1PRNG:SUN ", true); 197 198 testProperty(" SHA1PRNG:SUn", false); 199 testProperty("SHA1PRNG:SUn ", false); 200 testProperty(" SHA1PRNG:SUn ", false); 201 202 testProperty(",,,SHA1PRNG", true); 203 testProperty(",,, SHA1PRNG", true); 204 testProperty(" , , ,SHA1PRNG ", true); 205 206 testProperty(",,,, SHA1PRNG ,,,", true); 207 testProperty(",,,, SHA1PRNG:SUN ,,,", true); 208 testProperty(",,,, SHA1PRNG:SUn ,,,", false); 209 210 testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUN", true); 211 testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUN", true); 212 testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUN", true); 213 214 testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUn", false); 215 testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUn", false); 216 testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUn", false); 217 218 testProperty( 219 " @#%,%$#:!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUN", 220 true); 221 testProperty(" @#%,%$#!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUn", 222 false); 223 } 224 225 /* 226 * Linux tends to block, so ignore anything that reads /dev/random. 227 */ 228 private static void handleLinuxRead(SecureRandom sr) throws Exception { 229 if (os.equals("Linux")) { 230 if (!sr.getAlgorithm().equalsIgnoreCase("NativePRNGBlocking")) { 231 sr.nextBytes(new byte[34]); 232 } 233 } else { 234 sr.nextBytes(new byte[34]); 235 sr.generateSeed(34); 236 sr.setSeed(new byte[34]); 237 } 238 } 239 240 /* 241 * This is duplicating stuff above, but just iterate over all impls 242 * just in case we missed something. 243 */ 244 private static void testAllImpls() throws Exception { 245 System.out.print("Testing: AllImpls: "); 246 247 Iterator<String> i = Security.getAlgorithms("SecureRandom").iterator(); 248 249 while (i.hasNext()) { 250 String s = i.next(); 251 System.out.print("/" + s); 252 SecureRandom sr = SecureRandom.getInstance(s); 253 254 handleLinuxRead(sr); 255 handleLinuxRead(sr); 256 } 257 System.out.println("/"); 258 } 259 260 public static void main(String args[]) throws Exception { 261 testDefaultEgd(); 262 for (String algo : new String[]{ 263 "SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) { 264 testSecureRandomImpl(algo, isDRBG(algo)); 265 } 266 testNativePRNGImpls(); 267 testAllImpls(); 268 269 // test default. 270 testStrongInstance(true); 271 testProperties(); 272 } 273 }