1 /*
2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.security;
27 
28 import java.util.Locale;
29 import java.util.Objects;
30 
31 /**
32  * This class specifies the parameters used by a DRBG (Deterministic
33  * Random Bit Generator).
34  * <p>
35  * According to
36  * <a href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">
37  * NIST Special Publication 800-90A Revision 1, Recommendation for Random
38  * Number Generation Using Deterministic Random Bit Generators</a> (800-90Ar1),
39  * <blockquote>
40  * A DRBG is based on a DRBG mechanism as specified in this Recommendation
41  * and includes a source of randomness. A DRBG mechanism uses an algorithm
42  * (i.e., a DRBG algorithm) that produces a sequence of bits from an initial
43  * value that is determined by a seed that is determined from the output of
44  * the randomness source."
45  * </blockquote>
46  * <p>
47  * The 800-90Ar1 specification allows for a variety of DRBG implementation
48  * choices, such as:
49  * <ul>
50  * <li> an entropy source,
51  * <li> a DRBG mechanism (for example, Hash_DRBG),
52  * <li> a DRBG algorithm (for example, SHA-256 for Hash_DRBG and AES-256
53  * for CTR_DRBG. Please note that it is not the algorithm used in
54  * {@link SecureRandom#getInstance}, which we will call a
55  * <em>SecureRandom algorithm</em> below),
56  * <li> optional features, including prediction resistance
57  * and reseeding supports,
58  * <li> highest security strength.
59  * </ul>
60  * <p>
61  * These choices are set in each implementation and are not directly
62  * managed by the {@code SecureRandom} API.  Check your DRBG provider's
63  * documentation to find an appropriate implementation for the situation.
64  * <p>
65  * On the other hand, the 800-90Ar1 specification does have some configurable
66  * options, such as:
67  * <ul>
68  * <li> required security strength,
69  * <li> if prediction resistance is required,
70  * <li> personalization string and additional input.
71  * </ul>
72  * <p>
73  * A DRBG instance can be instantiated with parameters from an
74  * {@link DrbgParameters.Instantiation} object and other information
75  * (for example, the nonce, which is not managed by this API). This maps
76  * to the {@code Instantiate_function} defined in NIST SP 800-90Ar1.
77  * <p>
78  * A DRBG instance can be reseeded with parameters from a
79  * {@link DrbgParameters.Reseed} object. This maps to the
80  * {@code Reseed_function} defined in NIST SP 800-90Ar1. Calling
81  * {@link SecureRandom#reseed()} is equivalent to calling
82  * {@link SecureRandom#reseed(SecureRandomParameters)} with the effective
83  * instantiated prediction resistance flag (as returned by
84  * {@link SecureRandom#getParameters()}) with no additional input.
85  * <p>
86  * A DRBG instance generates data with additional parameters from a
87  * {@link DrbgParameters.NextBytes} object. This maps to the
88  * {@code Generate_function} defined in NIST SP 800-90Ar1. Calling
89  * {@link SecureRandom#nextBytes(byte[])} is equivalent to calling
90  * {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)}
91  * with the effective instantiated strength and prediction resistance flag
92  * (as returned by {@link SecureRandom#getParameters()}) with no
93  * additional input.
94  * <p>
95  * A DRBG should be implemented as a subclass of {@link SecureRandomSpi}.
96  * It is recommended that the implementation contain the 1-arg
97  * {@linkplain SecureRandomSpi#SecureRandomSpi(SecureRandomParameters) constructor}
98  * that takes a {@code DrbgParameters.Instantiation} argument. If implemented
99  * this way, this implementation can be chosen by any
100  * {@code SecureRandom.getInstance()} method. If it is chosen by a
101  * {@code SecureRandom.getInstance()} with a {@link SecureRandomParameters}
102  * parameter, the parameter is passed into this constructor. If it is chosen
103  * by a {@code SecureRandom.getInstance()} without a
104  * {@code SecureRandomParameters} parameter, the constructor is called with
105  * a {@code null} argument and the implementation should choose its own
106  * parameters. Its {@link SecureRandom#getParameters()} must always return a
107  * non-null effective {@code DrbgParameters.Instantiation} object that reflects
108  * how the DRBG is actually instantiated. A caller can use this information
109  * to determine whether a {@code SecureRandom} object is a DRBG and what
110  * features it supports. Please note that the returned value does not
111  * necessarily equal to the {@code DrbgParameters.Instantiation} object passed
112  * into the {@code SecureRandom.getInstance()} call. For example,
113  * the requested capability can be {@link DrbgParameters.Capability#NONE}
114  * but the effective value can be {@link DrbgParameters.Capability#RESEED_ONLY}
115  * if the implementation supports reseeding. The implementation must implement
116  * the {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)}
117  * method which takes a {@code DrbgParameters.NextBytes} parameter. Unless
118  * the result of {@link SecureRandom#getParameters()} has its
119  * {@linkplain DrbgParameters.Instantiation#getCapability() capability} being
120  * {@link Capability#NONE NONE}, it must implement
121  * {@link SecureRandomSpi#engineReseed(SecureRandomParameters)} which takes
122  * a {@code DrbgParameters.Reseed} parameter.
123  * <p>
124  * On the other hand, if a DRBG implementation does not contain a constructor
125  * that has an {@code DrbgParameters.Instantiation} argument (not recommended),
126  * it can only be chosen by a {@code SecureRandom.getInstance()} without
127  * a {@code SecureRandomParameters} parameter, but will not be chosen if
128  * a {@code getInstance} method with a {@code SecureRandomParameters} parameter
129  * is called. If implemented this way, its {@link SecureRandom#getParameters()}
130  * must return {@code null}, and it does not need to implement either
131  * {@link SecureRandomSpi#engineNextBytes(byte[], SecureRandomParameters)}
132  * or {@link SecureRandomSpi#engineReseed(SecureRandomParameters)}.
133  * <p>
134  * A DRBG might reseed itself automatically if the seed period is bigger
135  * than the maximum seed life defined by the DRBG mechanism.
136  * <p>
137  * A DRBG implementation should support serialization and deserialization
138  * by retaining the configuration and effective parameters, but the internal
139  * state must not be serialized and the deserialized object must be
140  * reinstantiated.
141  * <p>
142  * Examples:
143  * <blockquote><pre>
144  * SecureRandom drbg;
145  * byte[] buffer = new byte[32];
146  *
147  * // Any DRBG is OK
148  * drbg = SecureRandom.getInstance("DRBG");
149  * drbg.nextBytes(buffer);
150  *
151  * SecureRandomParameters params = drbg.getParameters();
152  * if (params instanceof DrbgParameters.Instantiation) {
153  *     DrbgParameters.Instantiation ins = (DrbgParameters.Instantiation) params;
154  *     if (ins.getCapability().supportsReseeding()) {
155  *         drbg.reseed();
156  *     }
157  * }
158  *
159  * // The following call requests a weak DRBG instance. It is only
160  * // guaranteed to support 112 bits of security strength.
161  * drbg = SecureRandom.getInstance("DRBG",
162  *         DrbgParameters.instantiation(112, NONE, null));
163  *
164  * // Both the next two calls will likely fail, because drbg could be
165  * // instantiated with a smaller strength with no prediction resistance
166  * // support.
167  * drbg.nextBytes(buffer,
168  *         DrbgParameters.nextBytes(256, false, "more".getBytes()));
169  * drbg.nextBytes(buffer,
170  *         DrbgParameters.nextBytes(112, true, "more".getBytes()));
171  *
172  * // The following call requests a strong DRBG instance, with a
173  * // personalization string. If it successfully returns an instance,
174  * // that instance is guaranteed to support 256 bits of security strength
175  * // with prediction resistance available.
176  * drbg = SecureRandom.getInstance("DRBG", DrbgParameters.instantiation(
177  *         256, PR_AND_RESEED, "hello".getBytes()));
178  *
179  * // Prediction resistance is not requested in this single call,
180  * // but an additional input is used.
181  * drbg.nextBytes(buffer,
182  *         DrbgParameters.nextBytes(-1, false, "more".getBytes()));
183  *
184  * // Same for this call.
185  * drbg.reseed(DrbgParameters.reseed(false, "extra".getBytes()));</pre>
186  * </blockquote>
187  *
188  * @implSpec
189  * By convention, a provider should name its primary DRBG implementation
190  * with the <a href=
191  * "{@docRoot}/../specs/security/standard-names.html#securerandom-number-generation-algorithms">
192  * standard {@code SecureRandom} algorithm name</a> "DRBG".
193  *
194  * @implNote
195  * The following notes apply to the "DRBG" implementation in the SUN provider
196  * of the JDK reference implementation.
197  * <p>
198  * This implementation supports the Hash_DRBG and HMAC_DRBG mechanisms with
199  * DRBG algorithm SHA-224, SHA-512/224, SHA-256, SHA-512/256, SHA-384 and
200  * SHA-512, and CTR_DRBG (both using derivation function and not using
201  * derivation function) with DRBG algorithm AES-128, AES-192 and AES-256.
202  * <p>
203  * The mechanism name and DRBG algorithm name are determined by the
204  * {@linkplain Security#getProperty(String) security property}
205  * {@code securerandom.drbg.config}. The default choice is Hash_DRBG
206  * with SHA-256.
207  * <p>
208  * For each combination, the security strength can be requested from 112
209  * up to the highest strength it supports. Both reseeding and prediction
210  * resistance are supported.
211  * <p>
212  * Personalization string is supported through the
213  * {@link DrbgParameters.Instantiation} class and additional input is supported
214  * through the {@link DrbgParameters.NextBytes} and
215  * {@link DrbgParameters.Reseed} classes.
216  * <p>
217  * If a DRBG is not instantiated with a {@link DrbgParameters.Instantiation}
218  * object explicitly, this implementation instantiates it with a default
219  * requested strength of 128 bits, no prediction resistance request, and
220  * no personalization string. These default instantiation parameters can also
221  * be customized with the {@code securerandom.drbg.config} security property.
222  * <p>
223  * This implementation reads fresh entropy from the system default entropy
224  * source determined by the security property {@code securerandom.source}.
225  * <p>
226  * Calling {@link SecureRandom#generateSeed(int)} will directly read
227  * from this system default entropy source.
228  *
229  * @since 9
230  */
231 public class DrbgParameters {
232 
DrbgParameters()233     private DrbgParameters() {
234         // This class should not be instantiated
235     }
236 
237     /**
238      * The reseedable and prediction resistance capabilities of a DRBG.
239      * <p>
240      * When this object is passed to a {@code SecureRandom.getInstance()} call,
241      * it is the requested minimum capability. When it's returned from
242      * {@code SecureRandom.getParameters()}, it is the effective capability.
243      * <p>
244      * Please note that while the {@code Instantiate_function} defined in
245      * NIST SP 800-90Ar1 only includes a {@code prediction_resistance_flag}
246      * parameter, the {@code Capability} type includes an extra value
247      * {@link #RESEED_ONLY} because reseeding is an optional function.
248      * If {@code NONE} is used in an {@code Instantiation} object in calling the
249      * {@code SecureRandom.getInstance} method, the returned DRBG instance
250      * is not guaranteed to support reseeding. If {@code RESEED_ONLY} or
251      * {@code PR_AND_RESEED} is used, the instance must support reseeding.
252      * <p>
253      * The table below lists possible effective values if a certain
254      * capability is requested, i.e.
255      * <blockquote><pre>
256      * Capability requested = ...;
257      * SecureRandom s = SecureRandom.getInstance("DRBG",
258      *         DrbgParameters(-1, requested, null));
259      * Capability effective = ((DrbgParametes.Initiate) s.getParameters())
260      *         .getCapability();</pre>
261      * </blockquote>
262      * <table class="striped">
263      * <caption style="display:none">requested and effective capabilities</caption>
264      * <thead>
265      * <tr>
266      * <th scope="col">Requested Value</th>
267      * <th scope="col">Possible Effective Values</th>
268      * </tr>
269      * </thead>
270      * <tbody style="text-align:left">
271      * <tr><th scope="row">NONE</th><td>NONE, RESEED_ONLY, PR_AND_RESEED</td></tr>
272      * <tr><th scope="row">RESEED_ONLY</th><td>RESEED_ONLY, PR_AND_RESEED</td></tr>
273      * <tr><th scope="row">PR_AND_RESEED</th><td>PR_AND_RESEED</td></tr>
274      * </tbody>
275      * </table>
276      * <p>
277      * A DRBG implementation supporting prediction resistance must also
278      * support reseeding.
279      *
280      * @since 9
281      */
282     public enum Capability {
283 
284         /**
285          * Both prediction resistance and reseed.
286          */
287         PR_AND_RESEED,
288 
289         /**
290          * Reseed but no prediction resistance.
291          */
292         RESEED_ONLY,
293 
294         /**
295          * Neither prediction resistance nor reseed.
296          */
297         NONE;
298 
299         @Override
toString()300         public String toString() {
301             return name().toLowerCase(Locale.ROOT);
302         }
303 
304         /**
305          * Returns whether this capability supports reseeding.
306          *
307          * @return {@code true} for {@link #PR_AND_RESEED} and
308          *      {@link #RESEED_ONLY}, and {@code false} for {@link #NONE}
309          */
supportsReseeding()310         public boolean supportsReseeding() {
311             return this != NONE;
312         }
313 
314         /**
315          * Returns whether this capability supports prediction resistance.
316          *
317          * @return {@code true} for {@link #PR_AND_RESEED}, and {@code false}
318          *      for {@link #RESEED_ONLY} and {@link #NONE}
319          */
supportsPredictionResistance()320         public boolean supportsPredictionResistance() {
321             return this == PR_AND_RESEED;
322         }
323     }
324 
325     /**
326      * DRBG parameters for instantiation.
327      * <p>
328      * When used in
329      * {@link SecureRandom#getInstance(String, SecureRandomParameters)}
330      * or one of the other similar {@code getInstance} calls that take a
331      * {@code SecureRandomParameters} parameter, it means the
332      * requested instantiate parameters the newly created {@code SecureRandom}
333      * object must minimally support. When used as the return value of the
334      * {@link SecureRandom#getParameters()} method, it means the effective
335      * instantiate parameters of the {@code SecureRandom} object.
336      *
337      * @since 9
338      */
339     public static final class Instantiation
340             implements SecureRandomParameters {
341 
342         private final int strength;
343         private final Capability capability;
344         private final byte[] personalizationString;
345 
346         /**
347          * Returns the security strength in bits.
348          *
349          * @return If used in {@code getInstance}, returns the minimum strength
350          * requested, or -1 if there is no specific request on the strength.
351          * If used in {@code getParameters}, returns the effective strength.
352          * The effective strength must be greater than or equal to the minimum
353          * strength requested.
354          */
getStrength()355         public int getStrength() {
356             return strength;
357         }
358 
359         /**
360          * Returns the capability.
361          *
362          * @return If used in {@code getInstance}, returns the minimum
363          * capability requested. If used in {@code getParameters}, returns
364          * information on the effective prediction resistance flag and
365          * whether it supports reseeding.
366          */
getCapability()367         public Capability getCapability() {
368             return capability;
369         }
370 
371         /**
372          * Returns the personalization string as a byte array.
373          *
374          * @return If used in {@code getInstance}, returns the requested
375          * personalization string as a newly allocated array, or {@code null}
376          * if no personalization string is requested. The same string should
377          * be returned in {@code getParameters} as a new copy, or {@code null}
378          * if no personalization string is requested in {@code getInstance}.
379          */
getPersonalizationString()380         public byte[] getPersonalizationString() {
381             return (personalizationString == null) ?
382                     null : personalizationString.clone();
383         }
384 
Instantiation(int strength, Capability capability, byte[] personalizationString)385         private Instantiation(int strength, Capability capability,
386                               byte[] personalizationString) {
387             if (strength < -1) {
388                 throw new IllegalArgumentException(
389                         "Illegal security strength: " + strength);
390             }
391             this.strength = strength;
392             this.capability = capability;
393             this.personalizationString = (personalizationString == null) ?
394                     null : personalizationString.clone();
395         }
396 
397         /**
398          * Returns a Human-readable string representation of this
399          * {@code Instantiation}.
400          *
401          * @return the string representation
402          */
403         @Override
toString()404         public String toString() {
405             // I don't care what personalizationString looks like
406             return strength + "," + capability + "," + personalizationString;
407         }
408     }
409 
410     /**
411      * DRBG parameters for random bits generation. It is used in
412      * {@link SecureRandom#nextBytes(byte[], SecureRandomParameters)}.
413      *
414      * @since 9
415      */
416     public static final class NextBytes
417             implements SecureRandomParameters {
418         private final int strength;
419         private final boolean predictionResistance;
420         private final byte[] additionalInput;
421 
422         /**
423          * Returns the security strength requested in bits.
424          *
425          * @return the strength requested, or -1 if the effective strength
426          *      should be used.
427          */
getStrength()428         public int getStrength() {
429             return strength;
430         }
431 
432         /**
433          * Returns whether prediction resistance is requested.
434          *
435          * @return whether prediction resistance is requested
436          */
getPredictionResistance()437         public boolean getPredictionResistance() {
438             return predictionResistance;
439         }
440 
441         /**
442          * Returns the requested additional input.
443          *
444          * @return the requested additional input, {@code null} if not
445          * requested. A new byte array is returned each time this method
446          * is called.
447          */
getAdditionalInput()448         public byte[] getAdditionalInput() {
449             return additionalInput == null? null: additionalInput.clone();
450         }
451 
NextBytes(int strength, boolean predictionResistance, byte[] additionalInput)452         private NextBytes(int strength, boolean predictionResistance,
453                           byte[] additionalInput) {
454             if (strength < -1) {
455                 throw new IllegalArgumentException(
456                         "Illegal security strength: " + strength);
457             }
458             this.strength = strength;
459             this.predictionResistance = predictionResistance;
460             this.additionalInput = (additionalInput == null) ?
461                     null : additionalInput.clone();
462         }
463     }
464 
465     /**
466      * DRBG parameters for reseed. It is used in
467      * {@link SecureRandom#reseed(SecureRandomParameters)}.
468      *
469      * @since 9
470      */
471     public static final class Reseed implements SecureRandomParameters {
472 
473         private final byte[] additionalInput;
474         private final boolean predictionResistance;
475 
476         /**
477          * Returns whether prediction resistance is requested.
478          *
479          * @return whether prediction resistance is requested
480          */
getPredictionResistance()481         public boolean getPredictionResistance() {
482             return predictionResistance;
483         }
484 
485         /**
486          * Returns the requested additional input.
487          *
488          * @return the requested additional input, or {@code null} if
489          * not requested. A new byte array is returned each time this method
490          * is called.
491          */
getAdditionalInput()492         public byte[] getAdditionalInput() {
493             return additionalInput == null ? null : additionalInput.clone();
494         }
495 
Reseed(boolean predictionResistance, byte[] additionalInput)496         private Reseed(boolean predictionResistance, byte[] additionalInput) {
497             this.predictionResistance = predictionResistance;
498             this.additionalInput = (additionalInput == null) ?
499                     null : additionalInput.clone();
500         }
501     }
502 
503     /**
504      * Generates a {@link DrbgParameters.Instantiation} object.
505      *
506      * @param strength security strength in bits, -1 for default strength
507      *                 if used in {@code getInstance}.
508      * @param capability capability
509      * @param personalizationString personalization string as a byte array,
510      *                              can be {@code null}. The content of this
511      *                              byte array will be copied.
512      * @return a new {@code Instantiation} object
513      * @throws NullPointerException if {@code capability} is {@code null}
514      * @throws IllegalArgumentException if {@code strength} is less than -1
515      */
instantiation(int strength, Capability capability, byte[] personalizationString)516     public static Instantiation instantiation(int strength,
517                                               Capability capability,
518                                               byte[] personalizationString) {
519         return new Instantiation(strength, Objects.requireNonNull(capability),
520                 personalizationString);
521     }
522 
523     /**
524      * Generates a {@link NextBytes} object.
525      *
526      * @param strength requested security strength in bits. If set to -1, the
527      *                 effective strength will be used.
528      * @param predictionResistance prediction resistance requested
529      * @param additionalInput additional input, can be {@code null}.
530      *                        The content of this byte array will be copied.
531      * @throws IllegalArgumentException if {@code strength} is less than -1
532      * @return a new {@code NextBytes} object
533      */
nextBytes(int strength, boolean predictionResistance, byte[] additionalInput)534     public static NextBytes nextBytes(int strength,
535                                       boolean predictionResistance,
536                                       byte[] additionalInput) {
537         return new NextBytes(strength, predictionResistance, additionalInput);
538     }
539 
540     /**
541      * Generates a {@link Reseed} object.
542      *
543      * @param predictionResistance prediction resistance requested
544      * @param additionalInput additional input, can be {@code null}.
545      *                        The content of this byte array will be copied.
546      * @return a new {@code Reseed} object
547      */
reseed( boolean predictionResistance, byte[] additionalInput)548     public static Reseed reseed(
549             boolean predictionResistance, byte[] additionalInput) {
550         return new Reseed(predictionResistance, additionalInput);
551     }
552 }
553