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 }