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