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