changeset 14374:2d42c4cfd5ac

8051408: NIST SP 800-90A SecureRandom implementations Reviewed-by: wetmore, xuelei, coffeys
author weijun
date Fri, 06 May 2016 11:38:44 +0800
parents 59248872ead8
children 160221b05c27
files src/java.base/share/classes/com/sun/crypto/provider/HmacCore.java src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java src/java.base/share/classes/java/security/DrbgParameters.java src/java.base/share/classes/java/security/Provider.java src/java.base/share/classes/java/security/SecureRandom.java src/java.base/share/classes/java/security/SecureRandomParameters.java src/java.base/share/classes/java/security/SecureRandomSpi.java src/java.base/share/classes/sun/security/provider/AbstractDrbg.java src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java src/java.base/share/classes/sun/security/provider/CtrDrbg.java src/java.base/share/classes/sun/security/provider/DRBG.java src/java.base/share/classes/sun/security/provider/EntropySource.java src/java.base/share/classes/sun/security/provider/HashDrbg.java src/java.base/share/classes/sun/security/provider/HmacDrbg.java src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java src/java.base/share/classes/sun/security/provider/SHA5.java src/java.base/share/classes/sun/security/provider/SunEntries.java src/java.base/share/classes/sun/security/util/Debug.java src/java.base/share/conf/security/java.security test/com/sun/crypto/provider/Mac/HmacSHA512.java test/java/security/SecureRandom/DrbgParametersSpec.java test/java/security/SecureRandom/Serialize.java test/sun/security/provider/MessageDigest/SHA512.java test/sun/security/provider/SecureRandom/AbstractDrbgSpec.java test/sun/security/provider/SecureRandom/AutoReseed.java test/sun/security/provider/SecureRandom/CommonSeeder.java test/sun/security/provider/SecureRandom/DRBGAlg.java test/sun/security/provider/SecureRandom/DrbgCavp.java test/sun/security/provider/SecureRandom/SelfSeed.java test/sun/security/provider/SecureRandom/StrongSeedReader.java
diffstat 30 files changed, 5029 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/com/sun/crypto/provider/HmacCore.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/HmacCore.java	Fri May 06 11:38:44 2016 +0800
@@ -262,4 +262,14 @@
             super("SHA-512", 128);
         }
     }
+    public static final class HmacSHA512_224 extends HmacCore {
+        public HmacSHA512_224() throws NoSuchAlgorithmException {
+            super("SHA-512/224", 128);
+        }
+    }
+    public static final class HmacSHA512_256 extends HmacCore {
+        public HmacSHA512_256() throws NoSuchAlgorithmException {
+            super("SHA-512/256", 128);
+        }
+    }
 }
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Fri May 06 11:38:44 2016 +0800
@@ -704,6 +704,12 @@
                     put("Alg.Alias.Mac.OID.1.2.840.113549.2.11", "HmacSHA512");
                     put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
 
+                    // TODO: aliases with OIDs
+                    put("Mac.HmacSHA512/224",
+                            "com.sun.crypto.provider.HmacCore$HmacSHA512_224");
+                    put("Mac.HmacSHA512/256",
+                            "com.sun.crypto.provider.HmacCore$HmacSHA512_256");
+
                     put("Mac.HmacPBESHA1",
                         "com.sun.crypto.provider.HmacPKCS12PBESHA1");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/security/DrbgParameters.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,543 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 java.security;
+
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * This class specifies the parameters used by a DRBG (Deterministic
+ * Random Bit Generator).
+ * <p>
+ * According to
+ * <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">
+ * NIST Special Publication 800-90A Revision 1, Recommendation for Random
+ * Number Generation Using Deterministic Random Bit Generators</a> (800-90Ar1),
+ * <blockquote>
+ * A DRBG is based on a DRBG mechanism as specified in this Recommendation
+ * and includes a source of randomness. A DRBG mechanism uses an algorithm
+ * (i.e., a DRBG algorithm) that produces a sequence of bits from an initial
+ * value that is determined by a seed that is determined from the output of
+ * the randomness source."
+ * </blockquote>
+ * <p>
+ * The 800-90Ar1 specification allows for a variety of DRBG implementation
+ * choices, such as:
+ * <ul>
+ * <li> an entropy source,
+ * <li> a DRBG mechanism (for example, Hash_DRBG),
+ * <li> a DRBG algorithm (for example, SHA-256 for Hash_DRBG and AES-256
+ * for CTR_DRBG. Please note that it is not the algorithm used in
+ * {@link SecureRandom#getInstance}, which we will call a
+ * <em>SecureRandom algorithm</em> below),
+ * <li> optionally features, including prediction resistance
+ * and reseeding supports.
+ * <li> highest security strength.
+ * </ul>
+ * <p>
+ * These choices are set in each implementation and are not directly
+ * managed by the {@code SecureRandom} API.  Check your DRBG provider's
+ * documentation to find an appropriate implementation for the situation.
+ * <p>
+ * On the other hand, the 800-90Ar1 specification does have some configurable
+ * options, such as:
+ * <ul>
+ * <li> required security strength,
+ * <li> if prediction resistance is required,
+ * <li> personalization string and additional input.
+ * </ul>
+ * <p>
+ * A DRBG instance can be instantiated with parameters from an
+ * {@link DrbgParameters.Instantiation} object and other information
+ * (for example, the nonce, which is not managed by this API). This maps
+ * to the {@code Instantiate_function} defined in NIST SP 800-90Ar1.
+ * <p>
+ * A DRBG instance can be reseeded with parameters from a
+ * {@link DrbgParameters.Reseed} object. This maps to the
+ * {@code Reseed_function} defined in NIST SP 800-90Ar1. Calling
+ * {@link SecureRandom#reseed()} is equivalent to calling
+ * {@link SecureRandom#reseed(SecureRandomParameters)} with the effective
+ * instantiated prediction resistance flag (as returned by
+ * {@link SecureRandom#getParameters()}) with no additional input.
+ * <p>
+ * A DRBG instance generates data with additional parameters from a
+ * {@link DrbgParameters.NextBytes} object. This maps to the
+ * {@code Generate_function} defined in NIST SP 800-90Ar1. Calling
+ * {@link SecureRandom#nextBytes(byte[])} is equivalent to calling
+ * {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)}
+ * with the effective instantiated strength and prediction resistance flag
+ * (as returned by {@link SecureRandom#getParameters()}) with no
+ * additional input.
+ * <p>
+ * A DRBG should be implemented as a subclass of {@link SecureRandomSpi}.
+ * It is recommended that the implementation contain the 1-arg
+ * {@linkplain SecureRandomSpi#SecureRandomSpi(SecureRandomParameters) constructor}
+ * that takes a {@code DrbgParameters.Instantiation} argument. If implemented
+ * this way, this implementation can be chosen by any
+ * {@code SecureRandom.getInstance()} method. If it is chosen by a
+ * {@code SecureRandom.getInstance()} with a {@link SecureRandomParameters}
+ * parameter, the parameter is passed into this constructor. If it is chosen
+ * by a {@code SecureRandom.getInstance()} without a
+ * {@code SecureRandomParameters} parameter, the constructor is called with
+ * a {@code null} argument and the implementation should choose its own
+ * parameters. Its {@link SecureRandom#getParameters()} must always return a
+ * non-null effective {@code DrbgParameters.Instantiation} object that reflects
+ * how the DRBG is actually instantiated. A caller can use this information
+ * to determine whether a {@code SecureRandom} object is a DRBG and what
+ * features it supports. Please note that the returned value does not
+ * necessarily equal to the {@code DrbgParameters.Instantiation} object passed
+ * into the {@code SecureRandom.getInstance()} call. For example,
+ * the requested capability can be {@link DrbgParameters.Capability#NONE}
+ * but the effective value can be {@link DrbgParameters.Capability#RESEED_ONLY}
+ * if the implementation supports reseeding. The implementation must implement
+ * the {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)}
+ * method which takes a {@code DrbgParameters.NextBytes} parameter. Unless
+ * the result of {@link SecureRandom#getParameters()} has its
+ * {@linkplain DrbgParameters.Instantiation#getCapability() capability} being
+ * {@link Capability#NONE NONE}, it must implement
+ * {@link SecureRandomSpi#engineReseed(SecureRandomParameters)} which takes
+ * a {@code DrbgParameters.Reseed} parameter.
+ * <p>
+ * On the other hand, if a DRBG implementation does not contain a constructor
+ * that has an {@code DrbgParameters.Instantiation} argument (not recommended),
+ * it can only be chosen by a {@code SecureRandom.getInstance()} without
+ * a {@code SecureRandomParameters} parameter, but will not be chosen if
+ * a {@code getInstance} method with a {@code SecureRandomParameters} parameter
+ * is called. If implemented this way, its {@link SecureRandom#getParameters()}
+ * must return {@code null}, and it does not need to implement either
+ * {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)}
+ * or {@link SecureRandomSpi#engineReseed(SecureRandomParameters)}.
+ * <p>
+ * A DRBG might reseed itself automatically if the seed period is bigger
+ * than the maximum seed life defined by the DRBG mechanism.
+ * <p>
+ * A DRBG implementation should support serialization and deserialization
+ * by retaining the configuration and effective parameters, but the internal
+ * state must not be serialized and the deserialized object must be
+ * reinstantiated.
+ * <p>
+ * Examples:
+ * <blockquote><pre>
+ * SecureRandom drbg;
+ * byte[] buffer = new byte[32];
+ *
+ * // Any DRBG is OK
+ * drbg = SecureRandom.getInstance("DRBG");
+ * drbg.nextBytes(buffer);
+ *
+ * SecureRandomParameters params = drbg.getParameters();
+ * if (params instanceof DrbgParameters.Instantiation) {
+ *     DrbgParameters.Instantiation ins = (DrbgParameters.Instantiation) params;
+ *     if (ins.getCapability().supportsReseeding()) {
+ *         drbg.reseed();
+ *     }
+ * }
+ *
+ * // The following call requests a weak DRBG instance. It is only
+ * // guaranteed to support 112 bits of security strength.
+ * drbg = SecureRandom.getInstance("DRBG",
+ *         DrbgParameters.instantiation(112, NONE, null));
+ *
+ * // Both the next two calls will likely fail, because drbg could be
+ * // instantiated with a smaller strength with no prediction resistance
+ * // support.
+ * drbg.nextBytes(buffer,
+ *         DrbgParameters.nextBytes(256, false, "more".getBytes()));
+ * drbg.nextBytes(buffer,
+ *         DrbgParameters.nextBytes(112, true, "more".getBytes()));
+ *
+ * // The following call requests a strong DRBG instance, with a
+ * // personalization string. If it successfully returns an instance,
+ * // that instance is guaranteed to support 256 bits of security strength
+ * // with prediction resistance available.
+ * drbg = SecureRandom.getInstance("DRBG", DrbgParameters.instantiation(
+ *         256, PR_AND_RESEED, "hello".getBytes()));
+ *
+ * // Prediction resistance is not requested in this single call,
+ * // but an additional input is used.
+ * drbg.nextBytes(buffer,
+ *         DrbgParameters.nextBytes(-1, false, "more".getBytes()));
+ *
+ * // Same for this call.
+ * drbg.reseed(DrbgParameters.reseed(false, "extra".getBytes()));</pre>
+ * </blockquote>
+ *
+ * @implSpec
+ * By convention, a provider should name its primary DRBG implementation
+ * with the <a href=
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
+ * standard {@code SecureRandom} algorithm name</a> "DRBG".
+ *
+ * @implNote
+ * The following notes apply to the "DRBG" implementation in the SUN provider
+ * of the JDK reference implementation.
+ * <p>
+ * This implementation supports the Hash_DRBG and HMAC_DRBG mechanisms with
+ * DRBG algorithm SHA-1, SHA-224, SHA-512/224, SHA-256, SHA-512/256,
+ * SHA-384 and SHA-512, and CTR_DRBG (both using derivation function and
+ * not using derivation function) with DRBG algorithm 3KeyTDEA
+ * (also known as DESede in JCE), AES-128, AES-192 and AES-256.
+ * <p>
+ * The mechanism name and DRBG algorithm name are determined by the
+ * {@linkplain Security#getProperty(String) security property}
+ * {@code securerandom.drbg.config}. The default choice is Hash_DRBG
+ * with SHA-256.
+ * <p>
+ * For each combination, the security strength can be requested from 112
+ * up to the highest strength it supports. Both reseeding and prediction
+ * resistance are supported.
+ * <p>
+ * Personalization string is supported through the
+ * {@link DrbgParameters.Instantiation} class and additional input is supported
+ * through the {@link DrbgParameters.NextBytes} and
+ * {@link DrbgParameters.Reseed} classes.
+ * <p>
+ * If a DRBG is not instantiated with a {@link DrbgParameters.Instantiation}
+ * object explicitly, this implementation instantiates it with a default
+ * requested strength of 128 bits (112 bits for CTR_DRBG with 3KeyTDEA),
+ * no prediction resistance request, and no personalization string.
+ * These default instantiation parameters can also be customized with
+ * the {@code securerandom.drbg.config} security property.
+ * <p>
+ * This implementation reads fresh entropy from the system default entropy
+ * source determined by the security property {@code securerandom.source}.
+ * <p>
+ * Calling {@link SecureRandom#generateSeed(int)} will directly read
+ * from this system default entropy source.
+ * <p>
+ * This implementation has passed all tests included in the 20151104 version of
+ * <a href="http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip">
+ * The DRBG Test Vectors</a>.
+ *
+ * @since 9
+ */
+public class DrbgParameters {
+
+    private DrbgParameters() {
+        // This class should not be instantiated
+    }
+
+    /**
+     * The reseedable and prediction resistance capabilities of a DRBG.
+     * <p>
+     * When this object is passed to a {@code SecureRandom.getInstance()} call,
+     * it is the requested minimum capability. When it's returned from
+     * {@code SecureRandom.getParameters()}, it is the effective capability.
+     * <p>
+     * Please note that while the {@code Instantiate_function} defined in
+     * NIST SP 800-90Ar1 only includes a {@code prediction_resistance_flag}
+     * parameter, the {@code Capability} type includes an extra value
+     * {@link #RESEED_ONLY} because reseeding is an optional function.
+     * If {@code NONE} is used in an {@code Instantiation} object in calling the
+     * {@code SecureRandom.getInstance} method, the returned DRBG instance
+     * is not guaranteed to support reseeding. If {@code RESEED_ONLY} or
+     * {@code PR_AND_RESEED} is used, the instance must support reseeding.
+     * <p>
+     * The table below lists possible effective values if a certain
+     * capability is requested, i.e.
+     * <blockquote><pre>
+     * Capability requested = ...;
+     * SecureRandom s = SecureRandom.getInstance("DRBG",
+     *         DrbgParameters(-1, requested, null));
+     * Capability effective = ((DrbgParametes.Initiate) s.getParameters())
+     *         .getCapability();</pre>
+     * </blockquote>
+     * <table border=1 summary="requested and effective capabilities">
+     * <tr>
+     * <th>Requested Value</th>
+     * <th>Possible Effective Values</th>
+     * </tr>
+     * <tr><td>NONE</td><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
+     * <tr><td>RESEED_ONLY</td><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
+     * <tr><td>PR_AND_RESEED</td><td>PR_AND_RESEED</td></tr>
+     * </table>
+     * <p>
+     * A DRBG implementation supporting prediction resistance must also
+     * support reseeding.
+     *
+     * @since 9
+     */
+    public enum Capability {
+
+        /**
+         * Both prediction resistance and reseed.
+         */
+        PR_AND_RESEED,
+
+        /**
+         * Reseed but no prediction resistance.
+         */
+        RESEED_ONLY,
+
+        /**
+         * Neither prediction resistance nor reseed.
+         */
+        NONE;
+
+        @Override
+        public String toString() {
+            return name().toLowerCase(Locale.ROOT);
+        }
+
+        /**
+         * Returns whether this capability supports reseeding.
+         *
+         * @return {@code true} for {@link #PR_AND_RESEED} and
+         *      {@link #RESEED_ONLY}, and {@code false} for {@link #NONE}
+         */
+        public boolean supportsReseeding() {
+            return this != NONE;
+        }
+
+        /**
+         * Returns whether this capability supports prediction resistance.
+         *
+         * @return {@code true} for {@link #PR_AND_RESEED}, and {@code false}
+         *      for {@link #RESEED_ONLY} and {@link #NONE}
+         */
+        public boolean supportsPredictionResistance() {
+            return this == PR_AND_RESEED;
+        }
+    }
+
+    /**
+     * DRBG parameters for instantiation.
+     * <p>
+     * When used in
+     * {@link SecureRandom#getInstance(String, SecureRandomParameters)}
+     * or one of the other similar {@code getInstance} calls that take a
+     * {@code SecureRandomParameters} parameter, it means the
+     * requested instantiate parameters the newly created {@code SecureRandom}
+     * object must minimally support. When used as the return value of the
+     * {@link SecureRandom#getParameters()} method, it means the effective
+     * instantiate parameters of the {@code SecureRandom} object.
+     *
+     * @since 9
+     */
+    public static final class Instantiation
+            implements SecureRandomParameters {
+
+        private final int strength;
+        private final Capability capability;
+        private final byte[] personalizationString;
+
+        /**
+         * Returns the security strength in bits.
+         *
+         * @return If used in {@code getInstance}, returns the minimum strength
+         * requested, or -1 if there is no specific request on the strength.
+         * If used in {@code getParameters}, returns the effective strength.
+         * The effective strength must be greater than or equal to the minimum
+         * strength requested.
+         */
+        public int getStrength() {
+            return strength;
+        }
+
+        /**
+         * Returns the capability.
+         *
+         * @return If used in {@code getInstance}, returns the minimum
+         * capability requested. If used in {@code getParameters}, returns
+         * information on the effective prediction resistance flag and
+         * whether it supports reseeding.
+         */
+        public Capability getCapability() {
+            return capability;
+        }
+
+        /**
+         * Returns the personalization string as a byte array.
+         *
+         * @return If used in {@code getInstance}, returns the requested
+         * personalization string as a newly allocated array, or {@code null}
+         * if no personalization string is requested. The same string should
+         * be returned in {@code getParameters} as a new copy, or {@code null}
+         * if no personalization string is requested in {@code getInstance}.
+         */
+        public byte[] getPersonalizationString() {
+            return (personalizationString == null) ?
+                    null : personalizationString.clone();
+        }
+
+        private Instantiation(int strength, Capability capability,
+                              byte[] personalizationString) {
+            this.strength = strength;
+            this.capability = capability;
+            this.personalizationString = (personalizationString == null) ?
+                    null : personalizationString.clone();
+        }
+
+        /**
+         * Returns a Human-readable string representation of this
+         * {@code Instantiation}.
+         *
+         * @return the string representation
+         */
+        @Override
+        public String toString() {
+            // I don't care what personalizationString looks like
+            return strength + "," + capability + "," + personalizationString;
+        }
+    }
+
+    /**
+     * DRBG parameters for random bits generation. It is used in
+     * {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)}.
+     *
+     * @since 9
+     */
+    public static final class NextBytes
+            implements SecureRandomParameters {
+        private final int strength;
+        private final boolean predictionResistance;
+        private final byte[] additionalInput;
+
+        /**
+         * Returns the security strength requested in bits.
+         *
+         * @return the strength requested, or -1 if the effective strength
+         *      should be used.
+         */
+        public int getStrength() {
+            return strength;
+        }
+
+        /**
+         * Returns whether prediction resistance is requested.
+         *
+         * @return whether prediction resistance is requested
+         */
+        public boolean getPredictionResistance() {
+            return predictionResistance;
+        }
+
+        /**
+         * Returns the requested additional input.
+         *
+         * @return the requested additional input, {@code null} if not
+         * requested. A new byte array is returned each time this method
+         * is called.
+         */
+        public byte[] getAdditionalInput() {
+            return additionalInput == null? null: additionalInput.clone();
+        }
+
+        private NextBytes(int strength, boolean predictionResistance,
+                          byte[] additionalInput) {
+            this.strength = strength;
+            this.predictionResistance = predictionResistance;
+            this.additionalInput = (additionalInput == null) ?
+                    null : additionalInput.clone();
+        }
+    }
+
+    /**
+     * DRBG parameters for reseed. It is used in
+     * {@link SecureRandom#reseed(SecureRandomParameters)}.
+     *
+     * @since 9
+     */
+    public static final class Reseed implements SecureRandomParameters {
+
+        private final byte[] additionalInput;
+        private final boolean predictionResistance;
+
+        /**
+         * Returns whether prediction resistance is requested.
+         *
+         * @return whether prediction resistance is requested
+         */
+        public boolean getPredictionResistance() {
+            return predictionResistance;
+        }
+
+        /**
+         * Returns the requested additional input.
+         *
+         * @return the requested additional input, or {@code null} if
+         * not requested. A new byte array is returned each time this method
+         * is called.
+         */
+        public byte[] getAdditionalInput() {
+            return additionalInput == null ? null : additionalInput.clone();
+        }
+
+        private Reseed(boolean predictionResistance, byte[] additionalInput) {
+            this.predictionResistance = predictionResistance;
+            this.additionalInput = (additionalInput == null) ?
+                    null : additionalInput.clone();
+        }
+    }
+
+    /**
+     * Generates a {@link DrbgParameters.Instantiation} object.
+     *
+     * @param strength security strength in bits, -1 for default strength
+     *                 if used in {@code getInstance}.
+     * @param capability capability
+     * @param personalizationString personalization string as a byte array,
+     *                              can be {@code null}. The content of this
+     *                              byte array will be copied.
+     * @return a new {@code Instantiation} object
+     * @throws NullPointerException if {@code capability} is {@code null}
+     */
+    public static Instantiation instantiation(int strength,
+                                              Capability capability,
+                                              byte[] personalizationString) {
+        return new Instantiation(strength, Objects.requireNonNull(capability),
+                personalizationString);
+    }
+
+    /**
+     * Generates a {@link NextBytes} object.
+     *
+     * @param strength requested security strength in bits. If set to -1, the
+     *                 effective strength will be used.
+     * @param predictionResistance prediction resistance requested
+     * @param additionalInput additional input, can be {@code null}.
+     *                        The content of this byte array will be copied.
+     * @return a new {@code NextBytes} object
+     */
+    public static NextBytes nextBytes(int strength,
+                                      boolean predictionResistance,
+                                      byte[] additionalInput) {
+        return new NextBytes(strength, predictionResistance, additionalInput);
+    }
+
+    /**
+     * Generates a {@link Reseed} object.
+     *
+     * @param predictionResistance prediction resistance requested
+     * @param additionalInput additional input, can be {@code null}.
+     *                        The content of this byte array will be copied.
+     * @return a new {@code Reseed} object
+     */
+    public static Reseed reseed(
+            boolean predictionResistance, byte[] additionalInput) {
+        return new Reseed(predictionResistance, additionalInput);
+    }
+}
--- a/src/java.base/share/classes/java/security/Provider.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/java/security/Provider.java	Fri May 06 11:38:44 2016 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved
+ * Copyright (c) 1996, 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
@@ -142,8 +142,35 @@
             Constructor<?> con = clazz.getConstructor();
             return con.newInstance();
         } else {
-            Constructor<?> con = clazz.getConstructor(ctrParamClz);
-            return con.newInstance(ctorParamObj);
+            // Looking for the constructor with a params first and fallback
+            // to one without if not found. This is to support the enhanced
+            // SecureRandom where both styles of constructors are supported.
+            // Before jdk9, there was no params support (only getInstance(alg))
+            // and an impl only had the params-less constructor. Since jdk9,
+            // there is getInstance(alg,params) and an impl can contain
+            // an Impl(params) constructor.
+            try {
+                Constructor<?> con = clazz.getConstructor(ctrParamClz);
+                return con.newInstance(ctorParamObj);
+            } catch (NoSuchMethodException nsme) {
+                // For pre-jdk9 SecureRandom implementations, they only
+                // have params-less constructors which still works when
+                // the input ctorParamObj is null.
+                //
+                // For other primitives using params, ctorParamObj should not
+                // be null and nsme is thrown, just like before.
+                if (ctorParamObj == null) {
+                    try {
+                        Constructor<?> con = clazz.getConstructor();
+                        return con.newInstance();
+                    } catch (NoSuchMethodException nsme2) {
+                        nsme.addSuppressed(nsme2);
+                        throw nsme;
+                    }
+                } else {
+                    throw nsme;
+                }
+            }
         }
     }
 
@@ -1384,7 +1411,8 @@
         addEngine("KeyPairGenerator",                   false, null);
         addEngine("KeyStore",                           false, null);
         addEngine("MessageDigest",                      false, null);
-        addEngine("SecureRandom",                       false, null);
+        addEngine("SecureRandom",                       false,
+                "java.security.SecureRandomParameters");
         addEngine("Signature",                          true,  null);
         addEngine("CertificateFactory",                 false, null);
         addEngine("CertPathBuilder",                    false, null);
@@ -1678,6 +1706,7 @@
                         }
                     }
                 }
+                // constructorParameter can be null if not provided
                 return newInstanceUtil(getImplClass(), ctrParamClz, constructorParameter);
             } catch (NoSuchAlgorithmException e) {
                 throw e;
--- a/src/java.base/share/classes/java/security/SecureRandom.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/java/security/SecureRandom.java	Fri May 06 11:38:44 2016 +0800
@@ -38,52 +38,87 @@
  * This class provides a cryptographically strong random number
  * generator (RNG).
  *
- * <p>A cryptographically strong random number
- * minimally complies with the statistical random number generator tests
- * specified in
+ * <p>A cryptographically strong random number minimally complies with the
+ * statistical random number generator tests specified in
  * <a href="http://csrc.nist.gov/publications/fips/fips140-2/fips1402.pdf">
  * <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>,
  * section 4.9.1.
- * Additionally, SecureRandom must produce non-deterministic output.
- * Therefore any seed material passed to a SecureRandom object must be
- * unpredictable, and all SecureRandom output sequences must be
+ * Additionally, {@code SecureRandom} must produce non-deterministic output.
+ * Therefore any seed material passed to a {@code SecureRandom} object must be
+ * unpredictable, and all {@code SecureRandom} output sequences must be
  * cryptographically strong, as described in
  * <a href="http://tools.ietf.org/html/rfc4086">
  * <i>RFC 4086: Randomness Requirements for Security</i></a>.
  *
- * <p>A caller obtains a SecureRandom instance via the
- * no-argument constructor or one of the {@code getInstance} methods:
- *
- * <pre>
- *      SecureRandom random = new SecureRandom();
- * </pre>
- *
- * <p> Many SecureRandom implementations are in the form of a pseudo-random
- * number generator (PRNG), which means they use a deterministic algorithm
- * to produce a pseudo-random sequence from a true random seed.
+ * <p> Many {@code SecureRandom} implementations are in the form of a
+ * pseudo-random number generator (PRNG, also known as deterministic random
+ * bits generator or DRBG), which means they use a deterministic algorithm
+ * to produce a pseudo-random sequence from a random seed.
  * Other implementations may produce true random numbers,
  * and yet others may use a combination of both techniques.
  *
- * <p> Typical callers of SecureRandom invoke the following methods
+ * <p>A caller obtains a {@code SecureRandom} instance via the
+ * no-argument constructor or one of the {@code getInstance} methods.
+ * For example:
+ *
+ * <blockquote><pre>
+ * SecureRandom r1 = new SecureRandom();
+ * SecureRandom r2 = SecureRandom.getInstance("NativePRNG");
+ * SecureRandom r3 = SecureRandom("DRBG",
+ *         DrbgParameters.Instantiation(128, RESEED_ONLY, null));</pre>
+ * </blockquote>
+ *
+ * <p> The third statement above returns a {@code SecureRandom} object of the
+ * specific algorithm supporting the specific instantiate parameters. The
+ * implementation's effective instantiated parameters must match this minimum
+ * request but is not necessarily the same. For example, even if the request
+ * does not require a certain feature, the actual instantiation can provide
+ * the feature. An implementation may lazily instantiate a {@code SecureRandom}
+ * until it's actually used, but the effective instantiate parameters must be
+ * determined right after it's created and {@link #getParameters()} should
+ * always return the same result unchanged.
+ *
+ * <p> Typical callers of {@code SecureRandom} invoke the following methods
  * to retrieve random bytes:
  *
- * <pre>
- *      SecureRandom random = new SecureRandom();
- *      byte[] bytes = new byte[20];
- *      random.nextBytes(bytes);
- * </pre>
+ * <blockquote><pre>
+ * SecureRandom random = new SecureRandom();
+ * byte[] bytes = new byte[20];
+ * random.nextBytes(bytes);</pre>
+ * </blockquote>
  *
- * <p> Callers may also invoke the {@code generateSeed} method
+ * <p> Callers may also invoke the {@link #generateSeed} method
  * to generate a given number of seed bytes (to seed other random number
  * generators, for example):
- * <pre>
- *      byte[] seed = random.generateSeed(20);
- * </pre>
  *
- * Note: Depending on the implementation, the {@code generateSeed} and
- * {@code nextBytes} methods may block as entropy is being gathered,
- * for example, if they need to read from /dev/random on various Unix-like
- * operating systems.
+ * <blockquote><pre>
+ * byte[] seed = random.generateSeed(20);</pre>
+ * </blockquote>
+ *
+ * <p> A newly created PRNG {@code SecureRandom} object is not seeded (except
+ * if it is created by {@link #SecureRandom(byte[])}). The first call to
+ * {@code nextBytes} will force it to seed itself from an implementation-
+ * specific entropy source. This self-seeding will not occur if {@code setSeed}
+ * was previously called.
+ *
+ * <p> A {@code SecureRandom} can be reseeded at any time by calling the
+ * {@code reseed} or {@code setSeed} method. The {@code reseed} method
+ * reads entropy input from its entropy source to reseed itself.
+ * The {@code setSeed} method requires the caller to provide the seed.
+ *
+ * <p> Please note that {@code reseed} may not be supported by all
+ * {@code SecureRandom} implementations.
+ *
+ * <p> Some {@code SecureRandom} implementations may accept a
+ * {@link SecureRandomParameters} parameter in its
+ * {@link #nextBytes(byte[], SecureRandomParameters)} and
+ * {@link #reseed(SecureRandomParameters)} methods to further
+ * control the behavior of the methods.
+ *
+ * <p> Note: Depending on the implementation, the {@code generateSeed},
+ * {@code reseed} and {@code nextBytes} methods may block as entropy is being
+ * gathered, for example, if the entropy source is /dev/random on various
+ * Unix-like operating systems.
  *
  * @see java.security.SecureRandomSpi
  * @see java.util.Random
@@ -132,26 +167,19 @@
      *
      * <p> This constructor traverses the list of registered security Providers,
      * starting with the most preferred Provider.
-     * A new SecureRandom object encapsulating the
-     * SecureRandomSpi implementation from the first
-     * Provider that supports a SecureRandom (RNG) algorithm is returned.
+     * A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the first
+     * Provider that supports a {@code SecureRandom} (RNG) algorithm is returned.
      * If none of the Providers support a RNG algorithm,
      * then an implementation-specific default is returned.
      *
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
-     * <p> See the SecureRandom section in the <a href=
+     * <p> See the {@code SecureRandom} section in the <a href=
      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
-     *
-     * <p> The returned SecureRandom object has not been seeded.  To seed the
-     * returned object, call the {@code setSeed} method.
-     * If {@code setSeed} is not called, the first call to
-     * {@code nextBytes} will force the SecureRandom object to seed itself.
-     * This self-seeding will not occur if {@code setSeed} was
-     * previously called.
      */
     public SecureRandom() {
         /*
@@ -166,20 +194,20 @@
     /**
      * Constructs a secure random number generator (RNG) implementing the
      * default random number algorithm.
-     * The SecureRandom instance is seeded with the specified seed bytes.
+     * The {@code SecureRandom} instance is seeded with the specified seed bytes.
      *
      * <p> This constructor traverses the list of registered security Providers,
      * starting with the most preferred Provider.
-     * A new SecureRandom object encapsulating the
-     * SecureRandomSpi implementation from the first
-     * Provider that supports a SecureRandom (RNG) algorithm is returned.
+     * A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the first
+     * Provider that supports a {@code SecureRandom} (RNG) algorithm is returned.
      * If none of the Providers support a RNG algorithm,
      * then an implementation-specific default is returned.
      *
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
-     * <p> See the SecureRandom section in the <a href=
+     * <p> See the {@code SecureRandom} section in the <a href=
      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
@@ -225,9 +253,9 @@
     }
 
     /**
-     * Creates a SecureRandom object.
+     * Creates a {@code SecureRandom} object.
      *
-     * @param secureRandomSpi the SecureRandom implementation.
+     * @param secureRandomSpi the {@code SecureRandom} implementation.
      * @param provider the provider.
      */
     protected SecureRandom(SecureRandomSpi secureRandomSpi,
@@ -249,25 +277,18 @@
     }
 
     /**
-     * Returns a SecureRandom object that implements the specified
+     * Returns a {@code SecureRandom} object that implements the specified
      * Random Number Generator (RNG) algorithm.
      *
      * <p> This method traverses the list of registered security Providers,
      * starting with the most preferred Provider.
-     * A new SecureRandom object encapsulating the
-     * SecureRandomSpi implementation from the first
+     * A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the first
      * Provider that supports the specified algorithm is returned.
      *
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
-     * <p> The returned SecureRandom object has not been seeded.  To seed the
-     * returned object, call the {@code setSeed} method.
-     * If {@code setSeed} is not called, the first call to
-     * {@code nextBytes} will force the SecureRandom object to seed itself.
-     * This self-seeding will not occur if {@code setSeed} was
-     * previously called.
-     *
      * @implNote
      * The JDK Reference Implementation additionally uses the
      * {@code jdk.security.provider.preferred}
@@ -277,15 +298,15 @@
      * {@link Security#getProviders() Security.getProviders()}.
      *
      * @param algorithm the name of the RNG algorithm.
-     * See the SecureRandom section in the <a href=
+     * See the {@code SecureRandom} section in the <a href=
      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
-     * @return the new SecureRandom object.
+     * @return the new {@code SecureRandom} object.
      *
      * @exception NoSuchAlgorithmException if no Provider supports a
-     *          SecureRandomSpi implementation for the
+     *          {@code SecureRandomSpi} implementation for the
      *          specified algorithm.
      *
      * @see Provider
@@ -295,49 +316,42 @@
     public static SecureRandom getInstance(String algorithm)
             throws NoSuchAlgorithmException {
         Instance instance = GetInstance.getInstance("SecureRandom",
-            SecureRandomSpi.class, algorithm);
+                SecureRandomSpi.class, algorithm);
         return new SecureRandom((SecureRandomSpi)instance.impl,
-            instance.provider, algorithm);
+                instance.provider, algorithm);
     }
 
     /**
-     * Returns a SecureRandom object that implements the specified
+     * Returns a {@code SecureRandom} object that implements the specified
      * Random Number Generator (RNG) algorithm.
      *
-     * <p> A new SecureRandom object encapsulating the
-     * SecureRandomSpi implementation from the specified provider
+     * <p> A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the specified provider
      * is returned.  The specified provider must be registered
      * in the security provider list.
      *
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
-     * <p> The returned SecureRandom object has not been seeded.  To seed the
-     * returned object, call the {@code setSeed} method.
-     * If {@code setSeed} is not called, the first call to
-     * {@code nextBytes} will force the SecureRandom object to seed itself.
-     * This self-seeding will not occur if {@code setSeed} was
-     * previously called.
-     *
      * @param algorithm the name of the RNG algorithm.
-     * See the SecureRandom section in the <a href=
+     * See the {@code SecureRandom} section in the <a href=
      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
      * @param provider the name of the provider.
      *
-     * @return the new SecureRandom object.
+     * @return the new {@code SecureRandom} object.
      *
-     * @exception NoSuchAlgorithmException if a SecureRandomSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws NoSuchAlgorithmException if a {@code SecureRandomSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider.
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list.
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws IllegalArgumentException if the provider name is null
+     *         or empty.
      *
      * @see Provider
      *
@@ -352,36 +366,29 @@
     }
 
     /**
-     * Returns a SecureRandom object that implements the specified
+     * Returns a {@code SecureRandom} object that implements the specified
      * Random Number Generator (RNG) algorithm.
      *
-     * <p> A new SecureRandom object encapsulating the
-     * SecureRandomSpi implementation from the specified Provider
-     * object is returned.  Note that the specified Provider object
+     * <p> A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the specified {@code Provider}
+     * object is returned.  Note that the specified {@code Provider} object
      * does not have to be registered in the provider list.
      *
-     * <p> The returned SecureRandom object has not been seeded.  To seed the
-     * returned object, call the {@code setSeed} method.
-     * If {@code setSeed} is not called, the first call to
-     * {@code nextBytes} will force the SecureRandom object to seed itself.
-     * This self-seeding will not occur if {@code setSeed} was
-     * previously called.
-     *
      * @param algorithm the name of the RNG algorithm.
-     * See the SecureRandom section in the <a href=
+     * See the {@code SecureRandom} section in the <a href=
      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
      * @param provider the provider.
      *
-     * @return the new SecureRandom object.
+     * @return the new {@code SecureRandom} object.
      *
-     * @exception NoSuchAlgorithmException if a SecureRandomSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code SecureRandomSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object.
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws IllegalArgumentException if the specified provider is null.
      *
      * @see Provider
      *
@@ -396,24 +403,178 @@
     }
 
     /**
-     * Returns the SecureRandomSpi of this SecureRandom object.
+     * Returns a {@code SecureRandom} object that implements the specified
+     * Random Number Generator (RNG) algorithm and supports the specified
+     * {@code SecureRandomParameters} request.
+     *
+     * <p> This method traverses the list of registered security Providers,
+     * starting with the most preferred Provider.
+     * A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the first
+     * Provider that supports the specified algorithm and the specified
+     * {@code SecureRandomParameters} is returned.
+     *
+     * <p> Note that the list of registered providers may be retrieved via
+     * the {@link Security#getProviders() Security.getProviders()} method.
+     *
+     * @implNote
+     * The JDK Reference Implementation additionally uses the
+     * {@code jdk.security.provider.preferred} property to determine
+     * the preferred provider order for the specified algorithm. This
+     * may be different than the order of providers returned by
+     * {@link Security#getProviders() Security.getProviders()}.
+     *
+     * @param algorithm the name of the RNG algorithm.
+     * See the {@code SecureRandom} section in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
+     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * for information about standard RNG algorithm names.
+     *
+     * @param params the {@code SecureRandomParameters}
+     *               the newly created {@code SecureRandom} object must support.
+     *
+     * @return the new {@code SecureRandom} object.
+     *
+     * @throws NoSuchAlgorithmException if no Provider supports a
+     *         {@code SecureRandomSpi} implementation for the specified
+     *         algorithm and parameters.
+     *
+     * @throws IllegalArgumentException if the specified params is null.
+     *
+     * @see Provider
+     *
+     * @since 9
+     */
+    public static SecureRandom getInstance(
+            String algorithm, SecureRandomParameters params)
+            throws NoSuchAlgorithmException {
+        if (params == null) {
+            throw new IllegalArgumentException("params cannot be null");
+        }
+        Instance instance = GetInstance.getInstance("SecureRandom",
+                SecureRandomSpi.class, algorithm, params);
+        return new SecureRandom((SecureRandomSpi)instance.impl,
+                instance.provider, algorithm);
+    }
+
+    /**
+     * Returns a {@code SecureRandom} object that implements the specified
+     * Random Number Generator (RNG) algorithm and supports the specified
+     * {@code SecureRandomParameters} request.
+     *
+     * <p> A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the specified provider
+     * is returned.  The specified provider must be registered
+     * in the security provider list.
+     *
+     * <p> Note that the list of registered providers may be retrieved via
+     * the {@link Security#getProviders() Security.getProviders()} method.
+     *
+     * @param algorithm the name of the RNG algorithm.
+     * See the {@code SecureRandom} section in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
+     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * for information about standard RNG algorithm names.
+     *
+     * @param params the {@code SecureRandomParameters}
+     *               the newly created {@code SecureRandom} object must support.
+     *
+     * @param provider the name of the provider.
+     *
+     * @return the new {@code SecureRandom} object.
+     *
+     * @throws NoSuchAlgorithmException if the specified provider does not
+     *         support a {@code SecureRandomSpi} implementation for the
+     *         specified algorithm and parameters.
+     *
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list.
+     *
+     * @throws IllegalArgumentException if the provider name is null
+     *         or empty, or params is null.
+     *
+     * @see Provider
+     *
+     * @since 9
+     */
+    public static SecureRandom getInstance(String algorithm,
+            SecureRandomParameters params, String provider)
+            throws NoSuchAlgorithmException, NoSuchProviderException {
+        if (params == null) {
+            throw new IllegalArgumentException("params cannot be null");
+        }
+        Instance instance = GetInstance.getInstance("SecureRandom",
+                SecureRandomSpi.class, algorithm, params, provider);
+        return new SecureRandom((SecureRandomSpi)instance.impl,
+                instance.provider, algorithm);
+    }
+
+    /**
+     * Returns a {@code SecureRandom} object that implements the specified
+     * Random Number Generator (RNG) algorithm and supports the specified
+     * {@code SecureRandomParameters} request.
+     *
+     * <p> A new {@code SecureRandom} object encapsulating the
+     * {@code SecureRandomSpi} implementation from the specified
+     * {@code Provider} object is returned.  Note that the specified
+     * {@code Provider} object does not have to be registered in the
+     * provider list.
+     *
+     * @param algorithm the name of the RNG algorithm.
+     * See the {@code SecureRandom} section in the <a href=
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
+     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * for information about standard RNG algorithm names.
+     *
+     * @param params the {@code SecureRandomParameters}
+     *               the newly created {@code SecureRandom} object must support.
+     *
+     * @param provider the provider.
+     *
+     * @return the new {@code SecureRandom} object.
+     *
+     * @throws NoSuchAlgorithmException if the specified provider does not
+     *         support a {@code SecureRandomSpi} implementation for the
+     *         specified algorithm and parameters.
+     *
+     * @throws IllegalArgumentException if the specified provider or params
+     *         is null.
+     *
+     * @see Provider
+     *
+     * @since 9
+     */
+    public static SecureRandom getInstance(String algorithm,
+            SecureRandomParameters params, Provider provider)
+            throws NoSuchAlgorithmException {
+        if (params == null) {
+            throw new IllegalArgumentException("params cannot be null");
+        }
+        Instance instance = GetInstance.getInstance("SecureRandom",
+                SecureRandomSpi.class, algorithm, params, provider);
+        return new SecureRandom((SecureRandomSpi)instance.impl,
+                instance.provider, algorithm);
+    }
+
+    /**
+     * Returns the {@code SecureRandomSpi} of this {@code SecureRandom} object.
      */
     SecureRandomSpi getSecureRandomSpi() {
         return secureRandomSpi;
     }
 
     /**
-     * Returns the provider of this SecureRandom object.
+     * Returns the provider of this {@code SecureRandom} object.
      *
-     * @return the provider of this SecureRandom object.
+     * @return the provider of this {@code SecureRandom} object.
      */
     public final Provider getProvider() {
         return provider;
     }
 
     /**
-     * Returns the name of the algorithm implemented by this SecureRandom
-     * object.
+     * Returns the name of the algorithm implemented by this
+     * {@code SecureRandom} object.
      *
      * @return the name of the algorithm or {@code unknown}
      *          if the algorithm name cannot be determined.
@@ -424,9 +585,49 @@
     }
 
     /**
-     * Reseeds this random object. The given seed supplements, rather than
-     * replaces, the existing seed. Thus, repeated calls are guaranteed
-     * never to reduce randomness.
+     * Returns a Human-readable string representation of this
+     * {@code SecureRandom}.
+     *
+     * @return the string representation
+     *
+     * @since 9
+     */
+    @Override
+    public String toString() {
+        return secureRandomSpi.toString();
+    }
+
+    /**
+     * Returns the effective {@link SecureRandomParameters} for this
+     * {@code SecureRandom} instance.
+     * <p>
+     * The returned value can be different from the
+     * {@code SecureRandomParameters} object passed into a {@code getInstance}
+     * method, but it cannot change during the lifetime of this
+     * {@code SecureRandom} object.
+     * <p>
+     * A caller can use the returned value to find out what features this
+     * {@code SecureRandom} supports.
+     *
+     * @return the effective {@link SecureRandomParameters} parameters,
+     * or {@code null} if no parameters were used.
+     *
+     * @since 9
+     * @see SecureRandomSpi
+     */
+    public SecureRandomParameters getParameters() {
+        return secureRandomSpi.engineGetParameters();
+    }
+
+    /**
+     * Reseeds this random object with the given seed. The seed supplements,
+     * rather than replaces, the existing seed. Thus, repeated calls are
+     * guaranteed never to reduce randomness.
+     * <p>
+     * A PRNG {@code SecureRandom} will not seed itself automatically if
+     * {@code setSeed} is called before any {@code nextBytes} or {@code reseed}
+     * calls. The caller should make sure that the {@code seed} argument
+     * contains enough entropy for the security of this {@code SecureRandom}.
      *
      * @param seed the seed.
      *
@@ -458,18 +659,13 @@
          * yet been initialized at that point.
          */
         if (seed != 0) {
-            secureRandomSpi.engineSetSeed(longToByteArray(seed));
+            this.secureRandomSpi.engineSetSeed(longToByteArray(seed));
         }
     }
 
     /**
      * Generates a user-specified number of random bytes.
      *
-     * <p> If a call to {@code setSeed} had not occurred previously,
-     * the first call to this method forces this SecureRandom object
-     * to seed itself.  This self-seeding will not occur if
-     * {@code setSeed} was previously called.
-     *
      * @param bytes the array to be filled in with random bytes.
      */
     @Override
@@ -478,6 +674,28 @@
     }
 
     /**
+     * Generates a user-specified number of random bytes with
+     * additional parameters.
+     *
+     * @param bytes the array to be filled in with random bytes
+     * @param params additional parameters
+     * @throws NullPointerException if {@code bytes} is null
+     * @throws UnsupportedOperationException if the underlying provider
+     *         implementation has not overridden this method
+     * @throws IllegalArgumentException if {@code params} is {@code null},
+     *         illegal or unsupported by this {@code SecureRandom}
+     *
+     * @since 9
+     */
+    public synchronized void nextBytes(
+            byte[] bytes, SecureRandomParameters params) {
+        if (params == null) {
+            throw new IllegalArgumentException("params cannot be null");
+        }
+        secureRandomSpi.engineNextBytes(Objects.requireNonNull(bytes), params);
+    }
+
+    /**
      * Generates an integer containing the user-specified number of
      * pseudo-random bits (right justified, with leading zeros).  This
      * method overrides a {@code java.util.Random} method, and serves
@@ -512,7 +730,7 @@
      *
      * <p>This method is only included for backwards compatibility.
      * The caller is encouraged to use one of the alternative
-     * {@code getInstance} methods to obtain a SecureRandom object, and
+     * {@code getInstance} methods to obtain a {@code SecureRandom} object, and
      * then call the {@code generateSeed} method to obtain seed bytes
      * from that object.
      *
@@ -537,10 +755,13 @@
      * call may be used to seed other random number generators.
      *
      * @param numBytes the number of seed bytes to generate.
-     *
+     * @throws IllegalArgumentException if {@code numBytes} is negative
      * @return the seed bytes.
      */
     public byte[] generateSeed(int numBytes) {
+        if (numBytes < 0) {
+            throw new IllegalArgumentException("numBytes cannot be negative");
+        }
         return secureRandomSpi.engineGenerateSeed(numBytes);
     }
 
@@ -562,8 +783,8 @@
     /**
      * Gets a default PRNG algorithm by looking through all registered
      * providers. Returns the first PRNG algorithm of the first provider that
-     * has registered a SecureRandom implementation, or null if none of the
-     * registered providers supplies a SecureRandom implementation.
+     * has registered a {@code SecureRandom} implementation, or null if none of
+     * the registered providers supplies a {@code SecureRandom} implementation.
      */
     private static String getPrngAlgorithm() {
         for (Provider p : Providers.getProviderList().providers()) {
@@ -667,6 +888,42 @@
             "No strong SecureRandom impls available: " + property);
     }
 
+    /**
+     * Reseeds this {@code SecureRandom} with entropy input read from its
+     * entropy source.
+     *
+     * @throws UnsupportedOperationException if the underlying provider
+     *         implementation has not overridden this method.
+     *
+     * @since 9
+     */
+    public synchronized void reseed() {
+        secureRandomSpi.engineReseed(null);
+    }
+
+    /**
+     * Reseeds this {@code SecureRandom} with entropy input read from its
+     * entropy source with additional parameters.
+     * <p>
+     * Note that entropy is obtained from an entropy source. While
+     * some data in {@code params} may contain entropy, its main usage is to
+     * provide diversity.
+     *
+     * @param params extra parameters
+     * @throws UnsupportedOperationException if the underlying provider
+     *         implementation has not overridden this method.
+     * @throws IllegalArgumentException if {@code params} is {@code null},
+     *         illegal or unsupported by this {@code SecureRandom}
+     *
+     * @since 9
+     */
+    public synchronized void reseed(SecureRandomParameters params) {
+        if (params == null) {
+            throw new IllegalArgumentException("params cannot be null");
+        }
+        secureRandomSpi.engineReseed(params);
+    }
+
     // Declare serialVersionUID to be compatible with JDK1.1
     static final long serialVersionUID = 4940670005562187L;
 
@@ -685,7 +942,7 @@
      * We know that the MessageDigest class does not implement
      * java.io.Serializable.  However, since this field is no longer
      * used, it will always be NULL and won't affect the serialization
-     * of the SecureRandom class itself.
+     * of the {@code SecureRandom} class itself.
      */
     private byte[] randomBytes;
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/security/SecureRandomParameters.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,38 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 java.security;
+
+/**
+ * A marker interface for parameters used in various {@code SecureRandom}
+ * methods.
+ * <p>
+ * Some {@code SecureRandom} implementations might require additional
+ * operational parameters. Objects of classes which implement this interface
+ * can be passed to those implementations that support them.
+ *
+ * @see DrbgParameters
+ */
+public interface SecureRandomParameters {
+}
--- a/src/java.base/share/classes/java/security/SecureRandomSpi.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/java/security/SecureRandomSpi.java	Fri May 06 11:38:44 2016 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -27,13 +27,38 @@
 
 /**
  * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
- * for the {@code SecureRandom} class.
+ * for the {@link SecureRandom} class.
+ * <p>
  * All the abstract methods in this class must be implemented by each
  * service provider who wishes to supply the implementation
  * of a cryptographically strong pseudo-random number generator.
  *
+ * @implSpec
+ * If the {@link #SecureRandomSpi(SecureRandomParameters)}
+ * constructor is overridden in an implementation, it will always be called
+ * whenever a {@code SecureRandom} is instantiated. Precisely, if an object is
+ * instantiated with one of {@code SecureRandom}'s {@code getInstance} methods
+ * <em>without</em> a {@link SecureRandomParameters} parameter,
+ * the constructor will be called with a {@code null} argument and the
+ * implementation is responsible for creating its own
+ * {@code SecureRandomParameters} parameter for use when
+ * {@link #engineGetParameters()} is called. If an object
+ * is instantiated with one of {@code SecureRandom}'s {@code getInstance}
+ * methods <em>with</em> a {@code SecureRandomParameters} argument,
+ * the constructor will be called with that argument. The
+ * {@link #engineGetParameters()} method must not return {@code null}.
+ * <p>
+ * Otherwise, if the {@code SecureRandomSpi(SecureRandomParameters)}
+ * constructor is not overridden in an implementation, the
+ * {@link #SecureRandomSpi()} constructor must be overridden and it will be
+ * called if an object is instantiated with one of {@code SecureRandom}'s
+ * {@code getInstance} methods <em>without</em> a
+ * {@code SecureRandomParameters} argument. Calling one of
+ * {@code SecureRandom}'s {@code getInstance} methods <em>with</em>
+ * a {@code SecureRandomParameters} argument will never
+ * return an instance of this implementation. The
+ * {@link #engineGetParameters()} method must return {@code null}.
  *
- * @see SecureRandom
  * @since 1.2
  */
 
@@ -42,9 +67,30 @@
     private static final long serialVersionUID = -2991854161009191830L;
 
     /**
-     * Reseeds this random object. The given seed supplements, rather than
-     * replaces, the existing seed. Thus, repeated calls are guaranteed
-     * never to reduce randomness.
+     * Constructor without a parameter.
+     */
+    public SecureRandomSpi() {
+        // ignored
+    }
+
+    /**
+     * Constructor with a parameter.
+     *
+     * @param params the {@link SecureRandomParameters} object.
+     *               This argument can be {@code null}.
+     * @throws IllegalArgumentException if {@code params} is
+     *         unrecognizable or unsupported by this {@code SecureRandom}
+     *
+     * @since 9
+     */
+    protected SecureRandomSpi(SecureRandomParameters params) {
+        // ignored
+    }
+
+    /**
+     * Reseeds this random object with the given seed. The seed supplements,
+     * rather than replaces, the existing seed. Thus, repeated calls
+     * are guaranteed never to reduce randomness.
      *
      * @param seed the seed.
      */
@@ -52,17 +98,45 @@
 
     /**
      * Generates a user-specified number of random bytes.
-     *
-     * <p> If a call to {@code engineSetSeed} had not occurred previously,
-     * the first call to this method forces this SecureRandom implementation
-     * to seed itself.  This self-seeding will not occur if
-     * {@code engineSetSeed} was previously called.
+     * <p>
+     * Some random number generators can only generate a limited amount
+     * of random bytes per invocation. If the size of {@code bytes}
+     * is greater than this limit, the implementation should invoke
+     * its generation process multiple times to completely fill the
+     * buffer before returning from this method.
      *
      * @param bytes the array to be filled in with random bytes.
      */
     protected abstract void engineNextBytes(byte[] bytes);
 
     /**
+     * Generates a user-specified number of random bytes with
+     * additional parameters.
+     * <p>
+     * Some random number generators can only generate a limited amount
+     * of random bytes per invocation. If the size of {@code bytes}
+     * is greater than this limit, the implementation should invoke
+     * its generation process multiple times to completely fill the
+     * buffer before returning from this method.
+     *
+     * @implSpec The default implementation throws
+     * an {@link UnsupportedOperationException}.
+     *
+     * @param bytes the array to be filled in with random bytes
+     * @param params additional parameters
+     * @throws UnsupportedOperationException if the implementation
+     *         has not overridden this method
+     * @throws IllegalArgumentException if {@code params} is {@code null},
+     *         illegal or unsupported by this {@code SecureRandom}
+     *
+     * @since 9
+     */
+    protected void engineNextBytes(
+            byte[] bytes, SecureRandomParameters params) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Returns the given number of seed bytes.  This call may be used to
      * seed other random number generators.
      *
@@ -70,5 +144,58 @@
      *
      * @return the seed bytes.
      */
-     protected abstract byte[] engineGenerateSeed(int numBytes);
+    protected abstract byte[] engineGenerateSeed(int numBytes);
+
+    /**
+     * Reseeds this random object with entropy input read from its
+     * entropy source with additional parameters.
+     * <p>
+     * If this method is called by {@link SecureRandom#reseed()},
+     * {@code params} will be {@code null}.
+     * <p>
+     * Do not override this method if the implementation does not
+     * support reseeding.
+     *
+     * @implSpec The default implementation throws
+     *           an {@link UnsupportedOperationException}.
+     *
+     * @param params extra parameters, can be {@code null}.
+     * @throws UnsupportedOperationException if the implementation
+     *         has not overridden this method
+     * @throws IllegalArgumentException if {@code params} is
+     *         illegal or unsupported by this {@code SecureRandom}
+     *
+     * @since 9
+     */
+    protected void engineReseed(SecureRandomParameters params) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the effective {@link SecureRandomParameters} for this
+     * {@code SecureRandom} instance.
+     *
+     * @implSpec The default implementation returns {@code null}.
+     *
+     * @return the effective {@link SecureRandomParameters} parameters,
+     * or {@code null} if no parameters were used.
+     *
+     * @since 9
+     */
+    protected SecureRandomParameters engineGetParameters() {
+        return null;
+    }
+
+    /**
+     * Returns a Human-readable string representation of this
+     * {@code SecureRandom}.
+     *
+     * @return the string representation
+     *
+     * @since 9
+     */
+    @Override
+    public String toString() {
+        return getClass().getSimpleName();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,771 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 sun.security.util.Debug;
+
+import java.security.*;
+import java.util.Arrays;
+import java.util.Objects;
+import static java.security.DrbgParameters.Capability.*;
+
+/**
+ * The abstract base class for all DRBGs.
+ * <p>
+ * This class creates 5 new abstract methods. 3 are defined by the SP800-90A:
+ * <ol>
+ *  <li>{@link #generateAlgorithm(byte[], byte[])}
+ *  <li>{@link #reseedAlgorithm(byte[], byte[])} (might not be supported)
+ *  <li>{@link #instantiateAlgorithm(byte[])}
+ * </ol>
+ * and 2 for implementation purpose:
+ * <ol>
+ *  <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.
+ * <p>
+ * Synchronized keyword should be added to all externally callable engine
+ * methods including {@link #engineReseed}, {@link #engineSetSeed}, and
+ * {@link #engineNextBytes} (but not {@link #engineGenerateSeed}).
+ * Internal methods like {@link #configure} and {@link #instantiateAlgorithm}
+ * are not synchronized. They will either be called in a constructor or
+ * in another synchronized method.
+ */
+public abstract class AbstractDrbg extends SecureRandomSpi {
+
+    private static final long serialVersionUID = 9L;
+
+    /**
+     * This field is not null if {@code -Djava.security.debug=securerandom} is
+     * specified on the command line. An implementation can print useful
+     * debug info.
+     */
+    protected static final Debug debug = Debug.getInstance(
+            "securerandom", "drbg");
+
+    // Common working status
+
+    private transient boolean instantiated = false;
+
+    /**
+     * Reseed counter of a DRBG instance. A mechanism should increment it
+     * after each random bits generation and reset it in reseed. A mechanism
+     * does <em>not</em> need to compare it to {@link #reseedInterval}.
+     */
+    protected transient int reseedCounter = 0;
+
+    // Mech features. If not same as below, must be redefined in constructor.
+
+    /**
+     * Default strength of a DRBG instance if it is not configured.
+     * 128 is considered secure enough now. A mechanism
+     * can change it in a constructor.
+     *
+     * Remember to sync with "securerandom.drbg.config" in java.security.
+     */
+    protected static final int DEFAULT_STRENGTH = 128;
+
+    /**
+     * Mechanism name, say, {@code HashDRBG}. Must be set in constructor.
+     * This value will be used in {@code toString}.
+     */
+    protected String mechName = "DRBG";
+
+    /**
+     * highest_supported_security_strength of this mechanism for all algorithms
+     * it supports. A mechanism should update the value in its constructor
+     * if the value is not 256.
+     */
+    protected int highestSupportedSecurityStrength = 256;
+
+    /**
+     * Whether prediction resistance is supported. A mechanism should update
+     * the value in its constructor if it is <em>not</em> supported.
+     */
+    protected boolean supportPredictionResistance = true;
+
+    /**
+     * Whether reseed is supported. A mechanism should update
+     * the value in its constructor if it is <em>not</em> supported.
+     */
+    protected boolean supportReseeding = true;
+
+    // Strength features. If not same as below, must be redefined in
+    // chooseAlgorithmAndStrength. Among these, minLength and seedLen have no
+    // default value and must be redefined. If personalization string or
+    // additional input is not supported, set maxPersonalizationStringLength
+    // or maxAdditionalInputLength to -1.
+
+    /**
+     * Minimum entropy input length in bytes for this DRBG instance.
+     * Must be assigned in {@link #chooseAlgorithmAndStrength}.
+     */
+    protected int minLength;
+
+    /**
+     * Maximum entropy input length in bytes for this DRBG instance.
+     * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not
+     * {@link Integer#MAX_VALUE}.
+     * <p>
+     * In theory this value (and the values below) can be bigger than
+     * {@code Integer.MAX_VALUE} but a Java array can only have an int32 index.
+     */
+    protected int maxLength = Integer.MAX_VALUE;
+
+    /**
+     * Maximum personalization string length in bytes for this DRBG instance.
+     * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not
+     * {@link Integer#MAX_VALUE}.
+     */
+    protected int maxPersonalizationStringLength = Integer.MAX_VALUE;
+
+    /**
+     * Maximum additional input length in bytes for this DRBG instance.
+     * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not
+     * {@link Integer#MAX_VALUE}.
+     */
+    protected int maxAdditionalInputLength = Integer.MAX_VALUE;
+
+    /**
+     * max_number_of_bits_per_request in bytes for this DRBG instance.
+     * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not
+     * {@link Integer#MAX_VALUE}.
+     */
+    protected int maxNumberOfBytesPerRequest = Integer.MAX_VALUE;
+
+    /**
+     * Maximum number of requests between reseeds for this DRBG instance.
+     * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not
+     * {@link Integer#MAX_VALUE}.
+     */
+    protected int reseedInterval = Integer.MAX_VALUE;
+
+
+    /**
+     * 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}.
+     */
+    protected String algorithm;
+
+    // Configurable parameters
+
+    /**
+     * Security strength for this instance. Must be assigned in
+     * {@link #chooseAlgorithmAndStrength}. Should be at least the requested
+     * strength. Might be smaller than the highest strength
+     * {@link #algorithm} supports. Must not be -1.
+     */
+    protected int securityStrength;     // in bits
+
+    /**
+     * Strength requested in {@link DrbgParameters.Instantiation}.
+     * The real strength is based on it. Do not modify it in a mechanism.
+     */
+    protected int requestedInstantiationSecurityStrength = -1;
+
+    /**
+     * The personalization string used by this instance. Set inside
+     * {@link #configure(SecureRandomParameters)} and
+     * can be used in a mechanism. Do not modify it in a mechanism.
+     */
+    protected byte[] personalizationString;
+
+    /**
+     * The prediction resistance flag used by this instance. Set inside
+     * {@link #configure(SecureRandomParameters)}.
+     */
+    private boolean predictionResistanceFlag;
+
+    // Non-standard configurable parameters
+
+    /**
+     * Whether a derivation function is used. Requested in
+     * {@link MoreDrbgParameters}. Only CtrDRBG uses it.
+     * Do not modify it in a mechanism.
+     */
+    protected boolean usedf;
+
+    /**
+     * The nonce for this instance. Set in {@link #instantiateIfNecessary}.
+     * After instantiation, this field is not null. Do not modify it
+     * in a mechanism.
+     */
+    protected transient byte[] nonce;
+
+    /**
+     * Requested nonce in {@link MoreDrbgParameters}. If set to null,
+     * nonce will be chosen by system, and a reinstantiated DRBG will get a
+     * new system-provided nonce.
+     */
+    private byte[] requestedNonce;
+
+    /**
+     * Requested algorithm in {@link MoreDrbgParameters}.
+     * Do not modify it in a mechanism.
+     */
+    protected String requestedAlgorithm;
+
+    /**
+     * The entropy source used by this instance. Set inside
+     * {@link #configure(SecureRandomParameters)}. This field
+     * can be null. {@link #getEntropyInput} will take care of null check.
+     */
+    private transient EntropySource es;
+
+    // Five abstract methods for SP 800-90A DRBG
+
+    /**
+     * Decides what algorithm and strength to use (SHA-256 or AES-256,
+     * 128 or 256). Strength related fields must also be defined or redefined
+     * here. Called in {@link #configure}. A mechanism uses
+     * {@link #requestedAlgorithm},
+     * {@link #requestedInstantiationSecurityStrength}, and
+     * {@link #DEFAULT_STRENGTH} to decide which algorithm and strength to use.
+     * <p>
+     * If {@code requestedAlgorithm} is provided, it will always be used.
+     * If {@code requestedInstantiationSecurityStrength} is also provided,
+     * the algorithm will use the strength (an exception will be thrown if
+     * the strength is not supported), otherwise, the smaller one of
+     * the highest supported strength of the algorithm and the default strength
+     * will be used.
+     * <p>
+     * If {@code requestedAlgorithm} is not provided, an algorithm will be
+     * chosen that supports {@code requestedInstantiationSecurityStrength}
+     * (or {@code DEFAULT_STRENGTH} if there is no request).
+     * <p>
+     * Since every call to {@link #configure} will call this method,
+     * make sure to the calls do not contradict with each other.
+     * <p>
+     * Here are some examples of the algorithm and strength chosen (suppose
+     * {@code DEFAULT_STRENGTH} is 128) for HashDRBG:
+     * <pre>
+     * requested             effective
+     * (SHA-1, -1)           (SHA-1,128)
+     * (SHA-1, 112)          (SHA-1,112)
+     * (SHA-1, 192)          IAE
+     * (SHA-256, -1)         (SHA-256,128)
+     * (SHA-256, 128)        (SHA-256,128)
+     * (SHA-3, -1)           IAE
+     * (null, -1)            (SHA-256,128)
+     * (null, 112)           (SHA-256,112)
+     * (null, 192)           (SHA-256,192)
+     * (null, 256)           (SHA-256,256)
+     * (null, 384)           IAE
+     * </pre>
+     *
+     * @throws IllegalArgumentException if the requested parameters
+     *      can not be supported or contradict with each other.
+     */
+    protected abstract void chooseAlgorithmAndStrength();
+
+    /**
+     * 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.
+     */
+    protected abstract void initEngine();
+
+    /**
+     * Instantiates a DRBG. Called automatically before the first
+     * {@code nextBytes} call.
+     * <p>
+     * Note that the other parameters (nonce, strength, ps) are already
+     * stored inside at configuration.
+     *
+     * @param ei the entropy input, its length is already conditioned to be
+     *           between {@link #minLength} and {@link #maxLength}.
+     */
+    protected abstract void instantiateAlgorithm(byte[] ei);
+
+    /**
+     * The generate function.
+     *
+     * @param result fill result here, not null
+     * @param additionalInput additional input, can be null. If not null,
+     *          its length is smaller than {@link #maxAdditionalInputLength}
+     */
+    protected abstract void generateAlgorithm(
+            byte[] result, byte[] additionalInput);
+
+    /**
+     * The reseed function.
+     *
+     * @param ei the entropy input, its length is already conditioned to be
+     *           between {@link #minLength} and {@link #maxLength}.
+     * @param additionalInput additional input, can be null. If not null,
+     *          its length is smaller than {@link #maxAdditionalInputLength}
+     * @throws UnsupportedOperationException if reseed is not supported
+     */
+    protected void reseedAlgorithm(
+            byte[] ei, byte[] additionalInput) {
+        throw new UnsupportedOperationException("No reseed function");
+    }
+
+    // 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) {
+
+        Objects.requireNonNull(result);
+
+        if (debug != null) {
+            debug.println(this, "nextBytes");
+        }
+        if (params instanceof DrbgParameters.NextBytes) {
+
+            // 800-90Ar1 9.3: Generate Process.
+
+            DrbgParameters.NextBytes dp = (DrbgParameters.NextBytes) params;
+
+            // Step 2: max_number_of_bits_per_request
+            if (result.length > maxNumberOfBytesPerRequest) {
+                // generateAlgorithm should be called multiple times to fill
+                // up result. Unimplemented since maxNumberOfBytesPerRequest
+                // is now Integer.MAX_VALUE.
+            }
+
+            // Step 3: check requested_security_strength
+            if (dp.getStrength() > securityStrength) {
+                throw new IllegalArgumentException("strength too high: "
+                        + dp.getStrength());
+            }
+
+            // Step 4: check max_additional_input_length
+            byte[] ai = dp.getAdditionalInput();
+            if (ai != null && ai.length > maxAdditionalInputLength) {
+                throw new IllegalArgumentException("ai too long: "
+                        + ai.length);
+            }
+
+            // Step 5: check prediction_resistance_flag
+            boolean pr = dp.getPredictionResistance();
+            if (!predictionResistanceFlag && pr) {
+                throw new IllegalArgumentException("pr not available");
+            }
+
+            instantiateIfNecessary(null);
+
+            // Step 7: Auto reseed
+            if (reseedCounter > reseedInterval || pr) {
+                reseedAlgorithm(getEntropyInput(pr), ai);
+                ai = null;
+            }
+
+            // Step 8, 10: Generate_algorithm
+            // Step 9: Unnecessary. reseedCounter only updated after generation
+            generateAlgorithm(result, ai);
+
+            // Step 11: Return
+        } else {
+            throw new IllegalArgumentException("unknown params type:"
+                    + params.getClass());
+        }
+    }
+
+    @Override
+    public final void engineReseed(SecureRandomParameters params) {
+        if (debug != null) {
+            debug.println(this, "reseed with params");
+        }
+        if (!supportReseeding) {
+            throw new UnsupportedOperationException("Reseed not supported");
+        }
+        if (params == null) {
+            params = DrbgParameters.reseed(predictionResistanceFlag, null);
+        }
+        if (params instanceof DrbgParameters.Reseed) {
+            DrbgParameters.Reseed dp = (DrbgParameters.Reseed) params;
+
+            // 800-90Ar1 9.2: Reseed Process.
+
+            // Step 2: Check prediction_resistance_request
+            boolean pr = dp.getPredictionResistance();
+            if (!predictionResistanceFlag && pr) {
+                throw new IllegalArgumentException("pr not available");
+            }
+
+            // Step 3: Check additional_input length
+            byte[] ai = dp.getAdditionalInput();
+            if (ai != null && ai.length > maxAdditionalInputLength) {
+                throw new IllegalArgumentException("ai too long: "
+                        + ai.length);
+            }
+            instantiateIfNecessary(null);
+
+            // Step 4: Get_entropy_input
+            // Step 5: Check step 4
+            // Step 6-7: Reseed_algorithm
+            reseedAlgorithm(getEntropyInput(pr), ai);
+
+            // Step 8: Return
+        } else {
+            throw new IllegalArgumentException("unknown params type: "
+                    + params.getClass());
+        }
+    }
+
+    /**
+     * Returns the given number of seed bytes. A DRBG always uses
+     * {@link SeedGenerator} to get an array with full-entropy.
+     * <p>
+     * The implementation is identical to SHA1PRNG's
+     * {@link SecureRandom#engineGenerateSeed}.
+     *
+     * @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);
+        return b;
+    }
+
+    /**
+     * Reseeds this random object with the given seed. A DRBG always expands
+     * or truncates the input to be between {@link #minLength} and
+     * {@link #maxLength} and uses it to instantiate or reseed itself
+     * (depending on whether the DRBG is instantiated).
+     *
+     * @param input the seed
+     */
+    @Override
+    public final synchronized void engineSetSeed(byte[] input) {
+        if (debug != null) {
+            debug.println(this, "setSeed");
+        }
+        if (input.length < minLength) {
+            input = Arrays.copyOf(input, minLength);
+        } else if (input.length > maxLength) {
+            input = Arrays.copyOf(input, maxLength);
+        }
+        if (!instantiated) {
+            instantiateIfNecessary(input);
+        } else {
+            reseedAlgorithm(input, null);
+        }
+    }
+
+    // get_entropy_input
+
+    private byte[] getEntropyInput(boolean isPr) {
+        // Should the 1st arg be minEntropy or minLength?
+        //
+        // Technically it should be minEntropy, but CtrDRBG
+        // (not using derivation function) is so confusing
+        // (does it need only strength or seedlen of entropy?)
+        // that it's safer to assume minLength. In all other
+        // cases minLength equals to minEntropy.
+        return getEntropyInput(minLength, minLength, maxLength, isPr);
+    }
+
+    private byte[] getEntropyInput(int minEntropy, int minLength,
+                                   int maxLength, boolean pr) {
+        if (debug != null) {
+            debug.println(this, "getEntropy(" + minEntropy + "," + minLength +
+                    "," + maxLength + "," + pr + ")");
+        }
+        EntropySource esNow = es;
+        if (esNow == null) {
+            esNow = pr ? SeederHolder.prseeder : SeederHolder.seeder;
+        }
+        return esNow.getEntropy(minEntropy, minLength, maxLength, pr);
+    }
+
+    // Defaults
+
+    /**
+     * The default {@code EntropySource} determined by system property
+     * "java.security.egd" or security property "securerandom.source".
+     * <p>
+     * This object uses {@link SeedGenerator#generateSeed(byte[])} to
+     * return a byte array containing {@code minLength} bytes. It is
+     * assumed to support prediction resistance and always contains
+     * full-entropy. A trusted application can update this field.
+     */
+    private final static EntropySource defaultES =
+            (minE, minLen, maxLen, pr) -> {
+        byte[] result = new byte[minLen];
+        SeedGenerator.generateSeed(result);
+        return result;
+    };
+
+    private static class SeederHolder {
+
+        /**
+         * Default EntropySource for SecureRandom with prediction resistance,
+         */
+        static final EntropySource prseeder;
+
+        /**
+         * Default EntropySource for SecureRandom without prediction resistance,
+         * which is backed by a DRBG whose EntropySource is {@link #prseeder}.
+         */
+        static final EntropySource seeder;
+
+        static {
+            prseeder = defaultES;
+            // According to SP800-90C section 7, a DRBG without live
+            // entropy (drbg here, with pr being false) can instantiate
+            // another DRBG with weaker strength. So we choose highest
+            // strength we support.
+            HashDrbg first = new HashDrbg(new MoreDrbgParameters(
+                    prseeder, null, "SHA-256", null, false,
+                    DrbgParameters.instantiation(
+                            256, NONE,
+                            SeedGenerator.getSystemEntropy())));
+            seeder = (entropy, minLen, maxLen, pr) -> {
+                if (pr) {
+                    // This SEI does not support pr
+                    throw new IllegalArgumentException("pr not supported");
+                }
+                byte[] result = new byte[minLen];
+                first.engineNextBytes(result);
+                return result;
+            };
+        }
+    }
+
+    // Constructor called by overridden methods, initializer...
+
+    /**
+     * A constructor without argument so that an implementation does not
+     * need to always write {@code super(params)}.
+     */
+    protected AbstractDrbg() {
+        // Nothing
+    }
+
+    /**
+     * A mechanism shall override this constructor to setup {@link #mechName},
+     * {@link #highestSupportedSecurityStrength},
+     * {@link #supportPredictionResistance}, {@link #supportReseeding}
+     * or other features like {@link #DEFAULT_STRENGTH}. Finally it shall
+     * call {@link #configure} on {@code params}.
+     *
+     * @param params the {@link SecureRandomParameters} object.
+     *               This argument can be {@code null}.
+     * @throws IllegalArgumentException if {@code params} is
+     *         inappropriate for this SecureRandom.
+     */
+    protected AbstractDrbg(SecureRandomParameters params) {
+        // Nothing
+    }
+
+    /**
+     * Returns the current configuration as a {@link DrbgParameters.Instantiation}
+     * object.
+     *
+     * @return the curent configuration
+     */
+    @Override
+    protected SecureRandomParameters engineGetParameters() {
+        // Or read from variable.
+        return DrbgParameters.instantiation(
+                securityStrength,
+                predictionResistanceFlag ? PR_AND_RESEED :
+                        (supportReseeding ? RESEED_ONLY : NONE),
+                personalizationString);
+    }
+
+    /**
+     * Configure this DRBG. This method calls
+     * {@link #chooseAlgorithmAndStrength()} and {@link #initEngine()}
+     * but does not do the actual instantiation.
+     *
+     * @param params configuration, if null, default configuration (default
+     *               strength, pr_false, no personalization string) is used.
+     * @throws IllegalArgumentException if {@code params} is
+     *         inappropriate for this SecureRandom.
+     */
+    protected final synchronized void configure(
+            SecureRandomParameters params) {
+        if (debug != null) {
+            debug.println(this, "configure " + this + " with " + params);
+        }
+        if (params == null) {
+            params = DrbgParameters.instantiation(-1, RESEED_ONLY, null);
+        }
+        if (params instanceof MoreDrbgParameters) {
+            MoreDrbgParameters m = (MoreDrbgParameters)params;
+            this.requestedNonce = m.nonce;
+            this.es = m.es;
+            this.requestedAlgorithm = m.algorithm;
+            this.usedf = m.usedf;
+            params = m.config;
+        }
+        if (params != null) {
+            if (params instanceof DrbgParameters.Instantiation) {
+                DrbgParameters.Instantiation inst =
+                        (DrbgParameters.Instantiation) params;
+
+                // 800-90Ar1 9.1: Instantiate Process. Steps 1-5.
+
+                // Step 1: Check requested_instantiation_security_strength
+                if (inst.getStrength() > highestSupportedSecurityStrength) {
+                    throw new IllegalArgumentException("strength too big: "
+                            + inst.getStrength());
+                }
+
+                // Step 2: Check prediction_resistance_flag
+                if (inst.getCapability().supportsPredictionResistance()
+                        && !supportPredictionResistance) {
+                    throw new IllegalArgumentException("pr not supported");
+                }
+
+                // Step 3: Check personalization_string
+                byte[] ps = inst.getPersonalizationString();
+                if (ps != null && ps.length > maxPersonalizationStringLength) {
+                    throw new IllegalArgumentException("ps too long: "
+                            + ps.length);
+                }
+
+                if (inst.getCapability().supportsReseeding()
+                        && !supportReseeding) {
+                    throw new IllegalArgumentException("reseed not supported");
+                }
+                this.personalizationString = ps;
+                this.predictionResistanceFlag =
+                        inst.getCapability().supportsPredictionResistance();
+                this.requestedInstantiationSecurityStrength = inst.getStrength();
+            } else {
+                throw new IllegalArgumentException("unknown params: "
+                        + params.getClass());
+            }
+        }
+
+        // Step 4: Set security_strength
+        chooseAlgorithmAndStrength();
+        instantiated = false;
+
+        // Step 5: no-op.
+
+        if (debug != null) {
+            debug.println(this, "configured " + this);
+        }
+    }
+
+    /**
+     * Instantiate if necessary,
+     *
+     * @param entropy a user-provided entropy, the length is already good.
+     *                If null, will fetch entropy input automatically.
+     */
+    private synchronized void instantiateIfNecessary(byte[] entropy) {
+        if (!instantiated) {
+
+            // 800-90Ar1 9.1: Instantiate Process. Steps 6-12.
+
+            // Step 6: Get_entropy_input
+            // Step 7: check error (getEntropyInput throw no exception now)
+            if (entropy == null) {
+                entropy = getEntropyInput(predictionResistanceFlag);
+            }
+
+            // Step 8. nonce
+            if (requestedNonce != null) {
+                nonce = requestedNonce;
+            } else {
+                nonce = NonceProvider.next();
+            }
+            initEngine();
+
+            // Step 9-11: Instantiate_algorithm
+            instantiateAlgorithm(entropy);
+            instantiated = true;
+
+            // Step 12: Return
+        }
+    }
+
+    // Nonce provider
+
+    private static class NonceProvider {
+
+        // 128 bits of nonce can be used by 256-bit strength DRBG
+        private static final byte[] block = new byte[16];
+
+        private static synchronized byte[] next() {
+            int k = 15;
+            while ((k >= 0) && (++block[k] == 0)) {
+                k--;
+            }
+            return block.clone();
+        }
+    }
+
+    // Misc
+
+    /** A handy method returning hexdump string with no colon or new line.
+     *
+     * @param in input byte array
+     * @return the hexdump string
+     */
+    protected static String hex(byte[] in) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : in) {
+            sb.append(String.format("%02x", b&0xff));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the smallest standard strength (112, 128, 192, 256) that is
+     * greater or equal to the input.
+     *
+     * @param input the input strength
+     * @return the standard strength
+     */
+    protected static int getStandardStrength(int input) {
+        if (input <= 112) return 112;
+        if (input <= 128) return 128;
+        if (input <= 192) return 192;
+        if (input <= 256) return 256;
+        throw new IllegalArgumentException("input too big: " + input);
+    }
+
+    @Override
+    public String toString() {
+        return mechName + ","  + algorithm
+                + "," + securityStrength + ","
+                + (predictionResistanceFlag ? "pr_and_reseed"
+                        : (supportReseeding ? "reseed_only" : "none"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,160 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 sun.security.util.HexDumpEncoder;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+public abstract class AbstractHashDrbg extends AbstractDrbg {
+
+    private static final long serialVersionUID = 9L;
+
+    protected int outLen;
+    protected int seedLen;
+
+    private static int alg2strength(String algorithm) {
+        switch (algorithm.toUpperCase(Locale.ROOT)) {
+            case "SHA-1":
+                return 128;
+            case "SHA-224":
+            case "SHA-512/224":
+                return 192;
+            case "SHA-256":
+            case "SHA-512/256":
+            case "SHA-384":
+            case "SHA-512":
+                return 256;
+            default:
+                throw new IllegalArgumentException(algorithm +
+                        " not supported in Hash_DBRG");
+        }
+    }
+
+    protected void chooseAlgorithmAndStrength() {
+        if (requestedAlgorithm != null) {
+            algorithm = requestedAlgorithm.toUpperCase(Locale.ROOT);
+            int supportedStrength = alg2strength(algorithm);
+            if (requestedInstantiationSecurityStrength >= 0) {
+                int tryStrength = getStandardStrength(
+                        requestedInstantiationSecurityStrength);
+                if (tryStrength > supportedStrength) {
+                    throw new IllegalArgumentException(algorithm +
+                            " does not support strength " +
+                            requestedInstantiationSecurityStrength);
+                }
+                this.securityStrength = tryStrength;
+            } else {
+                this.securityStrength = DEFAULT_STRENGTH > supportedStrength ?
+                        supportedStrength : DEFAULT_STRENGTH;
+            }
+        } else {
+            int tryStrength = (requestedInstantiationSecurityStrength < 0) ?
+                    DEFAULT_STRENGTH : requestedInstantiationSecurityStrength;
+            tryStrength = getStandardStrength(tryStrength);
+            // The default algorithm which is enough for all strengths.
+            // Remember to sync with "securerandom.drbg.config" in java.security
+            algorithm = "SHA-256";
+            this.securityStrength = tryStrength;
+        }
+        switch (algorithm.toUpperCase(Locale.ROOT)) {
+            case "SHA-1":
+                this.seedLen = 440 / 8;
+                this.outLen = 160 / 8;
+                break;
+            case "SHA-224":
+            case "SHA-512/224":
+                this.seedLen = 440 / 8;
+                this.outLen = 224 / 8;
+                break;
+            case "SHA-256":
+            case "SHA-512/256":
+                this.seedLen = 440 / 8;
+                this.outLen = 256 / 8;
+                break;
+            case "SHA-384":
+                this.seedLen = 888 / 8;
+                this.outLen = 384 / 8;
+                break;
+            case "SHA-512":
+                this.seedLen = 888 / 8;
+                this.outLen = 512 / 8;
+                break;
+            default:
+                throw new IllegalArgumentException(algorithm +
+                        " not supported in Hash_DBRG");
+        }
+        this.minLength = this.securityStrength / 8;
+    }
+
+    @Override
+    public void instantiateAlgorithm(byte[] entropy) {
+        if (debug != null) {
+            debug.println(this, "instantiate");
+        }
+
+        // 800-90Ar1 10.1.1.2: Hash_DRBG Instantiate Process.
+        // 800-90Ar1 10.1.2.3: Hmac_DRBG Instantiate Process.
+
+        // Step 1: entropy_input || nonce || personalization_string.
+        byte[] seed = Arrays.copyOf(entropy, entropy.length + nonce.length +
+                ((personalizationString == null) ? 0
+                        : personalizationString.length));
+        System.arraycopy(nonce, 0, seed, entropy.length, nonce.length);
+        if (personalizationString != null) {
+            System.arraycopy(personalizationString, 0,
+                    seed, entropy.length + nonce.length,
+                    personalizationString.length);
+        }
+        hashReseedInternal(seed);
+    }
+
+    @Override
+    protected void reseedAlgorithm(
+            byte[] ei,
+            byte[] additionalInput) {
+        if (debug != null) {
+            debug.println(this, "reseedAlgorithm\n" +
+                    new HexDumpEncoder().encodeBuffer(ei) + "\n" +
+                    ((additionalInput == null) ? "" :
+                        new HexDumpEncoder().encodeBuffer(additionalInput)));
+        }
+
+        // 800-90Ar1 10.1.1.3: Hash_DRBG Reseed Process.
+        // 800-90Ar1 10.1.2.4: Hmac_DRBG Reseed Process.
+
+        // Step 1: entropy_input || additional_input.
+        if (additionalInput != null) {
+            ei = Arrays.copyOf(ei, ei.length + additionalInput.length);
+            System.arraycopy(additionalInput, 0, ei,
+                    ei.length - additionalInput.length, additionalInput.length);
+        }
+        hashReseedInternal(ei);
+    }
+
+    protected abstract void hashReseedInternal(byte[] seed);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/CtrDrbg.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,530 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+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 {
+        try {
+            AES_LIMIT = Cipher.getMaxAllowedKeyLength("AES");
+        } catch (Exception e) {
+            // should not happen
+            throw new AssertionError("Cannot detect AES", e);
+        }
+    }
+
+    private transient Cipher cipher;
+
+    private String cipherAlg;
+    private String keyAlg;
+
+    private int ctrLen;
+    private int blockLen;
+    private int keyLen;
+    private int seedLen;
+
+    private transient byte[] v;
+    private transient byte[] k;
+
+    public CtrDrbg(SecureRandomParameters params) {
+        mechName = "CTR_DRBG";
+        configure(params);
+    }
+
+    private static int alg2strength(String algorithm) {
+        switch (algorithm.toUpperCase(Locale.ROOT)) {
+            case "TDEA":
+            case "3KEYTDEA":
+            case "3 KEY TDEA":
+            case "DESEDE":
+                return 112;
+            case "AES-128":
+                return 128;
+            case "AES-192":
+                return 192;
+            case "AES-256":
+                return 256;
+            default:
+                throw new IllegalArgumentException(algorithm +
+                        " not supported in CTR_DBRG");
+        }
+    }
+
+    @Override
+    protected void chooseAlgorithmAndStrength() {
+        if (requestedAlgorithm != null) {
+            algorithm = requestedAlgorithm.toUpperCase();
+            int supportedStrength = alg2strength(algorithm);
+            if (requestedInstantiationSecurityStrength >= 0) {
+                int tryStrength = getStandardStrength(
+                        requestedInstantiationSecurityStrength);
+                if (tryStrength > supportedStrength) {
+                    throw new IllegalArgumentException(algorithm +
+                            " does not support strength " +
+                            requestedInstantiationSecurityStrength);
+                }
+                this.securityStrength = tryStrength;
+            } else {
+                this.securityStrength = (DEFAULT_STRENGTH > supportedStrength) ?
+                        supportedStrength : DEFAULT_STRENGTH;
+            }
+        } else {
+            int tryStrength = (requestedInstantiationSecurityStrength < 0) ?
+                    DEFAULT_STRENGTH : requestedInstantiationSecurityStrength;
+            tryStrength = getStandardStrength(tryStrength);
+            // Default algorithm, use AES-128 if AES-256 is not available.
+            // Remember to sync with "securerandom.drbg.config" in java.security
+            if (tryStrength <= 128 && AES_LIMIT < 256) {
+                algorithm = "AES-128";
+            } else if (AES_LIMIT >= 256) {
+                algorithm = "AES-256";
+            } else {
+                throw new IllegalArgumentException("unsupported strength " +
+                        requestedInstantiationSecurityStrength);
+            }
+            this.securityStrength = tryStrength;
+        }
+        switch (algorithm.toUpperCase(Locale.ROOT)) {
+            case "TDEA":
+            case "3KEYTDEA":
+            case "3 KEY TDEA":
+            case "DESEDE":
+                algorithm = "DESede";
+                this.keyAlg = "DESede";
+                this.cipherAlg = "DESede/ECB/NoPadding";
+                this.blockLen = 64 / 8;
+                this.keyLen = 168 / 8;
+                break;
+            case "AES-128":
+            case "AES-192":
+            case "AES-256":
+                this.keyAlg = "AES";
+                this.cipherAlg = "AES/ECB/NoPadding";
+                switch (algorithm) {
+                    case "AES-128":
+                        this.keyLen = 128 / 8;
+                        break;
+                    case "AES-192":
+                        this.keyLen = 192 / 8;
+                        if (AES_LIMIT < 192) {
+                            throw new IllegalArgumentException(algorithm +
+                                " not available (because policy) in CTR_DBRG");
+                        }
+                        break;
+                    case "AES-256":
+                        this.keyLen = 256 / 8;
+                        if (AES_LIMIT < 256) {
+                            throw new IllegalArgumentException(algorithm +
+                                " not available (because policy) in CTR_DBRG");
+                        }
+                        break;
+                    default:
+                        throw new IllegalArgumentException(algorithm +
+                            " not supported in CTR_DBRG");
+                }
+                this.blockLen = 128 / 8;
+                break;
+            default:
+                throw new IllegalArgumentException(algorithm +
+                        " not supported in CTR_DBRG");
+        }
+        this.seedLen = this.blockLen + this.keyLen;
+        this.ctrLen = this.blockLen;    // TODO
+        if (usedf) {
+            this.minLength = this.securityStrength / 8;
+        } else {
+            this.minLength = this.maxLength =
+                    this.maxPersonalizationStringLength =
+                            this.maxAdditionalInputLength = seedLen;
+        }
+    }
+
+    /**
+     * This call, used by the constructors, instantiates the digest.
+     */
+    @Override
+    protected void initEngine() {
+        try {
+            /*
+             * Use the local SUN implementation to avoid native
+             * performance overhead.
+             */
+            cipher = Cipher.getInstance(cipherAlg, "SunJCE");
+        } catch (NoSuchProviderException | NoSuchAlgorithmException
+                | NoSuchPaddingException e) {
+            // Fallback to any available.
+            try {
+                cipher = Cipher.getInstance(cipherAlg);
+            } catch (NoSuchAlgorithmException | NoSuchPaddingException exc) {
+                throw new InternalError(
+                    "internal error: " + cipherAlg + " not available.", exc);
+            }
+        }
+    }
+
+    private void status() {
+        if (debug != null) {
+            debug.println(this, "Key = " + hex(k));
+            debug.println(this, "V   = " + hex(v));
+            debug.println(this, "reseed counter = " + reseedCounter);
+        }
+    }
+
+    // 800-90Ar1 10.2.1.2. CTR_DRBG_Update
+    private void update(byte[] input) {
+        if (input.length != seedLen) {
+            // Should not happen
+            throw new IllegalArgumentException("input length not seedLen: "
+                    + input.length);
+        }
+        try {
+
+            int m = (seedLen + blockLen - 1) / blockLen;
+            byte[] temp = new byte[m * blockLen];
+
+            // Step 1. temp = Null.
+
+            // Step 2. Loop
+            for (int i = 0; i < m; i++) {
+                // Step 2.1. Increment
+                addOne(v, ctrLen);
+                // Step 2.2. Block_Encrypt
+                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                // Step 2.3. Encrypt into right position, no need to cat
+                cipher.doFinal(v, 0, blockLen, temp, i * blockLen);
+            }
+
+            // Step 3. Truncate
+            temp = Arrays.copyOf(temp, seedLen);
+
+            // Step 4: Add
+            for (int i = 0; i < seedLen; i++) {
+                temp[i] ^= input[i];
+            }
+
+            // Step 5: leftmost
+            k = Arrays.copyOf(temp, keyLen);
+
+            // Step 6: rightmost
+            v = Arrays.copyOfRange(temp, seedLen - blockLen, seedLen);
+
+            // Step 7. Return
+        } catch (GeneralSecurityException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    protected void instantiateAlgorithm(byte[] ei) {
+        if (debug != null) {
+            debug.println(this, "instantiate");
+        }
+        byte[] more;
+        if (usedf) {
+            // 800-90Ar1 10.2.1.3.2 Step 1-2. cat bytes
+            if (personalizationString == null) {
+                more = nonce;
+            } else {
+                more = Arrays.copyOf(
+                        nonce, nonce.length + personalizationString.length);
+                System.arraycopy(personalizationString, 0, more, nonce.length,
+                        personalizationString.length);
+            }
+        } else {
+            // 800-90Ar1 10.2.1.3.1
+            // Step 1-2, no need to expand personalizationString, we only XOR
+            // with shorter length
+            more = personalizationString;
+        }
+        reseedAlgorithm(ei, more);
+    }
+
+    private byte[] df(byte[] input) {
+        int l = input.length;
+        int n = seedLen;
+        int slen = 4 + 4 + l + 1;
+        byte[] s = new byte[(slen + blockLen - 1) / blockLen * blockLen];
+        s[0] = (byte)(l >> 24);
+        s[1] = (byte)(l >> 16);
+        s[2] = (byte)(l >> 8);
+        s[3] = (byte)(l);
+        s[4] = (byte)(n >> 24);
+        s[5] = (byte)(n >> 16);
+        s[6] = (byte)(n >> 8);
+        s[7] = (byte)(n);
+        System.arraycopy(input, 0, s, 8, l);
+        s[8+l] = (byte)0x80;
+
+        byte[] k = new byte[keyLen];
+        for (int i = 0; i < k.length; i++) {
+            k[i] = (byte)i;
+        }
+
+        byte[] temp = new byte[seedLen];
+
+        for (int i = 0; i * blockLen < temp.length; i++) {
+            byte[] iv = new byte[blockLen + s.length];
+            iv[0] = (byte)(i >> 24);
+            iv[1] = (byte)(i >> 16);
+            iv[2] = (byte)(i >> 8);
+            iv[3] = (byte)(i);
+            System.arraycopy(s, 0, iv, blockLen, s.length);
+            int tailLen = temp.length - blockLen*i;
+            if (tailLen > blockLen) {
+                tailLen = blockLen;
+            }
+            System.arraycopy(bcc(k, iv), 0, temp, blockLen*i, tailLen);
+        }
+
+        k = Arrays.copyOf(temp, keyLen);
+        byte[] x = Arrays.copyOfRange(temp, keyLen, temp.length);
+
+        for (int i = 0; i * blockLen < seedLen; i++) {
+            try {
+                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                int tailLen = temp.length - blockLen*i;
+                if (tailLen > blockLen) {
+                    tailLen = blockLen;
+                }
+                x = cipher.doFinal(x);
+                System.arraycopy(x, 0, temp, blockLen * i, tailLen);
+            } catch (GeneralSecurityException e) {
+                throw new InternalError(e);
+            }
+        }
+        return temp;
+    }
+
+    private byte[] bcc(byte[] k, byte[] data) {
+        byte[] chain = new byte[blockLen];
+        int n = data.length / blockLen;
+        for (int i = 0; i < n; i++) {
+            byte[] inputBlock = Arrays.copyOfRange(
+                    data, i * blockLen, i * blockLen + blockLen);
+            for (int j = 0; j < blockLen; j++) {
+                inputBlock[j] ^= chain[j];
+            }
+            try {
+                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                chain = cipher.doFinal(inputBlock);
+            } catch (GeneralSecurityException e) {
+                throw new InternalError(e);
+            }
+        }
+        return chain;
+    }
+
+    @Override
+    protected void reseedAlgorithm(
+            byte[] ei,
+            byte[] additionalInput) {
+        if (usedf) {
+            // 800-90Ar1 10.2.1.3.2 Instantiate.
+            // 800-90Ar1 10.2.1.4.2 Reseed.
+
+            // Step 1: cat bytes
+            if (additionalInput != null) {
+                byte[] temp = Arrays.copyOf(
+                        ei, ei.length + additionalInput.length);
+                System.arraycopy(additionalInput, 0, temp, ei.length,
+                        additionalInput.length);
+                ei = temp;
+            }
+            // Step 2. df (seed_material, seedlen).
+            ei = df(ei);
+        } else {
+            // 800-90Ar1 10.2.1.3.1 Instantiate
+            // 800-90Ar1 10.2.1.4.1 Reseed
+            // Step 1-2. Needless
+            // Step 3. seed_material = entropy_input XOR more
+            if (additionalInput != null) {
+                // additionalInput.length <= seedLen
+                for (int i = 0; i < additionalInput.length; i++) {
+                    ei[i] ^= additionalInput[i];
+                }
+            }
+        }
+
+        if (v == null) {
+            // 800-90Ar1 10.2.1.3.2 Instantiate. Step 3-4
+            // 800-90Ar1 10.2.1.3.1 Instantiate. Step 4-5
+            k = new byte[keyLen];
+            v = new byte[blockLen];
+        }
+        //status();
+
+        // 800-90Ar1 10.2.1.3.1 Instantiate. Step 6
+        // 800-90Ar1 10.2.1.3.2 Instantiate. Step 5
+        // 800-90Ar1 10.2.1.4.1 Reseed. Step 4
+        // 800-90Ar1 10.2.1.4.2 Reseed. Step 3
+        update(ei);
+        // 800-90Ar1 10.2.1.3.1 Instantiate. Step 7
+        // 800-90Ar1 10.2.1.3.2 Instantiate. Step 6
+        // 800-90Ar1 10.2.1.4.1 Reseed. Step 5
+        // 800-90Ar1 10.2.1.4.2 Reseed. Step 4
+        reseedCounter = 1;
+        //status();
+
+        // Whatever step. Return
+    }
+
+    /**
+     * Add one to data, only touch the last len bytes.
+     */
+    private static void addOne(byte[] data, int len) {
+        for (int i = 0; i < len; i++) {
+            data[data.length - 1 - i]++;
+            if (data[data.length - 1 - i] != 0) {
+                break;
+            }
+        }
+    }
+
+    @Override
+    public synchronized void generateAlgorithm(
+            byte[] result, byte[] additionalInput) {
+
+        if (debug != null) {
+            debug.println(this, "generateAlgorithm");
+        }
+
+        // 800-90Ar1 10.2.1.5.1 Generate
+        // 800-90Ar1 10.2.1.5.2 Generate
+
+        // Step 1: Check reseed_counter. Will not fail. Already checked in
+        // AbstractDrbg#engineNextBytes.
+
+        if (additionalInput != null) {
+            if (usedf) {
+                // 10.2.1.5.2 Step 2.1
+                additionalInput = df(additionalInput);
+            } else {
+                // 10.2.1.5.1 Step 2.1-2.2
+                additionalInput = Arrays.copyOf(additionalInput, seedLen);
+            }
+            // 10.2.1.5.1 Step 2.3
+            // 10.2.1.5.2 Step 2.2
+            update(additionalInput);
+        } else {
+            // 10.2.1.5.1 Step 2 Else
+            // 10.2.1.5.2 Step 2 Else
+            additionalInput = new byte[seedLen];
+        }
+
+        // Step 3. temp = Null
+        int pos = 0;
+
+        // Step 4. Loop
+        while (pos < result.length) {
+            int tailLen = result.length - pos;
+            // Step 4.1. Increment
+            addOne(v, ctrLen);
+            try {
+                // Step 4.2. Encrypt
+                cipher.init(Cipher.ENCRYPT_MODE, getKey(keyAlg, k));
+                byte[] out = cipher.doFinal(v);
+
+                // Step 4.3 and 5. Cat bytes and leftmost
+                System.arraycopy(out, 0, result, pos,
+                        (tailLen > blockLen) ? blockLen : tailLen);
+            } catch (GeneralSecurityException e) {
+                throw new InternalError(e);
+            }
+            pos += blockLen;
+        }
+
+        // Step 6. Update
+        update(additionalInput);
+
+        // Step 7. reseed_counter++
+        reseedCounter++;
+
+        //status();
+
+        // Step 8. Return
+    }
+
+    private static void des7to8(
+            byte[] key56, int off56, byte[] key64, int off64) {
+        key64[off64 + 0] = (byte)
+                (key56[off56 + 0] & 0xFE); // << 0
+        key64[off64 + 1] = (byte)
+                ((key56[off56 + 0] << 7) | ((key56[off56 + 1] & 0xFF) >>> 1));
+        key64[off64 + 2] = (byte)
+                ((key56[off56 + 1] << 6) | ((key56[off56 + 2] & 0xFF) >>> 2));
+        key64[off64 + 3] = (byte)
+                ((key56[off56 + 2] << 5) | ((key56[off56 + 3] & 0xFF) >>> 3));
+        key64[off64 + 4] = (byte)
+                ((key56[off56 + 3] << 4) | ((key56[off56 + 4] & 0xFF) >>> 4));
+        key64[off64 + 5] = (byte)
+                ((key56[off56 + 4] << 3) | ((key56[off56 + 5] & 0xFF) >>> 5));
+        key64[off64 + 6] = (byte)
+                ((key56[off56 + 5] << 2) | ((key56[off56 + 6] & 0xFF) >>> 6));
+        key64[off64 + 7] = (byte)
+                (key56[off56 + 6] << 1);
+
+        for (int i = 0; i < 8; i++) {
+            // if even # bits, make uneven, XOR with 1 (uneven & 1)
+            // for uneven # bits, make even, XOR with 0 (even & 1)
+            key64[off64 + i] ^= Integer.bitCount(key64[off64 + i] ^ 1) & 1;
+        }
+    }
+
+    private static SecretKey getKey(String keyAlg, byte[] k) {
+        if (keyAlg.equals("DESede")) {
+            byte[] k2 = new byte[24];
+            des7to8(k, 0, k2, 0);
+            des7to8(k, 7, k2, 8);
+            des7to8(k, 14, k2, 16);
+            k = k2;
+        }
+        return new SecretKeySpec(k, keyAlg);
+    }
+
+    private void readObject(java.io.ObjectInputStream s)
+            throws IOException, ClassNotFoundException {
+        s.defaultReadObject ();
+        initEngine();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "/"
+                + (usedf ? "use_df" : "no_df");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/DRBG.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,271 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.AccessController;
+import java.security.DrbgParameters;
+import java.security.PrivilegedAction;
+import java.security.SecureRandomParameters;
+import java.security.SecureRandomSpi;
+import java.security.Security;
+import java.util.Locale;
+import static java.security.DrbgParameters.Capability.*;
+
+/**
+ * Implement the "SecureRandom.DRBG" algorithm.
+ *
+ * About the default "securerandom.drbg.config" value:
+ *
+ * The default value in java.security is set to "". This is because
+ * the default values of different aspects are dependent (For example,
+ * strength depends on algorithm) and if we write a full string there
+ * it will be difficult to modify one and keep all others legal.
+ *
+ * When changing default values, touch all places including:
+ *
+ * 1. comments of the security property in java.security
+ * 2. Default mech, cap, usedf set in this class
+ * 3. Default algorithm set in final implementation of each mech
+ * 4. Default strength set in AbstractDrbg, but the effective
+ *    value can be smaller if an algorithm does not support it.
+ *
+ * The default value is also mentioned in the @implNote part of
+ * {@link DrbgParameters} class.
+ */
+public final class DRBG extends SecureRandomSpi {
+
+    private static final String PROP_NAME = "securerandom.drbg.config";
+
+    private static final long serialVersionUID = 9L;
+
+    private final AbstractDrbg impl;
+
+    private final String mechName;
+
+    private final String algorithmName;
+
+    public DRBG(SecureRandomParameters params) {
+
+        // All parameters at unset status (null or -1).
+
+        // Configurable with the "securerandom.drbg.config" security property
+        String mech = null;
+        Boolean usedf = null;
+        String algorithm = null;
+
+        // Default instantiate parameters also configurable with
+        // "securerandom.drbg.config", and can be changed with params
+        // in getInstance("drbg", params)
+        int strength = -1;
+        DrbgParameters.Capability cap = null;
+        byte[] ps = null;
+
+        // Not configurable with public interfaces, but is a part of
+        // MoreDrbgParameters
+        EntropySource es = null;
+        byte[] nonce = null;
+
+        // Can be configured with a security property
+
+        String config = AccessController.doPrivileged((PrivilegedAction<String>)
+                    () -> Security.getProperty(PROP_NAME));
+
+        if (config != null && !config.isEmpty()) {
+            for (String part : config.split(",")) {
+                part = part.trim();
+                switch (part.toLowerCase(Locale.ROOT)) {
+                    case "":
+                        throw new IllegalArgumentException(
+                                "aspect in " + PROP_NAME + " cannot be empty");
+                    case "pr_and_reseed":
+                        checkTwice(cap != null, "capability");
+                        cap = PR_AND_RESEED;
+                        break;
+                    case "reseed_only":
+                        checkTwice(cap != null, "capability");
+                        cap = RESEED_ONLY;
+                        break;
+                    case "none":
+                        checkTwice(cap != null, "capability");
+                        cap = NONE;
+                        break;
+                    case "hash_drbg":
+                    case "hmac_drbg":
+                    case "ctr_drbg":
+                        checkTwice(mech != null, "mechanism name");
+                        mech = part;
+                        break;
+                    case "no_df":
+                        checkTwice(usedf != null, "usedf flag");
+                        usedf = false;
+                        break;
+                    case "use_df":
+                        checkTwice(usedf != null, "usedf flag");
+                        usedf = true;
+                        break;
+                    default:
+                        // For all other parts of the property, it is
+                        // either an algorithm name or a strength
+                        try {
+                            int tmp = Integer.parseInt(part);
+                            if (tmp < 0) {
+                                throw new IllegalArgumentException(
+                                        "strength in " + PROP_NAME +
+                                                " cannot be negative: " + part);
+                            }
+                            checkTwice(strength >= 0, "strength");
+                            strength = tmp;
+                        } catch (NumberFormatException e) {
+                            checkTwice(algorithm != null, "algorithm name");
+                            algorithm = part;
+                        }
+                }
+            }
+        }
+
+        // Can be updated by params
+
+        if (params != null) {
+            // MoreDrbgParameters is used for testing.
+            if (params instanceof MoreDrbgParameters) {
+                MoreDrbgParameters m = (MoreDrbgParameters)params;
+                params = m.config;
+
+                // No need to check null for es and nonce, they are still null
+                es = m.es;
+                nonce = m.nonce;
+
+                if (m.mech != null) {
+                    mech = m.mech;
+                }
+                if (m.algorithm != null) {
+                    algorithm = m.algorithm;
+                }
+                usedf = m.usedf;
+            }
+            if (params instanceof DrbgParameters.Instantiation) {
+                DrbgParameters.Instantiation dp =
+                        (DrbgParameters.Instantiation) params;
+
+                // ps is still null by now
+                ps = dp.getPersonalizationString();
+
+                int tmp = dp.getStrength();
+                if (tmp != -1) {
+                    strength = tmp;
+                }
+                cap = dp.getCapability();
+            } else {
+                throw new IllegalArgumentException("Unsupported params: "
+                        + params.getClass());
+            }
+        }
+
+        // Hardcoded defaults.
+        // Remember to sync with "securerandom.drbg.config" in java.security.
+
+        if (cap == null) {
+            cap = NONE;
+        }
+        if (mech == null) {
+            mech = "Hash_DRBG";
+        }
+        if (usedf == null) {
+            usedf = true;
+        }
+
+        MoreDrbgParameters m = new MoreDrbgParameters(
+                es, mech, algorithm, nonce, usedf,
+                DrbgParameters.instantiation(strength, cap, ps));
+
+        switch (mech.toLowerCase(Locale.ROOT)) {
+            case "hash_drbg":
+                impl = new HashDrbg(m);
+                break;
+            case "hmac_drbg":
+                impl = new HmacDrbg(m);
+                break;
+            case "ctr_drbg":
+                impl = new CtrDrbg(m);
+                break;
+            default:
+                throw new IllegalArgumentException("Unsupported mech: " + mech);
+        }
+
+        mechName = mech;
+        algorithmName = impl.algorithm;
+    }
+
+    @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();
+    }
+
+    /**
+     * Ensures an aspect is not set more than once.
+     *
+     * @param flag true if set more than once
+     * @param name the name of aspect shown in IAE
+     * @throws IllegalArgumentException if it happens
+     */
+    private static void checkTwice(boolean flag, String name) {
+        if (flag) {
+            throw new IllegalArgumentException(name
+                    + " cannot be provided more than once in " + PROP_NAME);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/EntropySource.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,47 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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;
+
+/**
+ * An interface of a source of entropy input.
+ *
+ * @since 9
+ */
+public interface EntropySource {
+    /**
+     * Returns a byte array containing entropy.
+     * <p>
+     * This maps to the {@code Get_entropy_input} function defined in
+     * Section 9 of NIST SP 800-90Ar1.
+     *
+     * @param minEntropy minimum entropy required, in bytes
+     * @param minLength minimum length of output, in bytes
+     * @param maxLength maximum length of output, in bytes
+     * @param pr whether prediction resistance is required
+     * @return the byte array containing entropy
+     */
+    byte[] getEntropy(int minEntropy, int minLength, int maxLength, boolean pr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/HashDrbg.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,276 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.io.IOException;
+import java.math.BigInteger;
+import java.security.DigestException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandomParameters;
+import java.util.Arrays;
+
+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 transient byte[] v;
+    private transient byte[] c;
+
+    public HashDrbg(SecureRandomParameters params) {
+        mechName = "Hash_DRBG";
+        configure(params);
+    }
+
+    /**
+     * This call, used by the constructors, instantiates the digest.
+     */
+    @Override
+    protected void initEngine() {
+        try {
+            /*
+             * Use the local SUN implementation to avoid native
+             * performance overhead.
+             */
+            digest = MessageDigest.getInstance(algorithm, "SUN");
+        } catch (NoSuchProviderException | NoSuchAlgorithmException e) {
+            // Fallback to any available.
+            try {
+                digest = MessageDigest.getInstance(algorithm);
+            } catch (NoSuchAlgorithmException exc) {
+                throw new InternalError(
+                    "internal error: " + algorithm + " not available.", exc);
+            }
+        }
+    }
+
+    private byte[] hashDf(int requested, byte[]... inputs) {
+        return hashDf(digest, outLen, requested, inputs);
+    }
+
+    /**
+     * A hash-based derivation function defined in NIST SP 800-90Ar1 10.3.1.
+     * The function is used inside Hash_DRBG, and can also be used as an
+     * approved conditioning function as described in 800-90B 6.4.2.2.
+     *
+     * @param digest a {@code MessageDigest} object in reset state
+     * @param outLen {@link MessageDigest#getDigestLength} of {@code digest}
+     * @param requested requested output length, in bytes
+     * @param inputs input data
+     * @return the condensed/expanded output
+     */
+    public static byte[] hashDf(MessageDigest digest, int outLen,
+                                int requested, byte[]... inputs) {
+        int len = (requested + outLen - 1) / outLen;
+        byte[] temp = new byte[len * outLen];
+        int counter = 1;
+
+        for (int i=0; i<len; i++) {
+            digest.update((byte) counter);
+            digest.update((byte)(requested >> 21)); // requested*8 as int32
+            digest.update((byte)(requested >> 13));
+            digest.update((byte)(requested >> 5));
+            digest.update((byte)(requested << 3));
+            for (byte[] input : inputs) {
+                digest.update(input);
+            }
+            try {
+                digest.digest(temp, i * outLen, outLen);
+            } catch (DigestException e) {
+                throw new AssertionError("will not happen", e);
+            }
+            counter++;
+        }
+        return temp.length == requested? temp: Arrays.copyOf(temp, requested);
+    }
+
+    // This method is used by both instantiation and reseeding.
+    @Override
+    protected final void hashReseedInternal(byte[] input) {
+
+        // 800-90Ar1 10.1.1.2: Instantiate Process.
+        // 800-90Ar1 10.1.1.3: Reseed Process.
+        byte[] seed;
+
+        // Step 2: seed = Hash_df (seed_material, seedlen).
+        if (v != null) {
+            // Step 1 of 10.1.1.3: Prepend 0x01 || V
+            seed = hashDf(seedLen, ONE, v, input);
+        } else {
+            seed = hashDf(seedLen, input);
+        }
+
+        // Step 3. V = seed.
+        v = seed;
+
+        // Step 4. C = Hash_df ((0x00 || V), seedlen).
+        c = hashDf(seedLen, ZERO, v);
+
+        // Step 5. reseed_counter = 1.
+        reseedCounter = 1;
+
+        //status();
+
+        // Step 6: Return
+    }
+
+    private void status() {
+        if (debug != null) {
+            debug.println(this, "V = " + hex(v));
+            debug.println(this, "C = " + hex(c));
+            debug.println(this, "reseed counter = " + reseedCounter);
+        }
+    }
+
+    /**
+     * Adds byte arrays into an existing one.
+     *
+     * @param out existing array
+     * @param data more arrays, can be of different length
+     */
+    private static void addBytes(byte[] out, int len, byte[]... data) {
+        for (byte[] d: data) {
+            int dlen = d.length;
+            int carry = 0;
+            for (int i = 0; i < len; i++) {
+                int sum = (out[len - i - 1] & 0xff) + carry;
+                if (i < dlen) {
+                    sum += (d[dlen - i - 1] & 0xff);
+                }
+                out[len - i - 1] = (byte) sum;
+                carry = sum >> 8;
+                if (i >= dlen - 1 && carry == 0) break;
+            }
+        }
+    }
+
+    /**
+     * Generates a user-specified number of random bytes.
+     *
+     * @param result the array to be filled in with random bytes.
+     */
+    @Override
+    public final synchronized void generateAlgorithm(
+            byte[] result, byte[] additionalInput) {
+
+        if (debug != null) {
+            debug.println(this, "generateAlgorithm");
+        }
+
+        // 800-90Ar1 10.1.1.4: Hash_DRBG_Generate Process
+
+        // Step 1: Check reseed_counter. Will not fail. Already checked in
+        // AbstractDrbg#engineNextBytes.
+
+        // Step 2: additional_input
+        if (additionalInput != null) {
+            digest.update((byte)2);
+            digest.update(v);
+            digest.update(additionalInput);
+            addBytes(v, seedLen, digest.digest());
+        }
+
+        // Step 3. Hashgen (requested_number_of_bits, V).
+        hashGen(result, result.length, v);
+
+        // Step 4. H = Hash (0x03 || V).
+        digest.update((byte)3);
+        digest.update(v);
+        byte[] h = digest.digest();
+
+        // Step 5. V = (V + H + C + reseed_counter) mod 2seedlen.
+        byte[] rcBytes;
+        if (reseedCounter < 256) {
+            rcBytes = new byte[]{(byte)reseedCounter};
+        } else {
+            rcBytes = BigInteger.valueOf(reseedCounter).toByteArray();
+        }
+        addBytes(v, seedLen, h, c, rcBytes);
+
+        // Step 6. reseed_counter = reseed_counter + 1.
+        reseedCounter++;
+
+        //status();
+
+        // Step 7: Return.
+    }
+
+    // 800-90Ar1 10.1.1.4: Hashgen
+    private void hashGen(byte[] output, int len, byte[] v) {
+
+        // Step 1. m
+        int m = (len + outLen - 1) / outLen;
+
+        // Step 2. data = V
+        byte[] data = v;
+
+        // Step 3: W is output not filled
+
+        // Step 4: For i = 1 to m
+        for (int i = 0; i < m; i++) {
+            int tailLen = len - i * outLen;
+            if (tailLen < outLen) {
+                // Step 4.1 w = Hash (data).
+                // Step 4.2 W = W || w.
+                System.arraycopy(digest.digest(data), 0, output, i * outLen,
+                        tailLen);
+            } else {
+                try {
+                    // Step 4.1 w = Hash (data).
+                    digest.update(data);
+                    // Step 4.2 digest into right position, no need to cat
+                    digest.digest(output, i*outLen, outLen);
+                } catch (DigestException e) {
+                    throw new AssertionError("will not happen", e);
+                }
+            }
+            // Unless this is the last around, we will need to increment data.
+            // but we cannot change v, so a copy is made.
+            if (i != m - 1) {
+                if (data == v) {
+                    data = Arrays.copyOf(v, v.length);
+                }
+                // Step 4.3 data = (data + 1) mod 2^seedlen.
+                addBytes(data, seedLen, ONE);
+            }
+        }
+
+        // Step 5: No need to truncate
+        // Step 6: Return
+    }
+
+    private void readObject(java.io.ObjectInputStream s)
+            throws IOException, ClassNotFoundException {
+        s.defaultReadObject ();
+        initEngine();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/HmacDrbg.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,203 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandomParameters;
+import java.util.Arrays;
+
+public class HmacDrbg extends AbstractHashDrbg {
+
+    private static final long serialVersionUID = 9L;
+
+    private transient Mac mac;
+
+    private String macAlg;
+
+    private transient byte[] v;
+    private transient byte[] k;
+
+    public HmacDrbg(SecureRandomParameters params) {
+        mechName = "HMAC_DRBG";
+        configure(params);
+    }
+
+    private void status() {
+        if (debug != null) {
+            debug.println(this, "V = " + hex(v));
+            debug.println(this, "Key = " + hex(k));
+            debug.println(this, "reseed counter = " + reseedCounter);
+        }
+    }
+
+    // 800-90Ar1 10.1.2.2: HMAC_DRBG Update Process
+    private void update(byte[]... inputs) {
+        try {
+            // Step 1. K = HMAC (K, V || 0x00 || provided_data).
+            mac.init(new SecretKeySpec(k, macAlg));
+            mac.update(v);
+            mac.update((byte) 0);
+            for (byte[] input: inputs) {
+                mac.update(input);
+            }
+            k = mac.doFinal();
+
+            // Step 2. V = HMAC (K, V).
+            mac.init(new SecretKeySpec(k, macAlg));
+            v = mac.doFinal(v);
+
+            if (inputs.length != 0) {
+                // Step 4. K = HMAC (K, V || 0x01 || provided_data).
+                mac.update(v);
+                mac.update((byte) 1);
+                for (byte[] input: inputs) {
+                    mac.update(input);
+                }
+                k = mac.doFinal();
+
+                // Step 5. V=HMAC(K,V).
+                mac.init(new SecretKeySpec(k, macAlg));
+                v = mac.doFinal(v);
+            } // else Step 3
+
+            // Step 6. Return
+        } catch (InvalidKeyException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * This call, used by the constructors, instantiates the digest.
+     */
+    @Override
+    protected void initEngine() {
+        macAlg = "HmacSHA" + algorithm.substring(4);
+        try {
+            mac = Mac.getInstance(macAlg, "SunJCE");
+        } catch (NoSuchProviderException | NoSuchAlgorithmException e) {
+            // Fallback to any available.
+            try {
+                mac = Mac.getInstance(macAlg);
+            } catch (NoSuchAlgorithmException exc) {
+                throw new InternalError(
+                    "internal error: " + macAlg + " not available.", exc);
+            }
+        }
+    }
+
+    // This method is used by both instantiation and reseeding.
+    @Override
+    protected final void hashReseedInternal(byte[] input) {
+
+        // 800-90Ar1 10.1.2.3: Instantiate Process.
+        // 800-90Ar1 10.1.2.4: Reseed Process.
+        if (v == null) {
+            k = new byte[outLen];
+            v = new byte[outLen];
+            Arrays.fill(v, (byte) 1);
+        }
+
+        // Step 2: HMAC_DRBG_Update
+        update(input);
+
+        // Step 3: reseed_counter = 1.
+        reseedCounter = 1;
+        //status();
+
+        // Step 4: Return
+    }
+
+    /**
+     * Generates a user-specified number of random bytes.
+     *
+     * @param result the array to be filled in with random bytes.
+     */
+    @Override
+    public synchronized void generateAlgorithm(
+            byte[] result, byte[] additionalInput) {
+
+        if (debug != null) {
+            debug.println(this, "generateAlgorithm");
+        }
+
+        // 800-90Ar1 10.1.2.5: HMAC_DRBG_Generate Process
+
+        // Step 1: Check reseed_counter. Will not fail. Already checked in
+        // AbstractDrbg#engineNextBytes.
+
+        // Step 2. HMAC_DRBG_Update
+        if (additionalInput != null) {
+            update(additionalInput);
+        }
+
+        // Step 3. temp = Null.
+        int pos = 0;
+
+        // Step 4. Loop
+        while (pos < result.length) {
+            int tailLen = result.length - pos;
+
+            // Step 4.1 V = HMAC (Key, V).
+            try {
+                mac.init(new SecretKeySpec(k, macAlg));
+            } catch (InvalidKeyException e) {
+                throw new InternalError(e);
+            }
+            v = mac.doFinal(v);
+            // Step 4.2 temp = temp || V.
+            System.arraycopy(v, 0, result, pos,
+                    tailLen > outLen ? outLen : tailLen);
+            pos += outLen;
+        }
+
+        // Step 5: No need to truncate
+
+        // Step 6. HMAC_DRBG_Update (additional_input, Key, V).
+        if (additionalInput != null) {
+            update(additionalInput);
+        } else {
+            update();
+        }
+
+        // Step 7. reseed_counter = reseed_counter + 1.
+        reseedCounter++;
+
+        //status();
+
+        // Step 8. Return
+    }
+
+    private void readObject(java.io.ObjectInputStream s)
+            throws IOException, ClassNotFoundException {
+        s.defaultReadObject ();
+        initEngine();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,73 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.DrbgParameters;
+import java.security.SecureRandomParameters;
+
+/**
+ * Extra non-standard parameters that can be used by DRBGs.
+ */
+public class MoreDrbgParameters implements SecureRandomParameters {
+
+    final String mech;
+    final String algorithm;
+    final EntropySource es;
+    final byte[] nonce;
+    final boolean usedf;
+    final DrbgParameters.Instantiation config;
+
+    /**
+     * Creates a new {@code MoreDrbgParameters} object.
+     *
+     * @param es the {@link EntropySource} to use. If set to {@code null},
+     *           a default entropy source will be used.
+     * @param mech mech name. If set to {@code null}, the one in
+     *             securerandom.drbg.config is used. This argument is ignored
+     *             when passing to HashDrbg/HmacDrbg/CtrDrbg.
+     * @param algorithm the requested algorithm to use. If set to {@code null},
+     *                  the algorithm will be decided by strength.
+     * @param nonce the nonce to use. If set to {@code null},
+     *              a nonce will be assigned.
+     * @param usedf whether a derivation function should be used
+     * @param config a {@link DrbgParameters.Instantiation} object
+     */
+    public MoreDrbgParameters(EntropySource es, String mech,
+                              String algorithm, byte[] nonce, boolean usedf,
+                              DrbgParameters.Instantiation config) {
+        this.mech = mech;
+        this.algorithm = algorithm;
+        this.es = es;
+        this.nonce = nonce;
+        this.usedf = usedf;
+        this.config = config;
+    }
+
+    @Override
+    public String toString() {
+        return mech + "," + algorithm + "," + usedf + "," + config;
+    }
+}
--- a/src/java.base/share/classes/sun/security/provider/SHA5.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/sun/security/provider/SHA5.java	Fri May 06 11:38:44 2016 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -25,9 +25,7 @@
 
 package sun.security.provider;
 
-import java.security.*;
 import java.util.Objects;
-import java.math.BigInteger;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
 import static sun.security.provider.ByteArrayAccess.*;
@@ -118,7 +116,14 @@
         i2bBig4((int)bitsProcessed, buffer, 124);
         implCompress(buffer, 0);
 
-        l2bBig(state, 0, out, ofs, engineGetDigestLength());
+        int len = engineGetDigestLength();
+        if (len == 28) {
+            // Special case for SHA-512/224
+            l2bBig(state, 0, out, ofs, 24);
+            i2bBig4((int)(state[3] >> 32), out, ofs + 24);
+        } else {
+            l2bBig(state, 0, out, ofs, len);
+        }
     }
 
     /**
@@ -306,4 +311,31 @@
             super("SHA-384", 48, INITIAL_HASHES);
         }
     }
+    public static final class SHA512_224 extends SHA5 {
+
+        private static final long[] INITIAL_HASHES = {
+                0x8C3D37C819544DA2L, 0x73E1996689DCD4D6L,
+                0x1DFAB7AE32FF9C82L, 0x679DD514582F9FCFL,
+                0x0F6D2B697BD44DA8L, 0x77E36F7304C48942L,
+                0x3F9D85A86A1D36C8L, 0x1112E6AD91D692A1L
+        };
+
+        public SHA512_224() {
+            super("SHA-512/224", 28, INITIAL_HASHES);
+        }
+    }
+
+    public static final class SHA512_256 extends SHA5 {
+
+        private static final long[] INITIAL_HASHES = {
+                0x22312194FC2BF72CL, 0x9F555FA3C84C64C2L,
+                0x2393B86B6F53B151L, 0x963877195940EABDL,
+                0x96283EE2A88EFFE3L, 0xBE5E1E2553863992L,
+                0x2B0199FC2C85B8AAL, 0x0EB72DDC81C52CA2L
+        };
+
+        public SHA512_256() {
+            super("SHA-512/256", 32, INITIAL_HASHES);
+        }
+    }
 }
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java	Fri May 06 11:38:44 2016 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -97,6 +97,9 @@
             map.put("SecureRandom.NativePRNG",
                 "sun.security.provider.NativePRNG");
         }
+
+        map.put("SecureRandom.DRBG", "sun.security.provider.DRBG");
+
         map.put("SecureRandom.SHA1PRNG",
              "sun.security.provider.SecureRandom");
         if (nativeAvailable && !useNativePRNG) {
@@ -199,6 +202,14 @@
         map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
         map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3",
                 "SHA-512");
+        map.put("MessageDigest.SHA-512/224", "sun.security.provider.SHA5$SHA512_224");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.5", "SHA-512/224");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.5",
+                "SHA-512/224");
+        map.put("MessageDigest.SHA-512/256", "sun.security.provider.SHA5$SHA512_256");
+        map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.6", "SHA-512/256");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.6",
+                "SHA-512/256");
 
         /*
          * Algorithm Parameter Generator engines
--- a/src/java.base/share/classes/sun/security/util/Debug.java	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/classes/sun/security/util/Debug.java	Fri May 06 11:38:44 2016 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -87,6 +87,7 @@
         System.err.println("pkcs12        PKCS12 KeyStore debugging");
         System.err.println("sunpkcs11     SunPKCS11 provider debugging");
         System.err.println("scl           permissions SecureClassLoader assigns");
+        System.err.println("securerandom  SecureRandom");
         System.err.println("ts            timestamping");
         System.err.println();
         System.err.println("The following can be used with access:");
@@ -175,6 +176,16 @@
     }
 
     /**
+     * print a message to stderr that is prefixed with the prefix
+     * created from the call to getInstance and obj.
+     */
+    public void println(Object obj, String message)
+    {
+        System.err.println(prefix + " [" + obj.getClass().getSimpleName() +
+                "@" + System.identityHashCode(obj) + "]: "+message);
+    }
+
+    /**
      * print a blank line to stderr that is prefixed with the prefix.
      */
 
--- a/src/java.base/share/conf/security/java.security	Thu May 05 16:36:06 2016 -0700
+++ b/src/java.base/share/conf/security/java.security	Fri May 06 11:38:44 2016 +0800
@@ -120,30 +120,30 @@
 #
 # Sun Provider SecureRandom seed source.
 #
-# Select the primary source of seed data for the "SHA1PRNG" and
-# "NativePRNG" SecureRandom implementations in the "Sun" provider.
+# Select the primary source of seed data for the "NativePRNG", "SHA1PRNG"
+# and "DRBG" SecureRandom implementations in the "Sun" provider.
 # (Other SecureRandom implementations might also use this property.)
 #
 # On Unix-like systems (for example, Solaris/Linux/MacOS), the
-# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
+# "NativePRNG", "SHA1PRNG" and "DRBG" implementations obtains seed data from
 # special device files such as file:/dev/random.
 #
 # On Windows systems, specifying the URLs "file:/dev/random" or
 # "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
-# mechanism for SHA1PRNG.
+# mechanism for SHA1PRNG and DRBG.
 #
 # By default, an attempt is made to use the entropy gathering device
 # specified by the "securerandom.source" Security property.  If an
 # exception occurs while accessing the specified URL:
 #
-#     SHA1PRNG:
-#         the traditional system/thread activity algorithm will be used.
-#
 #     NativePRNG:
 #         a default value of /dev/random will be used.  If neither
 #         are available, the implementation will be disabled.
 #         "file" is the only currently supported protocol type.
 #
+#     SHA1PRNG and DRBG:
+#         the traditional system/thread activity algorithm will be used.
+#
 # The entropy gathering device can also be specified with the System
 # property "java.security.egd". For example:
 #
@@ -154,7 +154,7 @@
 #
 # In addition, if "file:/dev/random" or "file:/dev/urandom" is
 # specified, the "NativePRNG" implementation will be more preferred than
-# SHA1PRNG in the Sun provider.
+# DRBG and SHA1PRNG in the Sun provider.
 #
 securerandom.source=file:/dev/random
 
@@ -169,13 +169,79 @@
 # entries.
 #
 #ifdef windows
-securerandom.strongAlgorithms=Windows-PRNG:SunMSCAPI,SHA1PRNG:SUN
+securerandom.strongAlgorithms=Windows-PRNG:SunMSCAPI,DRBG:SUN
 #endif
 #ifndef windows
-securerandom.strongAlgorithms=NativePRNGBlocking:SUN
+securerandom.strongAlgorithms=NativePRNGBlocking:SUN,DRBG:SUN
 #endif
 
 #
+# Sun provider DRBG configuration and default instantiation request.
+#
+# NIST SP 800-90Ar1 lists several DRBG mechanisms. Each can be configured
+# with a DRBG algorithm name, and can be instantiated with a security strength,
+# prediction resistance support, etc. This property defines the configuration
+# and the default instantiation request of "DRBG" SecureRandom implementations
+# in the SUN provider. (Other DRBG implementations can also use this property.)
+# Applications can request different instantiation parameters like security
+# strength, capability, personalization string using one of the
+# getInstance(...,SecureRandomParameters,...) methods with a
+# DrbgParameters.Instantiation argument, but other settings such as the
+# mechanism and DRBG algorithm names are not currently configurable by any API.
+#
+# Please note that the SUN implementation of DRBG always supports reseeding.
+#
+# The value of this property is a comma-separated list of all configurable
+# aspects. The aspects can appear in any order but the same aspect can only
+# appear at most once. Its BNF-style definition is:
+#
+#   Value:
+#     aspect { "," aspect }
+#
+#   aspect:
+#     mech_name | algorithm_name | strength | capability | df
+#
+#   // The DRBG mechanism to use. Default "Hash_DRBG"
+#   mech_name:
+#     "Hash_DRBG" | "HMAC_DRBG" | "CTR_DRBG"
+#
+#   // The DRBG algorithm name. The "SHA-***" names are for Hash_DRBG and
+#   // HMAC_DRBG, default "SHA-256". "3KeyTDEA" and "AES-***" names are for
+#   // CTR_DRBG, default "AES-128" when using the limited cryptographic
+#   // or "AES-256" when using the unlimited.
+#   algorithm_name:
+#     "SHA-1" | "SHA-224" | "SHA-512/224" | "SHA-256" |
+#     "SHA-512/256" | "SHA-384" | "SHA-512" |
+#     "3KeyTDEA" | "AES-128" | "AES-192" | "AES-256"
+#
+#   // Security strength requested. Default "128", or "112"
+#   // if mech_name is CTR_DRBG and algorithm_name is "3KeyTDEA"
+#   strength:
+#     "112" | "128" | "192" | "256"
+#
+#   // Prediction resistance and reseeding request. Default "none"
+#   //  "pr_and_reseed" - Both prediction resistance and reseeding
+#   //                    support requested
+#   //  "reseed_only"   - Only reseeding support requested
+#   //  "none"          - Neither prediction resistance not reseeding
+#   //                    support requested
+#   pr:
+#     "pr_and_reseed" | "reseed_only" | "none"
+#
+#   // Whether a derivation function should be used. only applicable
+#   // to CTR_DRBG. Default "use_df"
+#   df:
+#     "use_df" | "no_df"
+#
+# Examples,
+#   securerandom.drbg.config=Hash_DRBG,SHA-1,112,none
+#   securerandom.drbg.config=CTR_DRBG,AES-256,192,pr_and_reseed,use_df
+#
+# The default value is an empty string, which is equivalent to
+#   securerandom.drbg.config=Hash_DRBG,SHA-256,128,none
+securerandom.drbg.config=
+
+#
 # Class to instantiate as the javax.security.auth.login.Configuration
 # provider.
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Mac/HmacSHA512.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,79 @@
+/*
+ * 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 jdk.testlibrary.Asserts;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Arrays;
+
+/**
+ * @test
+ * @bug 8051408
+ * @library /lib/testlibrary
+ * @summary testing HmacSHA512/224 and HmacSHA512/256.
+ */
+public class HmacSHA512 {
+    public static void main(String[] args) throws Exception {
+
+        Mac mac;
+
+        // Test vectors obtained from
+        // https://groups.google.com/d/msg/sci.crypt/OolWgsgQD-8/IUR2KhCcfEkJ
+        mac = Mac.getInstance("HmacSHA512/224");
+        mac.init(new SecretKeySpec(xeh("4a656665"), "HmacSHA512/224"));
+        mac.update("what do ya want for nothing?".getBytes());
+        Asserts.assertTrue(Arrays.equals(mac.doFinal(),
+                xeh("4a530b31a79ebcce36916546317c45f247d83241dfb818fd37254bde")));
+
+        mac = Mac.getInstance("HmacSHA512/256");
+        mac.init(new SecretKeySpec(xeh("4a656665"), "HmacSHA512/256"));
+        mac.update("what do ya want for nothing?".getBytes());
+        Asserts.assertTrue(Arrays.equals(mac.doFinal(),
+                xeh("6df7b24630d5ccb2ee335407081a87188c221489768fa2020513b2d593359456")));
+
+        mac = Mac.getInstance("HmacSHA512/224");
+        mac.init(new SecretKeySpec(xeh("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+                "HmacSHA512/224"));
+        mac.update("Hi There".getBytes());
+        Asserts.assertTrue(Arrays.equals(mac.doFinal(),
+                xeh("b244ba01307c0e7a8ccaad13b1067a4cf6b961fe0c6a20bda3d92039")));
+
+        mac = Mac.getInstance("HmacSHA512/256");
+        mac.init(new SecretKeySpec(xeh("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+                "HmacSHA512/256"));
+        mac.update("Hi There".getBytes());
+        Asserts.assertTrue(Arrays.equals(mac.doFinal(),
+                xeh("9f9126c3d9c3c330d760425ca8a217e31feae31bfe70196ff81642b868402eab")));
+    }
+
+    static byte[] xeh(String in) {
+        in = in.replaceAll(" ", "");
+        int len = in.length() / 2;
+        byte[] out = new byte[len];
+        for (int i = 0; i < len; i++) {
+            out[i] = (byte)Integer.parseInt(in.substring(i * 2, i * 2 + 2), 16);
+        }
+        return out;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/security/SecureRandom/DrbgParametersSpec.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,104 @@
+/*
+ * 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
+ * @summary Make sure DrbgParameters coded as specified
+ * @library /test/lib/share/classes
+ */
+
+import jdk.test.lib.Asserts;
+
+import java.security.DrbgParameters;
+import java.util.Arrays;
+
+import static java.security.DrbgParameters.Capability.*;
+
+public class DrbgParametersSpec {
+
+    public static void main(String args[]) throws Exception {
+
+        byte[] p, np1, np2;
+
+        // Capability
+        Asserts.assertTrue(PR_AND_RESEED.supportsPredictionResistance());
+        Asserts.assertTrue(PR_AND_RESEED.supportsReseeding());
+        Asserts.assertFalse(RESEED_ONLY.supportsPredictionResistance());
+        Asserts.assertTrue(RESEED_ONLY.supportsReseeding());
+        Asserts.assertFalse(NONE.supportsPredictionResistance());
+        Asserts.assertFalse(NONE.supportsReseeding());
+
+        // Instantiation
+        p = "Instantiation".getBytes();
+        DrbgParameters.Instantiation ins = DrbgParameters
+                .instantiation(192, RESEED_ONLY, p);
+        Asserts.assertTrue(ins.getStrength() == 192);
+        Asserts.assertTrue(ins.getCapability() == RESEED_ONLY);
+        np1 = ins.getPersonalizationString();
+        np2 = ins.getPersonalizationString();
+        // Getter outputs have same content but not the same object
+        Asserts.assertTrue(Arrays.equals(np1, p));
+        Asserts.assertTrue(Arrays.equals(np2, p));
+        Asserts.assertNE(np1, np2);
+        // Changes to original input has no affect on object
+        p[0] = 'X';
+        np2 = ins.getPersonalizationString();
+        Asserts.assertTrue(Arrays.equals(np1, np2));
+
+        ins = DrbgParameters.instantiation(-1, NONE, null);
+        Asserts.assertNull(ins.getPersonalizationString());
+
+        // NextBytes
+        p = "NextBytes".getBytes();
+        DrbgParameters.NextBytes nb = DrbgParameters
+                .nextBytes(192, true, p);
+        Asserts.assertTrue(nb.getStrength() == 192);
+        Asserts.assertTrue(nb.getPredictionResistance());
+        np1 = nb.getAdditionalInput();
+        np2 = nb.getAdditionalInput();
+        // Getter outputs have same content but not the same object
+        Asserts.assertTrue(Arrays.equals(np1, p));
+        Asserts.assertTrue(Arrays.equals(np2, p));
+        Asserts.assertNE(np1, np2);
+        // Changes to original input has no affect on object
+        p[0] = 'X';
+        np2 = nb.getAdditionalInput();
+        Asserts.assertTrue(Arrays.equals(np1, np2));
+
+        // Reseed
+        p = "Reseed".getBytes();
+        DrbgParameters.Reseed rs = DrbgParameters
+                .reseed(true, p);
+        Asserts.assertTrue(rs.getPredictionResistance());
+        np1 = rs.getAdditionalInput();
+        np2 = rs.getAdditionalInput();
+        // Getter outputs have same content but not the same object
+        Asserts.assertTrue(Arrays.equals(np1, p));
+        Asserts.assertTrue(Arrays.equals(np2, p));
+        Asserts.assertNE(np1, np2);
+        // Changes to original input has no affect on object
+        p[0] = 'X';
+        np2 = rs.getAdditionalInput();
+        Asserts.assertTrue(Arrays.equals(np1, np2));
+    }
+}
--- a/test/java/security/SecureRandom/Serialize.java	Thu May 05 16:36:06 2016 -0700
+++ b/test/java/security/SecureRandom/Serialize.java	Fri May 06 11:38:44 2016 +0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -31,16 +31,73 @@
 
 public class Serialize {
 
-    public static void main(String args[]) throws IOException {
+    public static void main(String args[]) throws Exception {
+        for (String alg: new String[]{
+                "SHA1PRNG", "DRBG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG",
+                "Hash_DRBG,SHA-512,192,pr_and_reseed"}) {
 
-        FileOutputStream fos = new FileOutputStream("t.tmp");
-        ObjectOutputStream oos = new ObjectOutputStream(fos);
+            System.out.println("Testing " + alg);
+            SecureRandom s1;
 
-        SecureRandom secRandom = new SecureRandom();
+            // A SecureRandom can be s11ned and des11ned at any time.
 
-        // serialize and write out
-        oos.writeObject(secRandom);
-        oos.flush();
-        oos.close();
+            // Brand new.
+            s1 = getInstance(alg);
+            revive(s1).nextInt();
+            if (alg.contains("DRBG")) {
+                revive(s1).reseed();
+            }
+
+            // Used
+            s1 = getInstance(alg);
+            s1.nextInt();    // state set
+            revive(s1).nextInt();
+            if (alg.contains("DRBG")) {
+                revive(s1).reseed();
+            }
+
+            // Automatically reseeded
+            s1 = getInstance(alg);
+            if (alg.contains("DRBG")) {
+                s1.reseed();
+            }
+            revive(s1).nextInt();
+            if (alg.contains("DRBG")) {
+                revive(s1).reseed();
+            }
+
+            // Manually seeded
+            s1 = getInstance(alg);
+            s1.setSeed(1L);
+            revive(s1).nextInt();
+            if (alg.contains("DRBG")) {
+                revive(s1).reseed();
+            }
+        }
+    }
+
+    private static SecureRandom getInstance(String alg) throws Exception {
+        if (alg.equals("SHA1PRNG") || alg.equals("DRBG")) {
+            return SecureRandom.getInstance(alg);
+        } else {
+            String old = Security.getProperty("securerandom.drbg.config");
+            try {
+                Security.setProperty("securerandom.drbg.config", alg);
+                return SecureRandom.getInstance("DRBG");
+            } finally {
+                Security.setProperty("securerandom.drbg.config", old);
+            }
+        }
+    }
+
+    private static SecureRandom revive(SecureRandom oldOne) throws Exception {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        new ObjectOutputStream(bout).writeObject(oldOne);
+        SecureRandom newOne = (SecureRandom) new ObjectInputStream(
+                new ByteArrayInputStream(bout.toByteArray())).readObject();
+        if (!oldOne.toString().equals(newOne.toString())) {
+            throw new Exception(newOne + " is not " + oldOne);
+        }
+        return newOne;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/MessageDigest/SHA512.java	Fri May 06 11:38:44 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 jdk.testlibrary.Asserts;
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+/**
+ * @test
+ * @bug 8051408
+ * @library /lib/testlibrary
+ * @summary testing SHA-512/224 and SHA-512/256.
+ */
+public class SHA512 {
+    public static void main(String[] args) throws Exception {
+
+        MessageDigest md;
+
+        // Test vectors obtained from
+        // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_224.pdf
+        md = MessageDigest.getInstance("SHA-512/224");
+        Asserts.assertTrue(Arrays.equals(md.digest("abc".getBytes()),
+            xeh("4634270F 707B6A54 DAAE7530 460842E2 0E37ED26 5CEEE9A4 3E8924AA")));
+        Asserts.assertTrue(Arrays.equals(md.digest((
+                "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
+                "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu").getBytes()),
+            xeh("23FEC5BB 94D60B23 30819264 0B0C4533 35D66473 4FE40E72 68674AF9")));
+
+        // Test vectors obtained from
+        // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_256.pdf
+        md = MessageDigest.getInstance("SHA-512/256");
+        Asserts.assertTrue(Arrays.equals(md.digest("abc".getBytes()),
+            xeh("53048E26 81941EF9 9B2E29B7 6B4C7DAB E4C2D0C6 34FC6D46 E0E2F131 07E7AF23")));
+        Asserts.assertTrue(Arrays.equals(md.digest((
+                "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
+                "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu").getBytes()),
+            xeh("3928E184 FB8690F8 40DA3988 121D31BE 65CB9D3E F83EE614 6FEAC861 E19B563A")));
+    }
+
+    static byte[] xeh(String in) {
+        in = in.replaceAll(" ", "");
+        int len = in.length() / 2;
+        byte[] out = new byte[len];
+        for (int i = 0; i < len; i++) {
+            out[i] = (byte)Integer.parseInt(in.substring(i * 2, i * 2 + 2), 16);
+        }
+        return out;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/SecureRandom/AbstractDrbgSpec.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,310 @@
+/*
+ * 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/test/sun/security/provider/SecureRandom/AutoReseed.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,54 @@
+/*
+ * 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 java.security.SecureRandom;
+import java.security.Security;
+
+/**
+ * @test
+ * @bug 8051408
+ * @summary make sure nextBytes etc can be called before setSeed
+ */
+public class AutoReseed {
+
+    public static void main(String[] args) throws Exception {
+        SecureRandom sr;
+        String old = Security.getProperty("securerandom.drbg.config");
+        try {
+            for (String mech :
+                    new String[]{"Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) {
+                System.out.println("Testing " + mech + "...");
+                Security.setProperty("securerandom.drbg.config", mech);
+
+                // Check auto reseed works
+                sr = SecureRandom.getInstance("DRBG");
+                sr.nextInt();
+                sr = SecureRandom.getInstance("DRBG");
+                sr.reseed();
+                sr = SecureRandom.getInstance("DRBG");
+                sr.generateSeed(10);
+            }
+        } finally {
+            Security.setProperty("securerandom.drbg.config", old);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/SecureRandom/CommonSeeder.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,132 @@
+/*
+ * 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.AbstractDrbg;
+import sun.security.provider.EntropySource;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.security.DrbgParameters;
+import java.security.SecureRandom;
+import java.security.Security;
+
+/**
+ * @test
+ * @bug 8051408
+ * @modules java.base/sun.security.provider
+ * @run main/othervm CommonSeeder
+ * @summary check entropy reading of DRBGs
+ */
+public class CommonSeeder {
+
+    static class MyES implements EntropySource {
+        int count = 100;
+        int lastCount = 100;
+
+        @Override
+        public byte[] getEntropy(int minEntropy, int minLength,
+                                 int maxLength, boolean pr) {
+            count--;
+            return new byte[minLength];
+        }
+
+        /**
+         * Confirms genEntropy() has been called {@code less} times
+         * since last check.
+         */
+        public void checkUsage(int less) throws Exception {
+            if (lastCount != count + less) {
+                throw new Exception(String.format(
+                        "lastCount = %d, count = %d, less = %d",
+                        lastCount, count, less));
+            }
+            lastCount = count;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        byte[] result = new byte[10];
+        MyES es = new MyES();
+
+        // Set es as the default entropy source, overriding SeedGenerator.
+        setDefaultSeeder(es);
+
+        // Nothing happened yet
+        es.checkUsage(0);
+
+        SecureRandom sr;
+        sr = SecureRandom.getInstance("DRBG");
+
+        // No entropy reading if only getInstance
+        es.checkUsage(0);
+
+        // Entropy is read at 1st nextBytes of the 1st DRBG
+        sr.nextInt();
+        es.checkUsage(1);
+
+        for (String mech : new String[]{"Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) {
+            System.out.println("Testing " + mech + "...");
+
+            // DRBG with pr_false will never read entropy again no matter
+            // if nextBytes or reseed is called.
+
+            Security.setProperty("securerandom.drbg.config", mech);
+            sr = SecureRandom.getInstance("DRBG");
+            sr.nextInt();
+            sr.reseed();
+            es.checkUsage(0);
+
+            // DRBG with pr_true always read from default entropy, and
+            // its nextBytes always reseed itself
+
+            Security.setProperty("securerandom.drbg.config",
+                    mech + ",pr_and_reseed");
+            sr = SecureRandom.getInstance("DRBG");
+
+            sr.nextInt();
+            es.checkUsage(2); // one instantiate, one reseed
+            sr.nextInt();
+            es.checkUsage(1); // one reseed in nextBytes
+            sr.reseed();
+            es.checkUsage(1); // one reseed
+            sr.nextBytes(result, DrbgParameters.nextBytes(-1, false, null));
+            es.checkUsage(0); // pr_false for this call
+            sr.nextBytes(result, DrbgParameters.nextBytes(-1, true, null));
+            es.checkUsage(1); // pr_true for this call
+            sr.reseed(DrbgParameters.reseed(true, null));
+            es.checkUsage(1); // reseed from es
+            sr.reseed(DrbgParameters.reseed(false, null));
+            es.checkUsage(0); // reseed from AbstractDrbg.SeederHolder.seeder
+        }
+    }
+
+    static void setDefaultSeeder(EntropySource es) throws Exception {
+        Field f = AbstractDrbg.class.getDeclaredField("defaultES");
+        f.setAccessible(true);  // no more private
+        Field f2 = Field.class.getDeclaredField("modifiers");
+        f2.setAccessible(true);
+        f2.setInt(f, f2.getInt(f) - Modifier.FINAL);    // no more final
+        f.set(null, es);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/SecureRandom/DRBGAlg.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,180 @@
+/*
+ * 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.MoreDrbgParameters;
+
+import java.security.DrbgParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.SecureRandomParameters;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static java.security.DrbgParameters.Capability.*;
+
+/**
+ * @test
+ * @bug 8051408
+ * @modules java.base/sun.security.provider
+ * @summary make sure DRBG alg can be defined and instantiated freely
+ */
+public class DRBGAlg {
+
+    public static void main(String[] args) throws Exception {
+
+        check(null, "Hash_DRBG", "SHA-256", "reseed_only", ",128");
+        check("", "Hash_DRBG", "SHA-256", "reseed_only", ",128");
+        check("sha-1", "Hash_DRBG", "SHA-1", "reseed_only", ",128");
+        check("sha-256", "Hash_DRBG", "SHA-256", "reseed_only", ",128");
+        check("SHA-3");
+        check("hash_drbg", "Hash_DRBG", "SHA-256", "reseed_only", ",128");
+        check("hmac_drbg", "HMAC_DRBG", "SHA-256", "reseed_only", ",128");
+        check("ctr_drbg", "CTR_DRBG", "AES-", "reseed_only", ",128", "use_df");
+
+        // trying all permutations
+        checkPermutations(
+                Collections.emptyList(),
+                Arrays.asList("hash_drbg","sha-512","Pr_and_Reseed","192"),
+                "Hash_DRBG", "SHA-512", "pr_and_reseed", ",192");
+
+        check("Hash_DRBG,Hmac_DRBG");
+        check("SHA-1,SHA-256");
+        check("128,256");
+        check("none,reseed_only");
+        check("use_df,no_df");
+        check("Hash_DRBG,,SHA-1");
+
+        check(null, DrbgParameters.instantiation(112, PR_AND_RESEED, null),
+                "Hash_DRBG", "SHA-256", "pr_and_reseed", ",112");
+        check(null, DrbgParameters.instantiation(256, PR_AND_RESEED, null),
+                "Hash_DRBG", "SHA-256", "pr_and_reseed", ",256");
+        check(null, DrbgParameters.instantiation(384, PR_AND_RESEED, null));
+        check("sha-1", DrbgParameters.instantiation(112, PR_AND_RESEED, null),
+                "Hash_DRBG", "SHA-1", "pr_and_reseed", ",112");
+        check("sha-1", DrbgParameters.instantiation(192, PR_AND_RESEED, null));
+        check("hash_drbg,sha-512,Pr_and_Reseed,192",
+                DrbgParameters.instantiation(112, NONE, null),
+                "Hash_DRBG", "SHA-512", "reseed_only", ",112");
+        check("hash_drbg,sha-512,Pr_and_Reseed,192",
+                DrbgParameters.instantiation(-1, NONE, null),
+                "Hash_DRBG", "SHA-512", "reseed_only", ",192");
+        // getInstance params can be stronger than definition
+        check("hash_drbg,sha-256,None,112",
+                DrbgParameters.instantiation(192, PR_AND_RESEED, null),
+                "Hash_DRBG", "SHA-256", "pr_and_reseed", ",192");
+
+        check("hash_drbg,sha-1", new MoreDrbgParameters(
+                    null, null, "sha-512", null, false,
+                    DrbgParameters.instantiation(-1, NONE, null)),
+                "Hash_DRBG", "SHA-512");
+        check("hash_drbg,sha-1", new MoreDrbgParameters(
+                    null, null, null, null, false,
+                    DrbgParameters.instantiation(-1, NONE, null)),
+                "Hash_DRBG", "SHA-1");
+        check("hash_drbg", new MoreDrbgParameters(
+                    null, "hmac_drbg", null, null, false,
+                    DrbgParameters.instantiation(-1, NONE, null)),
+                "HMAC_DRBG", "SHA-256");
+
+        check("hash_drbg,sha-1", new MoreDrbgParameters(
+                    null, null, "sha-3", null, false,
+                    DrbgParameters.instantiation(-1, NONE, null)));
+        check("hash_drbg,sha-1", new MoreDrbgParameters(
+                    null, "Unknown_DRBG", null, null, false,
+                    DrbgParameters.instantiation(-1, NONE, null)));
+    }
+
+    /**
+     * Checks all permutatins of a config. This is a recursive method and
+     * should be called with checkPermutations(empty,config,expected).
+     *
+     * @param current the current chosen aspects
+     * @param remains the remaining
+     * @param expected the expected effective config
+     * @throws Exception when check fails
+     */
+    private static void checkPermutations(List<String> current,
+            List<String> remains, String... expected) throws Exception {
+        if (remains.isEmpty()) {
+            check(current.stream().collect(Collectors.joining(",")), expected);
+        } else {
+            for (String r : remains) {
+                List<String> newCurrent = new ArrayList<>(current);
+                newCurrent.add(r);
+                List<String> newRemains = new ArrayList<>(remains);
+                newRemains.remove(r);
+                checkPermutations(newCurrent, newRemains, expected);
+            }
+        }
+    }
+
+    /**
+     * Checks DRBG definition for getInstance(alg, params).
+     *
+     * @param define DRBG
+     * @param params getInstance request (null if none)
+     * @param expected expected actual instantiate params, empty if should fail
+     */
+    static void check(String define, SecureRandomParameters params,
+                      String... expected) throws Exception {
+        System.out.println("Testing " + define + " with " + params + "...");
+        String old = Security.getProperty("securerandom.drbg.config");
+        if (define != null) {
+            Security.setProperty("securerandom.drbg.config", define);
+        }
+        try {
+            String result = params != null ?
+                    SecureRandom.getInstance("DRBG", params).toString() :
+                    SecureRandom.getInstance("DRBG").toString();
+            System.out.println("Result " + result);
+            if (expected.length == 0) {
+                throw new Exception("should fail");
+            }
+            for (String s : expected) {
+                if (!result.contains(s)) {
+                    throw new Exception(result);
+                }
+            }
+        } catch (NoSuchAlgorithmException e) {
+            System.out.println("Result NSAE");
+            if (expected.length > 0) {
+                throw e;
+            }
+        } finally {
+            Security.setProperty("securerandom.drbg.config", old);
+        }
+    }
+
+    /**
+     * Checks DRBG definition for getInstance(alg).
+     *
+     * @param define DRBG
+     * @param expected expected actual instantiate params, empty if should fail
+     */
+    static void check(String define, String... expected) throws Exception {
+        check(define, null, expected);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/SecureRandom/DrbgCavp.java	Fri May 06 11:38:44 2016 +0800
@@ -0,0 +1,422 @@
+/*
+ * 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.EntropySource;
+import sun.security.provider.MoreDrbgParameters;
+
+import javax.crypto.Cipher;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.lang.*;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.DrbgParameters;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Queue;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+
+import static java.security.DrbgParameters.Capability.*;
+
+/**
+ * The Known-output DRBG test. The test vector can be obtained from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip.
+ *
+ * Manually run this test with
+ *
+ *   java DrbgCavp drbgtestvectors.zip
+ *
+ */
+public class DrbgCavp {
+
+    // the current nonce
+    private static byte[] nonce;
+
+    // A buffer to store test materials for the current call and
+    // can be printed out of an error occurs.
+    private static ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+    // Save err for restoring
+    private static PrintStream err = System.err;
+
+    private static final int AES_LIMIT;
+
+    static {
+        try {
+            AES_LIMIT = Cipher.getMaxAllowedKeyLength("AES");
+        } catch (Exception e) {
+            // should not happen
+            throw new AssertionError("Cannot detect AES");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length != 1) {
+            System.out.println("Usage: java DrbgCavp drbgtestvectors.zip");
+            return;
+        }
+        File tv = new File(args[0]);
+
+        EntropySource es = new TestEntropySource();
+        System.setErr(new PrintStream(bout));
+
+        // The testsuite is a zip file containing more zip files for different
+        // working modes. Each internal zip file contains test materials for
+        // different mechanisms.
+
+        try (ZipFile zf = new ZipFile(tv)) {
+            String[] modes = {"no_reseed", "pr_false", "pr_true"};
+            for (String mode : modes) {
+                try (ZipInputStream zis = new ZipInputStream(zf.getInputStream(
+                        zf.getEntry("drbgvectors_" + mode + ".zip")))) {
+                    while (true) {
+                        ZipEntry ze = zis.getNextEntry();
+                        if (ze == null) {
+                            break;
+                        }
+                        String fname = ze.getName();
+                        if (fname.equals("Hash_DRBG.txt")
+                                || fname.equals("HMAC_DRBG.txt")
+                                || fname.equals("CTR_DRBG.txt")) {
+                            String algorithm
+                                    = fname.substring(0, fname.length() - 4);
+                            test(mode, algorithm, es, zis);
+                        }
+                    }
+                }
+            }
+        } finally {
+            System.setErr(err);
+        }
+    }
+
+    /**
+     * A special entropy source you can set entropy input at will.
+     */
+    private static class TestEntropySource implements EntropySource {
+
+        private static Queue<byte[]> data = new ArrayDeque<>();
+
+        @Override
+        public byte[] getEntropy(int minEntropy, int minLength,
+                                 int maxLength, boolean pr) {
+            byte[] result = data.poll();
+            if (result == null
+                    || result.length < minLength
+                    || result.length > maxLength) {
+                throw new RuntimeException("Invalid entropy: " +
+                        "need [" + minLength + ", " + maxLength + "], " +
+                        (result == null ? "none" : "has " + result.length));
+            }
+            return result;
+        }
+
+        private static void setEntropy(byte[] input) {
+            data.offer(input);
+        }
+
+        private static void clearEntropy() {
+            data.clear();
+        }
+    }
+
+    /**
+     * The test.
+     *
+     * // Algorithm line, might contain usedf flag
+     * [AES-128 use df]
+     * // Ignored, use mode argument
+     * [PredictionResistance = True]
+     * // Ignored, just read EntropyInput
+     * [EntropyInputLen = 128]
+     * // Ignored, just read Nonce
+     * [NonceLen = 64]
+     * // Ignored, just read PersonalizationString
+     * [PersonalizationStringLen = 128]
+     * // Ignored, just read AdditionalInput
+     * [AdditionalInputLen = 128]
+     * // Used to allocate buffer for nextBytes() call
+     * [ReturnedBitsLen = 512]
+     *
+     * // A sign we can ignore old unused entropy input
+     * COUNT = 0
+     *
+     * // Instantiate
+     * EntropyInput = 92898f...
+     * Nonce = c2a4d9...
+     * PersonalizationString = ea65ee...  // Enough to call getInstance()
+     *
+     * // Reseed
+     * EntropyInputReseed = bfd503...
+     * AdditionalInputReseed = 009e0b... // Enough to call reseed()
+     *
+     * // Generation
+     * AdditionalInput = 1a40fa....  // Enough to call nextBytes() for PR off
+     * EntropyInputPR = 20728a...  // Enough to call nextBytes() for PR on
+     * ReturnedBits = 5a3539...  // Compare this to last nextBytes() output
+     *
+     * @param mode one of "no_reseed", "pr_false", "pr_true"
+     * @param mech one of "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"
+     * @param es our own entropy source
+     * @param is test material
+     */
+    private static void test(String mode, String mech, EntropySource es,
+            InputStream is) throws Exception {
+
+        SecureRandom hd = null;
+
+        // Expected output length in bits as in [ReturnedBitsLen]
+        int outLen = 0;
+
+        // DRBG algorithm as in the algorithm line
+        String algorithm = null;
+
+        // When CTR_DRBG uses a derivation function as in the algorithm line
+        boolean usedf = false;
+
+        // Additional input as in "AdditionalInput"
+        byte[] additional = null;
+
+        // Random bits generated
+        byte[] output = null;
+
+        // Prediction resistance flag, determined by mode
+        boolean isPr = false;
+
+        StringBuilder sb = new StringBuilder();
+
+        int lineno = 0;
+
+        System.out.println(mode + "/" + mech);
+
+        try (Stream<String> lines =
+                     new BufferedReader(new InputStreamReader(is)).lines()) {
+            for (String s: (Iterable<String>) lines::iterator) {
+                lineno++;
+                err.print(hd == null ? '-' : '*');
+                Line l = new Line(s);
+                if (l.key.contains("no df") || l.key.contains("use df") ||
+                        l.key.startsWith("SHA-")) {
+                    sb = new StringBuilder();
+                    bout.reset();
+                }
+                sb.append(String.format(
+                        "%9s %4s %5d %s\n", mode, mech, lineno, s));
+                switch (l.key) {
+                    case "3KeyTDEA no df":
+                    case "AES-128 no df":
+                    case "AES-192 no df":
+                    case "AES-256 no df":
+                    case "3KeyTDEA use df":
+                    case "AES-128 use df":
+                    case "AES-192 use df":
+                    case "AES-256 use df":
+                        algorithm = l.key.split(" ")[0];
+                        usedf = l.key.contains("use df");
+                        break;
+                    case "ReturnedBitsLen":
+                        outLen = l.vint();
+                        output = new byte[outLen / 8];
+                        break;
+                    case "EntropyInput":
+                        TestEntropySource.setEntropy(l.vdata());
+                        break;
+                    case "Nonce":
+                        nonce = l.vdata();
+                        break;
+                    case "COUNT":
+                        // Remove unused entropy (say, when AES-256 is skipped)
+                        TestEntropySource.clearEntropy();
+                        break;
+                    case "PersonalizationString":
+                        try {
+                            isPr = mode.equals("pr_true");
+                            byte[] ps = null;
+                            if (l.vdata().length != 0) {
+                                ps = l.vdata();
+                            }
+
+                            // MoreDrbgParameters must be used because we
+                            // want to set entropy input and nonce. Since
+                            // it can also set mechanism, algorithm and usedf,
+                            // we don't need to touch securerandom.drbg.config.
+                            hd = SecureRandom.getInstance("DRBG",
+                                    new MoreDrbgParameters(es, mech, algorithm,
+                                            nonce, usedf,
+                                            DrbgParameters.instantiation(
+                                                    -1,
+                                                    isPr ? PR_AND_RESEED
+                                                            : RESEED_ONLY,
+                                                    ps)),
+                                    "SUN");
+                        } catch (NoSuchAlgorithmException iae) {
+                            // AES-256 might not be available. This is OK.
+                            if ((algorithm.equals("AES-192")
+                                    || algorithm.equals("AES-256"))
+                                    && AES_LIMIT == 128) {
+                                hd = null;
+                            } else {
+                                throw iae;
+                            }
+                        }
+                        break;
+                    case "EntropyInputReseed":
+                        TestEntropySource.setEntropy(l.vdata());
+                        break;
+                    case "AdditionalInputReseed":
+                        if (l.vdata().length == 0) {
+                            additional = null;
+                        } else {
+                            additional = l.vdata();
+                        }
+                        if (hd != null) {
+                            if (additional == null) {
+                                hd.reseed();
+                            } else {
+                                hd.reseed(DrbgParameters.reseed(
+                                        isPr, additional));
+                            }
+                        }
+                        break;
+                    case "EntropyInputPR":
+                        if (l.vdata().length != 0) {
+                            TestEntropySource.setEntropy(l.vdata());
+                        }
+                        if (mode.equals("pr_true")) {
+                            if (hd != null) {
+                                if (additional == null) {
+                                    hd.nextBytes(output);
+                                } else {
+                                    hd.nextBytes(output,
+                                            DrbgParameters.nextBytes(
+                                                    -1, isPr, additional));
+                                }
+                            }
+                        }
+                        break;
+                    case "AdditionalInput":
+                        if (l.vdata().length == 0) {
+                            additional = null;
+                        } else {
+                            additional = l.vdata();
+                        }
+                        if (!mode.equals("pr_true")) {
+                            if (hd != null) {
+                                if (additional == null) {
+                                    hd.nextBytes(output);
+                                } else {
+                                    hd.nextBytes(output,
+                                            DrbgParameters.nextBytes(
+                                                    -1, isPr, additional));
+                                }
+                            }
+                        }
+                        break;
+                    case "ReturnedBits":
+                        if (hd != null) {
+                            if (!Arrays.equals(output, l.vdata())) {
+                                throw new Exception("\nExpected: " +
+                                        l.value + "\n  Actual: " + hex(output));
+                            }
+                        }
+                        break;
+                    default:
+                        // Algorithm line for Hash_DRBG and HMAC_DRBG
+                        if (l.key.startsWith("SHA-")) {
+                            algorithm = l.key;
+                        }
+                }
+            }
+            err.println();
+        } catch (Exception e) {
+            err.println();
+            err.println(sb.toString());
+            err.println(bout.toString());
+            throw e;
+        }
+    }
+
+    /**
+     * Parse a line from test material.
+     *
+     * Brackets are removed. Key and value separated.
+     */
+    static class Line {
+
+        final String key;
+        final String value;
+
+        Line(String s) {
+            s = s.trim();
+            if (s.length() >= 2) {
+                if (s.charAt(0) == '[') {
+                    s = s.substring(1, s.length() - 1);
+                }
+            }
+            if (s.indexOf('=') < 0) {
+                key = s;
+                value = null;
+            } else {
+                key = s.substring(0, s.indexOf('=')).trim();
+                value = s.substring(s.indexOf('=') + 1).trim();
+            }
+        }
+
+        int vint() {
+            return Integer.parseInt(value);
+        }
+
+        byte[] vdata() {
+            return xeh(value);
+        }
+    }
+
+    // Bytes to HEX
+    private static String hex(byte[] in) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b: in) {
+            sb.append(String.format("%02x", b&0xff));
+        }
+        return sb.toString();
+    }
+
+    // HEX to bytes
+    private static byte[] xeh(String in) {
+        in = in.replaceAll(" ", "");
+        int len = in.length() / 2;
+        byte[] out = new byte[len];
+        for (int i = 0; i < len; i++) {
+            out[i] = (byte) Integer.parseInt(
+                    in.substring(i * 2, i * 2 + 2), 16);
+        }
+        return out;
+    }
+}
--- a/test/sun/security/provider/SecureRandom/SelfSeed.java	Thu May 05 16:36:06 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 1998, 2003, 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 4168409
- * @summary SecureRandom forces all instances to self-seed, even if a seed is
- *                      provided
- */
-
-import java.security.SecureRandom;
-
-public class SelfSeed {
-
-    private static final int NUM_BYTES = 5;
-    private static byte seed[] = { (byte)0xaa, (byte)0x11, (byte)0xa1 };
-
-    public static void main(String[] args) {
-
-        try {
-            SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG");
-            sr1.setSeed(seed);
-            byte randomBytes[] = new byte[NUM_BYTES];
-            sr1.nextBytes(randomBytes);
-
-            SecureRandom sr2 = new SecureRandom(seed);
-            if (sr2.getAlgorithm().equals("SHA1PRNG") == false) {
-                System.out.println("Default PRNG is not SHA1PRNG, skipping test");
-                return;
-            }
-            byte otherRandomBytes[] = new byte[NUM_BYTES];
-            sr2.nextBytes(otherRandomBytes);
-
-            // make sure the random bytes generated are the same
-            for (int i = 0; i < NUM_BYTES; i++) {
-                if (randomBytes[i] != otherRandomBytes[i])
-                    throw new SecurityException("FAILURE: " +
-                                        "Returned bytes not equal");
-            }
-
-            // success
-        } catch (Exception e) {
-            throw new SecurityException("FAILURE: " + e.toString());
-        }
-    }
-}
--- a/test/sun/security/provider/SecureRandom/StrongSeedReader.java	Thu May 05 16:36:06 2016 -0700
+++ b/test/sun/security/provider/SecureRandom/StrongSeedReader.java	Fri May 06 11:38:44 2016 +0800
@@ -59,6 +59,7 @@
             System.setProperty("java.security.egd", file.toURI().toString());
             testSeed("NativePRNG");
             testSeed("SHA1PRNG");
+            testSeed("DRBG");
         } finally {
             if (file != null) {
                 file.delete();