/* * 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). *
* According to * * NIST Special Publication 800-90A Revision 1, Recommendation for Random Number * Generation Using Deterministic Random Bit Generators, *
* 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." **
* A DRBG implementation has a configuration, including but not limited to, *
* The configuration is defined by the implementation and not managed * by the {@code SecureRandom} API. *
* A DRBG instance is instantiated with parameters from an {@code Instantiate} * 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-90A. *
* Calling {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)} * and {@link SecureRandom#reseed(SecureRandomParameters)} map to the * {@code Reseed_function} and {@code Generate_function} defined in * NIST SP 800-90A, separately. 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 in {@link SecureRandom#getParameters()}) with no additional input. * Calling {@link SecureRandom#reseed()} is equivalent to calling * {@link SecureRandom#reseed(SecureRandomParameters)} with the effective * instantiated prediction resistance flag (as returned in * {@link SecureRandom#getParameters()}) with no additional input. *
* A DRBG should be implemented as a subclass of {@link SecureRandomSpi}. * It is recommended that the implementation contain * {@linkplain SecureRandomSpi#SecureRandomSpi(SecureRandomParameters) a constructor} * that has a {@link DrbgParameters.Instantiate} 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 {@link 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 {@link Instantiate} 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 Instantiate} object passed into the {@code SecureRandom.getInstance()} * call. For example, the requested capability can be {@link Capability#NONE} * but the returned capability can be {@link Capability#RESEED_ONLY} if the * implementation supports reseeding. The implementation must implement the * {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)} * method which takes a {@link NextBytes} parameter. Unless the result of * {@link SecureRandom#getParameters()} has its * {@linkplain Instantiate#getCapability() capability} being * {@link Capability#NONE NONE}, it must implement * {@link SecureRandomSpi#engineReseed(SecureRandomParameters)} * which takes a {@link Reseed} parameter. *
* On the other hand, if a DRBG implementation does not contain a * constructor that has an {@link Instantiate} argument (not recommended), * it can only be chosen by a {@code SecureRandom.getInstance()} * without a {@link SecureRandomParameters} parameter, but will not be chosen * if a {@code getInstance} method with a * {@link 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)}. *
* A DRBG might reseed itself automatically if the seed period is bigger * than the maximum seed life defined by the DRBG mechanism. *
* Examples: *
* * @implSpec * By convention, a provider should name its primary DRBG implementation * with the * standard {@code SecureRandom} algorithm name "DRBG". How this implementation * is configured is provider-specific. A provider is free to add other DRBG * implementations with specific configurations using different {@code SecureRandom} * algorithm names (for example, "Hash_DRBG/SHA-512"). * * @implNote * The following notes apply to the "DRBG" implementation in the SUN provider * of the JDK reference implementation. ** 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.Instantiate) { * DrbgParameters.Instantiate ins = (DrbgParameters.Instantiate) params; * if (ins.getCapability().supportsReseeding()) { * drbg.reseed(); * } * } * * // This might return a weak DRBG instance. It is only guaranteed to support * // 112 bits of security strength. * drbg = SecureRandom.getInstance("DRBG", * DrbgParameters.instantiate(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())); * * // This returns a strong DRBG instance, with a personalization string. * // It is guaranteed to support 256 bits of security strength with * // prediction resistance turned on. * drbg = SecureRandom.getInstance("DRBG", * DrbgParameters.instantiate(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())); *
* This implementation supports the Hash_DRBG and HMAC_DRBG mechanisms with * DRBG algorithm names 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 names DESede * (aka 3 Key TDEA), AES-128, AES-192 and AES-256. *
* The mechanism name and DRBG algorithm name can be configured with the * {@linkplain Security#getProperty(String) security property} {@code drbg}. * The default configuration is Hash_DRBG with SHA-256. *
* For each combination, the security strength can be requested from 112 * up to the highest strength it supports. Reseeding is supported, and * prediction resistance can be turned on or off. *
* Personalization string is supported through the * {@link DrbgParameters.Instantiate} class and additional input is supported * through the {@link DrbgParameters.NextBytes} * and {@link DrbgParameters.Reseed} classes. *
* If a DRBG is not instantiated with a {@link DrbgParameters.Instantiate} * object explicitly, this implementation instantiates it with a default * requested strength of 128 bits, no prediction resistance request, and * no personalization string. These default instantiation parameters can also * be customized with the {@code drbg} security property. *
* This implementation reads fresh entropy from the system default entropy * source determined by the security property {@code securerandom.source}. *
* This implementation has passed all tests included in the 20151104 version of * * The DRBG Test Vectors. *
* Calling {@link SecureRandom#generateSeed(int)} will directly read * from a DRBG's entropy source. * * @since 9 */ public class DrbgParameters { private DrbgParameters() { // This class should not be instantiated } /** * The reseedable and prediction resistance capabilities of a DRBG. *
* When this object is used in a {@code SecureRandom.getInstance()} call, * it means the required minimum capability. When used in * {@code SecureRandom.getParameters()}, it means the effective capability. *
* A DRBG implementation supporting prediction resistance must also * support reseeding. * * @see Instantiate#getCapability() * @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. *
* 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 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 Instantiate implements SecureRandomParameters { private final int strength; private final Capability capability; private final byte[] personalizationString; /** * Returns the strength. * * @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 actual initiated strength. * The actual strength must be greater than or equal to the minimum * strength requested. */ public int getStrength() { return strength; } /** * Returns the capability. *
* Please note that while the {@code Instantiate_function} defined in * NIST SP 800-90A only includes a {@code prediction_resistance_flag} * parameter, the {@code Capability} type includes extra values * for reseeding. If {@code NONE} or {@code RESEED_ONLY} is used in * an {@code Instantiate} object in calling the * {@code SecureRandom.getInstance} method, the returned DRBG instance * is not guaranteed to support reseed. If {@code RESEED_ONLY} or * {@code PR_AND_RESEED} is used, the instance must support reseed. *
* The table below lists possible effective values if a certain * capability is requested, i.e. *
** Capability req = ...; * SecureRandom s = SecureRandom.getInstance("DRBG", * DrbgParameters(-1, req, null)); * Capability eff = ((DrbgParametes.Initiate) s.getParameters()) * .getCapability(); *
Requested Value ({@code req}) | *Possible Effective Values ({@code eff}) | *
---|---|
NONE | NONE, RESEED_ONLY, PR_AND_RESEED |
RESEED_ONLY | RESEED_ONLY, PR_AND_RESEED |
PR_AND_RESEED | PR_AND_RESEED |