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 /* @test 25 * @bug 8051408 26 * @modules java.base/sun.security.provider 27 * @summary check the AbstractDrbg API etc 28 */ 29 30 import java.security.*; 31 import sun.security.provider.AbstractDrbg; 32 import static java.security.DrbgParameters.Capability.*; 33 34 /** 35 * This test makes sure the AbstractDrbg API works as specified. It also 36 * checks the SecureRandom API. 37 */ 38 public class AbstractDrbgSpec { 39 40 public static void main(String args[]) throws Exception { 41 42 // getInstance from a provider. 43 44 Provider p = new All("A", 0, ""); 45 byte[] bytes = new byte[100]; 46 47 // A non-DRBG 48 iae(() -> SecureRandom.getInstance("S1", null, p)); 49 nsae(() -> SecureRandom.getInstance("S1", 50 new SecureRandomParameters() {}, p)); 51 52 SecureRandom s1 = SecureRandom.getInstance("S1", p); 53 if (s1.getParameters() != null) { 54 throw new Exception(); 55 } 56 57 npe(() -> s1.nextBytes(null)); 58 iae(() -> s1.nextBytes(bytes, null)); 59 uoe(() -> s1.nextBytes(bytes, new SecureRandomParameters() {})); 60 uoe(() -> s1.reseed()); 61 iae(() -> s1.reseed(null)); 62 uoe(() -> s1.reseed(new SecureRandomParameters() {})); 63 64 // A weak DRBG 65 iae(() -> SecureRandom.getInstance("S2", null, p)); 66 nsae(() -> SecureRandom.getInstance("S2", 67 new SecureRandomParameters() {}, p)); 68 nsae(() -> SecureRandom.getInstance("S2", 69 DrbgParameters.instantiate(256, NONE, null), p)); 70 nsae(() -> SecureRandom.getInstance("S2", 71 DrbgParameters.instantiate(-1, PR_AND_RESEED, null), p)); 72 nsae(() -> SecureRandom.getInstance("S2", 73 DrbgParameters.instantiate(-1, RESEED_ONLY, null), p)); 74 75 SecureRandom s2 = SecureRandom.getInstance("S2", 76 DrbgParameters.instantiate(-1, NONE, null), p); 77 equals(s2, "S2,SQUEEZE,128,none"); 78 equals(s2.getParameters(), "128,none,null"); 79 80 npe(() -> s2.nextBytes(null)); 81 iae(() -> s2.nextBytes(bytes, null)); 82 iae(() -> s2.nextBytes(bytes, new SecureRandomParameters() {})); 83 uoe(() -> s2.reseed()); 84 iae(() -> s2.reseed(null)); 85 86 iae(() -> s2.nextBytes(bytes, DrbgParameters.nextBytes(-1, false, new byte[101]))); 87 iae(() -> s2.nextBytes(new byte[101], DrbgParameters.nextBytes(-1, false, new byte[100]))); 88 s2.nextBytes(bytes, DrbgParameters.nextBytes(-1, false, new byte[100])); 89 90 // A strong DRBG 91 iae(() -> SecureRandom.getInstance("S3", null, p)); 92 nsae(() -> SecureRandom.getInstance("S3", 93 new SecureRandomParameters() {}, p)); 94 SecureRandom.getInstance("S3", 95 DrbgParameters.instantiate(192, PR_AND_RESEED, null), p); 96 97 SecureRandom s3 = SecureRandom.getInstance("S3", p); 98 equals(s3, "S3,SQUEEZE,128,reseed_only"); 99 equals(s3.getParameters(), "128,reseed_only,null"); 100 101 iae(() -> s3.nextBytes(bytes, DrbgParameters.nextBytes(192, false, null))); 102 iae(() -> s3.nextBytes(bytes, DrbgParameters.nextBytes(112, true, null))); 103 iae(() -> s3.reseed(new SecureRandomParameters() {})); 104 105 SecureRandom s32 = SecureRandom.getInstance( 106 "S3", DrbgParameters.instantiate(192, PR_AND_RESEED, null), p); 107 equals(s32, "S3,SQUEEZE,192,pr_and_reseed"); 108 equals(s32.getParameters(), "192,pr_and_reseed,null"); 109 110 s32.nextBytes(bytes, DrbgParameters.nextBytes(192, false, null)); 111 s32.nextBytes(bytes, DrbgParameters.nextBytes(112, true, null)); 112 s32.reseed(); 113 s32.reseed(DrbgParameters.reseed(true, new byte[100])); 114 115 // getInstance from competitive providers. 116 117 Provider l = new Legacy("L", 0, ""); 118 Provider w = new Weak("W", 0, ""); 119 Provider s = new Strong("S", 0, ""); 120 121 Security.addProvider(l); 122 Security.addProvider(w); 123 Security.addProvider(s); 124 125 SecureRandom s4; 126 127 try { 128 s4 = SecureRandom.getInstance("S"); 129 if (s4.getProvider() != l) { 130 throw new Exception(); 131 } 132 133 nsae(() -> SecureRandom.getInstance( 134 "S", DrbgParameters.instantiate(256, NONE, null))); 135 136 s4 = SecureRandom.getInstance( 137 "S", DrbgParameters.instantiate(192, NONE, null)); 138 if (s4.getProvider() != s) { 139 throw new Exception(); 140 } 141 142 s4 = SecureRandom.getInstance( 143 "S", DrbgParameters.instantiate(128, PR_AND_RESEED, null)); 144 if (s4.getProvider() != s) { 145 throw new Exception(); 146 } 147 148 s4 = SecureRandom.getInstance( 149 "S", DrbgParameters.instantiate(128, RESEED_ONLY, null)); 150 if (s4.getProvider() != s) { 151 throw new Exception(); 152 } 153 154 s4 = SecureRandom.getInstance( 155 "S", DrbgParameters.instantiate(128, NONE, null)); 156 if (s4.getProvider() != w) { 157 throw new Exception(); 158 } 159 } finally { 160 Security.removeProvider("L"); 161 Security.removeProvider("W"); 162 Security.removeProvider("S"); 163 } 164 } 165 166 public static class All extends Provider { 167 protected All(String name, double version, String info) { 168 super(name, version, info); 169 put("SecureRandom.S1", S1.class.getName()); 170 put("SecureRandom.S2", S2.class.getName()); 171 put("SecureRandom.S3", S3.class.getName()); 172 } 173 } 174 175 // Providing S with no params support 176 public static class Legacy extends Provider { 177 protected Legacy(String name, double version, String info) { 178 super(name, version, info); 179 put("SecureRandom.S", S1.class.getName()); 180 } 181 } 182 183 public static class Weak extends Provider { 184 protected Weak(String name, double version, String info) { 185 super(name, version, info); 186 put("SecureRandom.S", S2.class.getName()); 187 } 188 } 189 190 public static class Strong extends Provider { 191 protected Strong(String name, double version, String info) { 192 super(name, version, info); 193 put("SecureRandom.S", S3.class.getName()); 194 } 195 } 196 197 // This is not a DRBG. 198 public static class S1 extends SecureRandomSpi { 199 @Override 200 protected void engineSetSeed(byte[] seed) { 201 } 202 203 @Override 204 protected void engineNextBytes(byte[] bytes) { 205 } 206 207 @Override 208 protected byte[] engineGenerateSeed(int numBytes) { 209 return new byte[numBytes]; 210 } 211 } 212 213 // This is a strong DRBG. 214 public static class S3 extends AbstractDrbg { 215 216 public S3(SecureRandomParameters params) { 217 supportPr = true; 218 supportReseed = true; 219 highestSecurity = 192; 220 mechName = "S3"; 221 algorithm = "SQUEEZE"; 222 configureInternal(params); 223 } 224 protected void chooseAlgorithmAndStrength() { 225 if (requestedStrength < 0) { 226 strength = defaultStrength; 227 } else { 228 strength = requestedStrength; 229 } 230 minLength = strength / 8; 231 maxAiLength = maxPsLength = maxNbLength = 100; 232 } 233 234 @Override 235 protected void initEngine() { 236 237 } 238 239 @Override 240 protected void instantiateAlgorithm(byte[] ei) { 241 242 } 243 244 @Override 245 protected void generateAlgorithm(byte[] result, byte[] additionalInput) { 246 247 } 248 249 @Override 250 protected void reseedAlgorithm(byte[] ei, byte[] additionalInput) { 251 252 } 253 } 254 255 // This is a weak DRBG. maximum strength is 192 and does 256 // not support prediction resistance or reseed. 257 public static class S2 extends S3 { 258 public S2(SecureRandomParameters params) { 259 super(null); 260 mechName = "S2"; 261 highestSecurity = 128; 262 supportPr = false; 263 supportReseed = false; 264 configureInternal(params); 265 } 266 } 267 268 static void nsae(RunnableWithException r) throws Exception { 269 checkException(r, NoSuchAlgorithmException.class); 270 } 271 272 static void iae(RunnableWithException r) throws Exception { 273 checkException(r, IllegalArgumentException.class); 274 } 275 276 static void uoe(RunnableWithException r) throws Exception { 277 checkException(r, UnsupportedOperationException.class); 278 } 279 280 static void npe(RunnableWithException r) throws Exception { 281 checkException(r, NullPointerException.class); 282 } 283 284 interface RunnableWithException { 285 void run() throws Exception; 286 } 287 288 static void checkException(RunnableWithException r, Class ex) 289 throws Exception { 290 try { 291 r.run(); 292 } catch (Exception e) { 293 if (ex.isAssignableFrom(e.getClass())) { 294 return; 295 } 296 throw e; 297 } 298 throw new Exception("No exception thrown"); 299 } 300 301 static void equals(Object o, String s) throws Exception { 302 if (!o.toString().equals(s)) { 303 throw new Exception(o.toString() + " is not " + s); 304 } 305 } 306 }