--- a/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java Tue Jun 07 10:10:59 2016 +0800
@@ -33,12 +33,13 @@
import static java.security.DrbgParameters.Capability.*;
/**
- * The abstract base class for all DRBGs.
+ * The abstract base class for all DRBGs. It is used as {@link DRBG#impl}.
* <p>
- * This class creates 5 new abstract methods. 3 are defined by the SP800-90A:
+ * This class has 5 abstract methods. 3 are defined by SP800-90A:
* <ol>
* <li>{@link #generateAlgorithm(byte[], byte[])}
- * <li>{@link #reseedAlgorithm(byte[], byte[])} (might not be supported)
+ * <li>{@link #reseedAlgorithm(byte[], byte[])} (In fact this is not an
+ * abstract method, but any DRBG supporting reseeding must override it.)
* <li>{@link #instantiateAlgorithm(byte[])}
* </ol>
* and 2 for implementation purpose:
@@ -46,18 +47,19 @@
* <li>{@link #initEngine()}
* <li>{@link #chooseAlgorithmAndStrength}
* </ol>
- * All existing {@link SecureRandomSpi} methods are implemented based on the
- * methods above as final. The initialization process is divided into 2 phases:
- * configuration is eagerly called to set up parameters, and instantiation
- * is lazily called only when nextBytes or reseed is called.
+ * Although this class is not a child class of {@link SecureRandomSpi}, it
+ * implements all abstract methods there as final.
+ * <p>
+ * The initialization process of a DRBG is divided into 2 phases:
+ * {@link #configure configuration} is eagerly called to set up parameters,
+ * and {@link #instantiateIfNecessary instantiation} is lazily called only
+ * when nextBytes or reseed is called.
* <p>
* SecureRandom methods like reseed and nextBytes are not thread-safe.
* An implementation is required to protect shared access to instantiate states
- * (instantiated, nonce) and DRBG states (v, c, key, reseedCounter).
+ * (instantiated, nonce) and DRBG states (v, c, key, reseedCounter, etc).
*/
-public abstract class AbstractDrbg extends SecureRandomSpi {
-
- private static final long serialVersionUID = 9L;
+public abstract class AbstractDrbg {
/**
* This field is not null if {@code -Djava.security.debug=securerandom} is
@@ -69,7 +71,7 @@
// Common working status
- private transient boolean instantiated = false;
+ private boolean instantiated = false;
/**
* Reseed counter of a DRBG instance. A mechanism should increment it
@@ -78,7 +80,7 @@
*
* Volatile, will be used in a double checked locking.
*/
- protected transient volatile int reseedCounter = 0;
+ protected volatile int reseedCounter = 0;
// Mech features. If not same as below, must be redefined in constructor.
@@ -170,7 +172,7 @@
/**
* Algorithm used by this instance (SHA-512 or AES-256). Must be assigned
* in {@link #chooseAlgorithmAndStrength}. This field is used in
- * {@link #toString()} and {@link DRBG#algorithmName}.
+ * {@link #toString()}.
*/
protected String algorithm;
@@ -217,7 +219,7 @@
* After instantiation, this field is not null. Do not modify it
* in a mechanism.
*/
- protected transient byte[] nonce;
+ protected byte[] nonce;
/**
* Requested nonce in {@link MoreDrbgParameters}. If set to null,
@@ -237,7 +239,7 @@
* {@link #configure(SecureRandomParameters)}. This field
* can be null. {@link #getEntropyInput} will take care of null check.
*/
- private transient EntropySource es;
+ private EntropySource es;
// Five abstract methods for SP 800-90A DRBG
@@ -286,10 +288,7 @@
/**
* Initiates security engines ({@code MessageDigest}, {@code Mac},
- * or {@code Cipher}). Must be called in deserialization. Please note
- * that before instantiation the algorithm might not be available yet.
- * In this case, just return and this method will be called
- * automatically at instantiation.
+ * or {@code Cipher}). This method is called during instantiation.
*/
protected abstract void initEngine();
@@ -331,13 +330,11 @@
// SecureRandomSpi methods taken care of here. All final.
- @Override
protected final void engineNextBytes(byte[] result) {
engineNextBytes(result, DrbgParameters.nextBytes(
-1, predictionResistanceFlag, null));
}
- @Override
protected final void engineNextBytes(
byte[] result, SecureRandomParameters params) {
@@ -402,7 +399,6 @@
}
}
- @Override
public final void engineReseed(SecureRandomParameters params) {
if (debug != null) {
debug.println(this, "reseed with params");
@@ -454,7 +450,6 @@
* @param numBytes the number of seed bytes to generate.
* @return the seed bytes.
*/
- @Override
public final byte[] engineGenerateSeed(int numBytes) {
byte[] b = new byte[numBytes];
SeedGenerator.generateSeed(b);
@@ -469,7 +464,6 @@
*
* @param input the seed
*/
- @Override
public final synchronized void engineSetSeed(byte[] input) {
if (debug != null) {
debug.println(this, "setSeed");
@@ -598,7 +592,6 @@
*
* @return the curent configuration
*/
- @Override
protected SecureRandomParameters engineGetParameters() {
// Or read from variable.
return DrbgParameters.instantiation(
@@ -631,7 +624,8 @@
this.es = m.es;
this.requestedAlgorithm = m.algorithm;
this.usedf = m.usedf;
- params = m.config;
+ params = DrbgParameters.instantiation(m.strength,
+ m.capability, m.personalizationString);
}
if (params != null) {
if (params instanceof DrbgParameters.Instantiation) {
--- a/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java Tue Jun 07 10:10:59 2016 +0800
@@ -32,8 +32,6 @@
public abstract class AbstractHashDrbg extends AbstractDrbg {
- private static final long serialVersionUID = 9L;
-
protected int outLen;
protected int seedLen;
--- a/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java Tue Jun 07 10:10:59 2016 +0800
@@ -28,14 +28,12 @@
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
-import java.io.IOException;
import java.security.*;
import java.util.Arrays;
import java.util.Locale;
public class CtrDrbg extends AbstractDrbg {
- private static final long serialVersionUID = 9L;
private static final int AES_LIMIT;
static {
@@ -47,7 +45,7 @@
}
}
- private transient Cipher cipher;
+ private Cipher cipher;
private String cipherAlg;
private String keyAlg;
@@ -57,8 +55,8 @@
private int keyLen;
private int seedLen;
- private transient byte[] v;
- private transient byte[] k;
+ private byte[] v;
+ private byte[] k;
public CtrDrbg(SecureRandomParameters params) {
mechName = "CTR_DRBG";
@@ -165,7 +163,7 @@
protected void initEngine() {
try {
/*
- * Use the local SUN implementation to avoid native
+ * Use the local SunJCE implementation to avoid native
* performance overhead.
*/
cipher = Cipher.getInstance(cipherAlg, "SunJCE");
@@ -463,12 +461,6 @@
// Step 8. Return
}
- private void readObject(java.io.ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject ();
- initEngine();
- }
-
@Override
public String toString() {
return super.toString() + ","
--- a/jdk/src/java.base/share/classes/sun/security/provider/DRBG.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DRBG.java Tue Jun 07 10:10:59 2016 +0800
@@ -25,6 +25,7 @@
package sun.security.provider;
+import java.io.IOException;
import java.security.AccessController;
import java.security.DrbgParameters;
import java.security.PrivilegedAction;
@@ -61,11 +62,12 @@
private static final long serialVersionUID = 9L;
- private final AbstractDrbg impl;
+ private transient AbstractDrbg impl;
- private final String mechName;
-
- private final String algorithmName;
+ /**
+ * @serial
+ */
+ private final MoreDrbgParameters mdp;
public DRBG(SecureRandomParameters params) {
@@ -91,7 +93,7 @@
// Can be configured with a security property
String config = AccessController.doPrivileged((PrivilegedAction<String>)
- () -> Security.getProperty(PROP_NAME));
+ () -> Security.getProperty(PROP_NAME));
if (config != null && !config.isEmpty()) {
for (String part : config.split(",")) {
@@ -151,8 +153,9 @@
if (params != null) {
// MoreDrbgParameters is used for testing.
if (params instanceof MoreDrbgParameters) {
- MoreDrbgParameters m = (MoreDrbgParameters)params;
- params = m.config;
+ MoreDrbgParameters m = (MoreDrbgParameters) params;
+ params = DrbgParameters.instantiation(m.strength,
+ m.capability, m.personalizationString);
// No need to check null for es and nonce, they are still null
es = m.es;
@@ -197,26 +200,27 @@
usedf = true;
}
- MoreDrbgParameters m = new MoreDrbgParameters(
+ mdp = new MoreDrbgParameters(
es, mech, algorithm, nonce, usedf,
DrbgParameters.instantiation(strength, cap, ps));
- switch (mech.toLowerCase(Locale.ROOT)) {
+ createImpl();
+ }
+
+ private void createImpl() {
+ switch (mdp.mech.toLowerCase(Locale.ROOT)) {
case "hash_drbg":
- impl = new HashDrbg(m);
+ impl = new HashDrbg(mdp);
break;
case "hmac_drbg":
- impl = new HmacDrbg(m);
+ impl = new HmacDrbg(mdp);
break;
case "ctr_drbg":
- impl = new CtrDrbg(m);
+ impl = new CtrDrbg(mdp);
break;
default:
- throw new IllegalArgumentException("Unsupported mech: " + mech);
+ throw new IllegalArgumentException("Unsupported mech: " + mdp.mech);
}
-
- mechName = mech;
- algorithmName = impl.algorithm;
}
@Override
@@ -268,4 +272,13 @@
+ " cannot be provided more than once in " + PROP_NAME);
}
}
+
+ private void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ if (mdp.mech == null) {
+ throw new IllegalArgumentException("Input data is corrupted");
+ }
+ createImpl();
+ }
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java Tue Jun 07 10:10:59 2016 +0800
@@ -25,7 +25,6 @@
package sun.security.provider;
-import java.io.IOException;
import java.math.BigInteger;
import java.security.DigestException;
import java.security.MessageDigest;
@@ -36,15 +35,13 @@
public class HashDrbg extends AbstractHashDrbg {
- private static final long serialVersionUID = 9L;
-
private static final byte[] ZERO = new byte[1];
private static final byte[] ONE = new byte[]{1};
- private transient MessageDigest digest;
+ private MessageDigest digest;
- private transient byte[] v;
- private transient byte[] c;
+ private byte[] v;
+ private byte[] c;
public HashDrbg(SecureRandomParameters params) {
mechName = "Hash_DRBG";
@@ -267,10 +264,4 @@
// Step 5: No need to truncate
// Step 6: Return
}
-
- private void readObject(java.io.ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject ();
- initEngine();
- }
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java Tue Jun 07 10:10:59 2016 +0800
@@ -27,7 +27,6 @@
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
-import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -36,14 +35,12 @@
public class HmacDrbg extends AbstractHashDrbg {
- private static final long serialVersionUID = 9L;
-
- private transient Mac mac;
+ private Mac mac;
private String macAlg;
- private transient byte[] v;
- private transient byte[] k;
+ private byte[] v;
+ private byte[] k;
public HmacDrbg(SecureRandomParameters params) {
mechName = "HMAC_DRBG";
@@ -101,6 +98,10 @@
protected void initEngine() {
macAlg = "HmacSHA" + algorithm.substring(4);
try {
+ /*
+ * Use the local SunJCE implementation to avoid native
+ * performance overhead.
+ */
mac = Mac.getInstance(macAlg, "SunJCE");
} catch (NoSuchProviderException | NoSuchAlgorithmException e) {
// Fallback to any available.
@@ -194,10 +195,4 @@
// Step 8. Return
}
-
- private void readObject(java.io.ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject ();
- initEngine();
- }
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java Mon Jun 06 16:46:54 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java Tue Jun 07 10:10:59 2016 +0800
@@ -25,20 +25,30 @@
package sun.security.provider;
+import java.io.IOException;
+import java.io.Serializable;
import java.security.DrbgParameters;
import java.security.SecureRandomParameters;
/**
- * Extra non-standard parameters that can be used by DRBGs.
+ * Exported and non-exported parameters that can be used by DRBGs.
*/
-public class MoreDrbgParameters implements SecureRandomParameters {
+public class MoreDrbgParameters implements SecureRandomParameters, Serializable {
+
+ private static final long serialVersionUID = 9L;
+
+ final transient EntropySource es;
final String mech;
final String algorithm;
- final EntropySource es;
- final byte[] nonce;
final boolean usedf;
- final DrbgParameters.Instantiation config;
+ final int strength;
+ final DrbgParameters.Capability capability;
+
+ // The following 2 fields will be reassigned in readObject and
+ // thus cannot be final
+ byte[] nonce;
+ byte[] personalizationString;
/**
* Creates a new {@code MoreDrbgParameters} object.
@@ -61,13 +71,31 @@
this.mech = mech;
this.algorithm = algorithm;
this.es = es;
- this.nonce = nonce;
+ this.nonce = (nonce == null) ? null : nonce.clone();
this.usedf = usedf;
- this.config = config;
+
+ this.strength = config.getStrength();
+ this.capability = config.getCapability();
+ this.personalizationString = config.getPersonalizationString();
}
@Override
public String toString() {
- return mech + "," + algorithm + "," + usedf + "," + config;
+ return mech + "," + algorithm + "," + usedf + "," + strength
+ + "," + capability + "," + personalizationString;
+ }
+
+ private void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ if (nonce != null) {
+ nonce = nonce.clone();
+ }
+ if (personalizationString != null) {
+ personalizationString = personalizationString.clone();
+ }
+ if (capability == null) {
+ throw new IllegalArgumentException("Input data is corrupted");
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java Tue Jun 07 10:10:59 2016 +0800
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8051408 8157308
+ * @modules java.base/sun.security.provider
+ * @build java.base/sun.security.provider.S
+ * @run main SpecTest
+ * @summary check the AbstractDrbg API etc
+ */
+
+import java.security.*;
+import sun.security.provider.S;
+import static java.security.DrbgParameters.Capability.*;
+
+/**
+ * This test makes sure the AbstractDrbg API works as specified. It also
+ * checks the SecureRandom API.
+ *
+ * The implementations must be patched into java.base/sun.security.provider
+ * because AbstractDrbg is not a public interface.
+ */
+public class SpecTest {
+
+ public static void main(String args[]) throws Exception {
+
+ // getInstance from a provider.
+
+ Provider p = new All("A", 0, "");
+ byte[] bytes = new byte[100];
+
+ // A non-DRBG
+ iae(() -> SecureRandom.getInstance("S1", null, p));
+ nsae(() -> SecureRandom.getInstance("S1",
+ new SecureRandomParameters() {}, p));
+
+ SecureRandom s1 = SecureRandom.getInstance("S1", p);
+ if (s1.getParameters() != null) {
+ throw new Exception();
+ }
+
+ iae(() -> s1.nextBytes(bytes, null));
+ uoe(() -> s1.nextBytes(bytes, new SecureRandomParameters() {}));
+ uoe(() -> s1.reseed());
+ iae(() -> s1.reseed(null));
+ uoe(() -> s1.reseed(new SecureRandomParameters() {}));
+
+ // A weak DRBG
+ iae(() -> SecureRandom.getInstance("S2", null, p));
+ nsae(() -> SecureRandom.getInstance("S2",
+ new SecureRandomParameters() {}, p));
+ nsae(() -> SecureRandom.getInstance("S2",
+ DrbgParameters.instantiation(256, NONE, null), p));
+ nsae(() -> SecureRandom.getInstance("S2",
+ DrbgParameters.instantiation(-1, PR_AND_RESEED, null), p));
+ nsae(() -> SecureRandom.getInstance("S2",
+ DrbgParameters.instantiation(-1, RESEED_ONLY, null), p));
+
+ SecureRandom s2 = SecureRandom.getInstance("S2",
+ DrbgParameters.instantiation(-1, NONE, null), p);
+ equals(s2, "S2,SQUEEZE,128,none");
+ equals(s2.getParameters(), "128,none,null");
+
+ npe(() -> s2.nextBytes(null));
+ iae(() -> s2.nextBytes(bytes, null));
+ iae(() -> s2.nextBytes(bytes, new SecureRandomParameters() {}));
+ uoe(() -> s2.reseed());
+ iae(() -> s2.reseed(null));
+
+ iae(() -> s2.nextBytes(bytes,
+ DrbgParameters.nextBytes(-1, false, new byte[101])));
+ s2.nextBytes(new byte[101],
+ DrbgParameters.nextBytes(-1, false, new byte[100]));
+ s2.nextBytes(bytes,
+ DrbgParameters.nextBytes(-1, false, new byte[100]));
+
+ // A strong DRBG
+ iae(() -> SecureRandom.getInstance("S3", null, p));
+ nsae(() -> SecureRandom.getInstance("S3",
+ new SecureRandomParameters() {}, p));
+ SecureRandom.getInstance("S3",
+ DrbgParameters.instantiation(192, PR_AND_RESEED, null), p);
+
+ SecureRandom s3 = SecureRandom.getInstance("S3", p);
+ equals(s3, "S3,SQUEEZE,128,reseed_only");
+ equals(s3.getParameters(), "128,reseed_only,null");
+
+ iae(() -> s3.nextBytes(bytes,
+ DrbgParameters.nextBytes(192, false, null)));
+ iae(() -> s3.nextBytes(bytes,
+ DrbgParameters.nextBytes(112, true, null)));
+ iae(() -> s3.reseed(new SecureRandomParameters() {}));
+
+ SecureRandom s32 = SecureRandom.getInstance(
+ "S3", DrbgParameters.instantiation(192, PR_AND_RESEED, null), p);
+ equals(s32, "S3,SQUEEZE,192,pr_and_reseed");
+ equals(s32.getParameters(), "192,pr_and_reseed,null");
+
+ s32.nextBytes(bytes, DrbgParameters.nextBytes(192, false, null));
+ s32.nextBytes(bytes, DrbgParameters.nextBytes(112, true, null));
+ s32.reseed();
+ s32.reseed(DrbgParameters.reseed(true, new byte[100]));
+
+ // getInstance from competitive providers.
+
+ Provider l = new Legacy("L", 0, "");
+ Provider w = new Weak("W", 0, "");
+ Provider s = new Strong("S", 0, "");
+
+ Security.addProvider(l);
+ Security.addProvider(w);
+ Security.addProvider(s);
+
+ SecureRandom s4;
+
+ try {
+ s4 = SecureRandom.getInstance("S");
+ if (s4.getProvider() != l) {
+ throw new Exception();
+ }
+
+ nsae(() -> SecureRandom.getInstance(
+ "S", DrbgParameters.instantiation(256, NONE, null)));
+
+ s4 = SecureRandom.getInstance(
+ "S", DrbgParameters.instantiation(192, NONE, null));
+ if (s4.getProvider() != s) {
+ throw new Exception();
+ }
+
+ s4 = SecureRandom.getInstance(
+ "S", DrbgParameters.instantiation(128, PR_AND_RESEED, null));
+ if (s4.getProvider() != s) {
+ throw new Exception();
+ }
+
+ s4 = SecureRandom.getInstance(
+ "S", DrbgParameters.instantiation(128, RESEED_ONLY, null));
+ if (s4.getProvider() != s) {
+ throw new Exception();
+ }
+
+ s4 = SecureRandom.getInstance(
+ "S", DrbgParameters.instantiation(128, NONE, null));
+ if (s4.getProvider() != w) {
+ throw new Exception();
+ }
+ } finally {
+ Security.removeProvider("L");
+ Security.removeProvider("W");
+ Security.removeProvider("S");
+ }
+ }
+
+ public static class All extends Provider {
+ protected All(String name, double version, String info) {
+ super(name, version, info);
+ put("SecureRandom.S1", S.S1.class.getName());
+ put("SecureRandom.S2", S.S2.class.getName());
+ put("SecureRandom.S3", S.S3.class.getName());
+ }
+ }
+
+ // Providing S with no params support
+ public static class Legacy extends Provider {
+ protected Legacy(String name, double version, String info) {
+ super(name, version, info);
+ put("SecureRandom.S", S.S1.class.getName());
+ }
+ }
+
+ public static class Weak extends Provider {
+ protected Weak(String name, double version, String info) {
+ super(name, version, info);
+ put("SecureRandom.S", S.S2.class.getName());
+ }
+ }
+
+ public static class Strong extends Provider {
+ protected Strong(String name, double version, String info) {
+ super(name, version, info);
+ put("SecureRandom.S", S.S3.class.getName());
+ }
+ }
+
+ static void nsae(RunnableWithException r) throws Exception {
+ checkException(r, NoSuchAlgorithmException.class);
+ }
+
+ static void iae(RunnableWithException r) throws Exception {
+ checkException(r, IllegalArgumentException.class);
+ }
+
+ static void uoe(RunnableWithException r) throws Exception {
+ checkException(r, UnsupportedOperationException.class);
+ }
+
+ static void npe(RunnableWithException r) throws Exception {
+ checkException(r, NullPointerException.class);
+ }
+
+ interface RunnableWithException {
+ void run() throws Exception;
+ }
+
+ static void checkException(RunnableWithException r, Class ex)
+ throws Exception {
+ try {
+ r.run();
+ } catch (Exception e) {
+ if (ex.isAssignableFrom(e.getClass())) {
+ return;
+ }
+ throw e;
+ }
+ throw new Exception("No exception thrown");
+ }
+
+ static void equals(Object o, String s) throws Exception {
+ if (!o.toString().equals(s)) {
+ throw new Exception(o.toString() + " is not " + s);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/java.base/sun/security/provider/S.java Tue Jun 07 10:10:59 2016 +0800
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.provider;
+
+import java.security.SecureRandomParameters;
+import java.security.SecureRandomSpi;
+
+/**
+ * Read ../../../../SpecTest.java for details.
+ */
+public class S extends SecureRandomSpi {
+
+ protected AbstractDrbg impl;
+
+ // This is not a DRBG.
+ public static class S1 extends SecureRandomSpi {
+ @Override
+ protected void engineSetSeed(byte[] seed) {
+ }
+
+ @Override
+ protected void engineNextBytes(byte[] bytes) {
+ }
+
+ @Override
+ protected byte[] engineGenerateSeed(int numBytes) {
+ return new byte[numBytes];
+ }
+ }
+
+ // This is a weak DRBG. maximum strength is 128 and does
+ // not support prediction resistance or reseed.
+ public static class S2 extends S {
+ public S2(SecureRandomParameters params) {
+ impl = new Impl2(params);
+ }
+ }
+
+ // This is a strong DRBG.
+ public static class S3 extends S {
+ public S3(SecureRandomParameters params) {
+ impl = new Impl3(params);
+ }
+ }
+
+ // AbstractDrbg Implementations
+
+ static class Impl3 extends AbstractDrbg {
+
+ public Impl3(SecureRandomParameters params) {
+ supportPredictionResistance = true;
+ supportReseeding = true;
+ highestSupportedSecurityStrength = 192;
+ mechName = "S3";
+ algorithm = "SQUEEZE";
+ configure(params);
+ }
+
+ protected void chooseAlgorithmAndStrength() {
+ if (requestedInstantiationSecurityStrength < 0) {
+ securityStrength = DEFAULT_STRENGTH;
+ } else {
+ securityStrength = requestedInstantiationSecurityStrength;
+ }
+ minLength = securityStrength / 8;
+ maxAdditionalInputLength = maxPersonalizationStringLength = 100;
+ }
+
+ @Override
+ protected void initEngine() {
+ }
+
+ @Override
+ protected void instantiateAlgorithm(byte[] ei) {
+ }
+
+ @Override
+ protected void generateAlgorithm(byte[] result, byte[] additionalInput) {
+ }
+
+ @Override
+ protected void reseedAlgorithm(byte[] ei, byte[] additionalInput) {
+ }
+ }
+
+ static class Impl2 extends Impl3 {
+ public Impl2(SecureRandomParameters params) {
+ super(null);
+ mechName = "S2";
+ highestSupportedSecurityStrength = 128;
+ supportPredictionResistance = false;
+ supportReseeding = false;
+ configure(params);
+ }
+ }
+
+ // Overridden SecureRandomSpi methods
+
+ @Override
+ protected void engineSetSeed(byte[] seed) {
+ impl.engineSetSeed(seed);
+ }
+
+ @Override
+ protected void engineNextBytes(byte[] bytes) {
+ impl.engineNextBytes(bytes);
+ }
+
+ @Override
+ protected byte[] engineGenerateSeed(int numBytes) {
+ return impl.engineGenerateSeed(numBytes);
+ }
+
+ @Override
+ protected void engineNextBytes(
+ byte[] bytes, SecureRandomParameters params) {
+ impl.engineNextBytes(bytes, params);
+ }
+
+ @Override
+ protected void engineReseed(SecureRandomParameters params) {
+ impl.engineReseed(params);
+ }
+
+ @Override
+ protected SecureRandomParameters engineGetParameters() {
+ return impl.engineGetParameters();
+ }
+
+ @Override
+ public String toString() {
+ return impl.toString();
+ }
+}
--- a/jdk/test/sun/security/provider/SecureRandom/AbstractDrbgSpec.java Mon Jun 06 16:46:54 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @bug 8051408
- * @modules java.base/sun.security.provider
- * @summary check the AbstractDrbg API etc
- */
-
-import java.security.*;
-import sun.security.provider.AbstractDrbg;
-import static java.security.DrbgParameters.Capability.*;
-
-/**
- * This test makes sure the AbstractDrbg API works as specified. It also
- * checks the SecureRandom API.
- */
-public class AbstractDrbgSpec {
-
- public static void main(String args[]) throws Exception {
-
- // getInstance from a provider.
-
- Provider p = new All("A", 0, "");
- byte[] bytes = new byte[100];
-
- // A non-DRBG
- iae(() -> SecureRandom.getInstance("S1", null, p));
- nsae(() -> SecureRandom.getInstance("S1",
- new SecureRandomParameters() {}, p));
-
- SecureRandom s1 = SecureRandom.getInstance("S1", p);
- if (s1.getParameters() != null) {
- throw new Exception();
- }
-
- iae(() -> s1.nextBytes(bytes, null));
- uoe(() -> s1.nextBytes(bytes, new SecureRandomParameters() {}));
- uoe(() -> s1.reseed());
- iae(() -> s1.reseed(null));
- uoe(() -> s1.reseed(new SecureRandomParameters() {}));
-
- // A weak DRBG
- iae(() -> SecureRandom.getInstance("S2", null, p));
- nsae(() -> SecureRandom.getInstance("S2",
- new SecureRandomParameters() {}, p));
- nsae(() -> SecureRandom.getInstance("S2",
- DrbgParameters.instantiation(256, NONE, null), p));
- nsae(() -> SecureRandom.getInstance("S2",
- DrbgParameters.instantiation(-1, PR_AND_RESEED, null), p));
- nsae(() -> SecureRandom.getInstance("S2",
- DrbgParameters.instantiation(-1, RESEED_ONLY, null), p));
-
- SecureRandom s2 = SecureRandom.getInstance("S2",
- DrbgParameters.instantiation(-1, NONE, null), p);
- equals(s2, "S2,SQUEEZE,128,none");
- equals(s2.getParameters(), "128,none,null");
-
- npe(() -> s2.nextBytes(null));
- iae(() -> s2.nextBytes(bytes, null));
- iae(() -> s2.nextBytes(bytes, new SecureRandomParameters() {}));
- uoe(() -> s2.reseed());
- iae(() -> s2.reseed(null));
-
- iae(() -> s2.nextBytes(bytes,
- DrbgParameters.nextBytes(-1, false, new byte[101])));
- s2.nextBytes(new byte[101],
- DrbgParameters.nextBytes(-1, false, new byte[100]));
- s2.nextBytes(bytes,
- DrbgParameters.nextBytes(-1, false, new byte[100]));
-
- // A strong DRBG
- iae(() -> SecureRandom.getInstance("S3", null, p));
- nsae(() -> SecureRandom.getInstance("S3",
- new SecureRandomParameters() {}, p));
- SecureRandom.getInstance("S3",
- DrbgParameters.instantiation(192, PR_AND_RESEED, null), p);
-
- SecureRandom s3 = SecureRandom.getInstance("S3", p);
- equals(s3, "S3,SQUEEZE,128,reseed_only");
- equals(s3.getParameters(), "128,reseed_only,null");
-
- iae(() -> s3.nextBytes(bytes,
- DrbgParameters.nextBytes(192, false, null)));
- iae(() -> s3.nextBytes(bytes,
- DrbgParameters.nextBytes(112, true, null)));
- iae(() -> s3.reseed(new SecureRandomParameters() {}));
-
- SecureRandom s32 = SecureRandom.getInstance(
- "S3", DrbgParameters.instantiation(192, PR_AND_RESEED, null), p);
- equals(s32, "S3,SQUEEZE,192,pr_and_reseed");
- equals(s32.getParameters(), "192,pr_and_reseed,null");
-
- s32.nextBytes(bytes, DrbgParameters.nextBytes(192, false, null));
- s32.nextBytes(bytes, DrbgParameters.nextBytes(112, true, null));
- s32.reseed();
- s32.reseed(DrbgParameters.reseed(true, new byte[100]));
-
- // getInstance from competitive providers.
-
- Provider l = new Legacy("L", 0, "");
- Provider w = new Weak("W", 0, "");
- Provider s = new Strong("S", 0, "");
-
- Security.addProvider(l);
- Security.addProvider(w);
- Security.addProvider(s);
-
- SecureRandom s4;
-
- try {
- s4 = SecureRandom.getInstance("S");
- if (s4.getProvider() != l) {
- throw new Exception();
- }
-
- nsae(() -> SecureRandom.getInstance(
- "S", DrbgParameters.instantiation(256, NONE, null)));
-
- s4 = SecureRandom.getInstance(
- "S", DrbgParameters.instantiation(192, NONE, null));
- if (s4.getProvider() != s) {
- throw new Exception();
- }
-
- s4 = SecureRandom.getInstance(
- "S", DrbgParameters.instantiation(128, PR_AND_RESEED, null));
- if (s4.getProvider() != s) {
- throw new Exception();
- }
-
- s4 = SecureRandom.getInstance(
- "S", DrbgParameters.instantiation(128, RESEED_ONLY, null));
- if (s4.getProvider() != s) {
- throw new Exception();
- }
-
- s4 = SecureRandom.getInstance(
- "S", DrbgParameters.instantiation(128, NONE, null));
- if (s4.getProvider() != w) {
- throw new Exception();
- }
- } finally {
- Security.removeProvider("L");
- Security.removeProvider("W");
- Security.removeProvider("S");
- }
- }
-
- public static class All extends Provider {
- protected All(String name, double version, String info) {
- super(name, version, info);
- put("SecureRandom.S1", S1.class.getName());
- put("SecureRandom.S2", S2.class.getName());
- put("SecureRandom.S3", S3.class.getName());
- }
- }
-
- // Providing S with no params support
- public static class Legacy extends Provider {
- protected Legacy(String name, double version, String info) {
- super(name, version, info);
- put("SecureRandom.S", S1.class.getName());
- }
- }
-
- public static class Weak extends Provider {
- protected Weak(String name, double version, String info) {
- super(name, version, info);
- put("SecureRandom.S", S2.class.getName());
- }
- }
-
- public static class Strong extends Provider {
- protected Strong(String name, double version, String info) {
- super(name, version, info);
- put("SecureRandom.S", S3.class.getName());
- }
- }
-
- // This is not a DRBG.
- public static class S1 extends SecureRandomSpi {
- @Override
- protected void engineSetSeed(byte[] seed) {
- }
-
- @Override
- protected void engineNextBytes(byte[] bytes) {
- }
-
- @Override
- protected byte[] engineGenerateSeed(int numBytes) {
- return new byte[numBytes];
- }
- }
-
- // This is a strong DRBG.
- public static class S3 extends AbstractDrbg {
-
- public S3(SecureRandomParameters params) {
- supportPredictionResistance = true;
- supportReseeding = true;
- highestSupportedSecurityStrength = 192;
- mechName = "S3";
- algorithm = "SQUEEZE";
- configure(params);
- }
- protected void chooseAlgorithmAndStrength() {
- if (requestedInstantiationSecurityStrength < 0) {
- securityStrength = DEFAULT_STRENGTH;
- } else {
- securityStrength = requestedInstantiationSecurityStrength;
- }
- minLength = securityStrength / 8;
- maxAdditionalInputLength = maxPersonalizationStringLength = 100;
- }
-
- @Override
- protected void initEngine() {
-
- }
-
- @Override
- protected void instantiateAlgorithm(byte[] ei) {
-
- }
-
- @Override
- protected void generateAlgorithm(byte[] result, byte[] additionalInput) {
-
- }
-
- @Override
- protected void reseedAlgorithm(byte[] ei, byte[] additionalInput) {
-
- }
- }
-
- // This is a weak DRBG. maximum strength is 128 and does
- // not support prediction resistance or reseed.
- public static class S2 extends S3 {
- public S2(SecureRandomParameters params) {
- super(null);
- mechName = "S2";
- highestSupportedSecurityStrength = 128;
- supportPredictionResistance = false;
- supportReseeding = false;
- configure(params);
- }
- }
-
- static void nsae(RunnableWithException r) throws Exception {
- checkException(r, NoSuchAlgorithmException.class);
- }
-
- static void iae(RunnableWithException r) throws Exception {
- checkException(r, IllegalArgumentException.class);
- }
-
- static void uoe(RunnableWithException r) throws Exception {
- checkException(r, UnsupportedOperationException.class);
- }
-
- static void npe(RunnableWithException r) throws Exception {
- checkException(r, NullPointerException.class);
- }
-
- interface RunnableWithException {
- void run() throws Exception;
- }
-
- static void checkException(RunnableWithException r, Class ex)
- throws Exception {
- try {
- r.run();
- } catch (Exception e) {
- if (ex.isAssignableFrom(e.getClass())) {
- return;
- }
- throw e;
- }
- throw new Exception("No exception thrown");
- }
-
- static void equals(Object o, String s) throws Exception {
- if (!o.toString().equals(s)) {
- throw new Exception(o.toString() + " is not " + s);
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java Tue Jun 07 10:10:59 2016 +0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import sun.security.provider.DRBG;
+import sun.security.provider.MoreDrbgParameters;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
+
+/**
+ * @test
+ * @bug 8157308
+ * @modules java.base/sun.security.provider
+ * @summary Make AbstractDrbg non-Serializable
+ * @run main DRBGS11n mech
+ * @run main DRBGS11n capability
+ */
+public class DRBGS11n {
+
+ public static void main(String[] args) throws Exception {
+
+ DRBG d = new DRBG(null);
+ Field f = DRBG.class.getDeclaredField("mdp");
+ f.setAccessible(true);
+ MoreDrbgParameters mdp = (MoreDrbgParameters)f.get(d);
+
+ // Corrupt the mech or capability fields inside DRBG#mdp.
+ f = MoreDrbgParameters.class.getDeclaredField(args[0]);
+ f.setAccessible(true);
+ f.set(mdp, null);
+
+ try {
+ revive(d);
+ } catch (IllegalArgumentException iae) {
+ // Expected
+ return;
+ }
+
+ throw new Exception("revive should fail");
+ }
+
+ static <T> T revive(T in) throws Exception {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ new ObjectOutputStream(bout).writeObject(in);
+ return (T) new ObjectInputStream(
+ new ByteArrayInputStream(bout.toByteArray())).readObject();
+ }
+}