1 /* 2 * Copyright (c) 2016, 2020, 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 sun.security.provider; 27 28 import sun.security.util.Debug; 29 30 import java.security.*; 31 import java.util.Arrays; 32 import java.util.Objects; 33 import static java.security.DrbgParameters.Capability.*; 34 35 /** 36 * The abstract base class for all DRBGs. It is used as {@link DRBG#impl}. 37 * <p> 38 * This class has 5 abstract methods. 3 are defined by SP800-90A: 39 * <ol> 40 * <li>{@link #generateAlgorithm(byte[], byte[])} 41 * <li>{@link #reseedAlgorithm(byte[], byte[])} (In fact this is not an 42 * abstract method, but any DRBG supporting reseeding must override it.) 43 * <li>{@link #instantiateAlgorithm(byte[])} 44 * </ol> 45 * and 2 for implementation purpose: 46 * <ol> 47 * <li>{@link #initEngine()} 48 * <li>{@link #chooseAlgorithmAndStrength} 49 * </ol> 50 * Although this class is not a child class of {@link SecureRandomSpi}, it 51 * implements all abstract methods there as final. 52 * <p> 53 * The initialization process of a DRBG is divided into 2 phases: 54 * {@link #configure configuration} is eagerly called to set up parameters, 55 * and {@link #instantiateIfNecessary instantiation} is lazily called only 56 * when nextBytes or reseed is called. 57 * <p> 58 * SecureRandom methods like reseed and nextBytes are not thread-safe. 59 * An implementation is required to protect shared access to instantiate states 60 * (instantiated, nonce) and DRBG states (v, c, key, reseedCounter, etc). 61 */ 62 public abstract class AbstractDrbg { 63 64 /** 65 * This field is not null if {@code -Djava.security.debug=securerandom} is 66 * specified on the command line. An implementation can print useful 67 * debug info. 68 */ 69 protected static final Debug debug = Debug.getInstance( 70 "securerandom", "drbg"); 71 72 // Common working status 73 74 private boolean instantiated = false; 75 76 /** 77 * Reseed counter of a DRBG instance. A mechanism should increment it 78 * after each random bits generation and reset it in reseed. A mechanism 79 * does <em>not</em> need to compare it to {@link #reseedInterval}. 80 * 81 * Volatile, will be used in a double checked locking. 82 */ 83 protected volatile int reseedCounter = 0; 84 85 // Mech features. If not same as below, must be redefined in constructor. 86 87 /** 88 * Default strength of a DRBG instance if it is not configured. 89 * 128 is considered secure enough now. A mechanism 90 * can change it in a constructor. 91 * 92 * Remember to sync with "securerandom.drbg.config" in java.security. 93 */ 94 protected static final int DEFAULT_STRENGTH = 128; 95 96 /** 97 * Mechanism name, say, {@code HashDRBG}. Must be set in constructor. 98 * This value will be used in {@code toString}. 99 */ 100 protected String mechName = "DRBG"; 101 102 /** 103 * highest_supported_security_strength of this mechanism for all algorithms 104 * it supports. A mechanism should update the value in its constructor 105 * if the value is not 256. 106 */ 107 protected int highestSupportedSecurityStrength = 256; 108 109 /** 110 * Whether prediction resistance is supported. A mechanism should update 111 * the value in its constructor if it is <em>not</em> supported. 112 */ 113 protected boolean supportPredictionResistance = true; 114 115 /** 116 * Whether reseed is supported. A mechanism should update 117 * the value in its constructor if it is <em>not</em> supported. 118 */ 119 protected boolean supportReseeding = true; 120 121 // Strength features. If not same as below, must be redefined in 122 // chooseAlgorithmAndStrength. Among these, minLength and seedLen have no 123 // default value and must be redefined. If personalization string or 124 // additional input is not supported, set maxPersonalizationStringLength 125 // or maxAdditionalInputLength to -1. 126 127 /** 128 * Minimum entropy input length in bytes for this DRBG instance. 129 * Must be assigned in {@link #chooseAlgorithmAndStrength}. 130 */ 131 protected int minLength; 132 133 /** 134 * Maximum entropy input length in bytes for this DRBG instance. 135 * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not 136 * {@link Integer#MAX_VALUE}. 137 * <p> 138 * In theory this value (and the values below) can be bigger than 139 * {@code Integer.MAX_VALUE} but a Java array can only have an int32 index. 140 */ 141 protected int maxLength = Integer.MAX_VALUE; 142 143 /** 144 * Maximum personalization string length in bytes for this DRBG instance. 145 * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not 146 * {@link Integer#MAX_VALUE}. 147 */ 148 protected int maxPersonalizationStringLength = Integer.MAX_VALUE; 149 150 /** 151 * Maximum additional input length in bytes for this DRBG instance. 152 * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not 153 * {@link Integer#MAX_VALUE}. 154 */ 155 protected int maxAdditionalInputLength = Integer.MAX_VALUE; 156 157 /** 158 * max_number_of_bits_per_request in bytes for this DRBG instance. 159 * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not 160 * {@link Integer#MAX_VALUE}. 161 */ 162 protected int maxNumberOfBytesPerRequest = Integer.MAX_VALUE; 163 164 /** 165 * Maximum number of requests between reseeds for this DRBG instance. 166 * Should be assigned in {@link #chooseAlgorithmAndStrength} if it is not 167 * {@link Integer#MAX_VALUE}. 168 */ 169 protected int reseedInterval = Integer.MAX_VALUE; 170 171 172 /** 173 * Algorithm used by this instance (SHA-512 or AES-256). Must be assigned 174 * in {@link #chooseAlgorithmAndStrength}. This field is used in 175 * {@link #toString()}. 176 */ 177 protected String algorithm; 178 179 // Configurable parameters 180 181 /** 182 * Security strength for this instance. Must be assigned in 183 * {@link #chooseAlgorithmAndStrength}. Should be at least the requested 184 * strength. Might be smaller than the highest strength 185 * {@link #algorithm} supports. Must not be -1. 186 */ 187 protected int securityStrength; // in bits 188 189 /** 190 * Strength requested in {@link DrbgParameters.Instantiation}. 191 * The real strength is based on it. Do not modify it in a mechanism. 192 */ 193 protected int requestedInstantiationSecurityStrength = -1; 194 195 /** 196 * The personalization string used by this instance. Set inside 197 * {@link #configure(SecureRandomParameters)} and 198 * can be used in a mechanism. Do not modify it in a mechanism. 199 */ 200 protected byte[] personalizationString; 201 202 /** 203 * The prediction resistance flag used by this instance. Set inside 204 * {@link #configure(SecureRandomParameters)}. 205 */ 206 private boolean predictionResistanceFlag; 207 208 // Non-standard configurable parameters 209 210 /** 211 * Whether a derivation function is used. Requested in 212 * {@link MoreDrbgParameters}. Only CtrDRBG uses it. 213 * Do not modify it in a mechanism. 214 */ 215 protected boolean usedf; 216 217 /** 218 * The nonce for this instance. Set in {@link #instantiateIfNecessary}. 219 * After instantiation, this field is not null. Do not modify it 220 * in a mechanism. 221 */ 222 protected byte[] nonce; 223 224 /** 225 * Requested nonce in {@link MoreDrbgParameters}. If set to null, 226 * nonce will be chosen by system, and a reinstantiated DRBG will get a 227 * new system-provided nonce. 228 */ 229 private byte[] requestedNonce; 230 231 /** 232 * Requested algorithm in {@link MoreDrbgParameters}. 233 * Do not modify it in a mechanism. 234 */ 235 protected String requestedAlgorithm; 236 237 /** 238 * The entropy source used by this instance. Set inside 239 * {@link #configure(SecureRandomParameters)}. This field 240 * can be null. {@link #getEntropyInput} will take care of null check. 241 */ 242 private EntropySource es; 243 244 // Five abstract methods for SP 800-90A DRBG 245 246 /** 247 * Decides what algorithm and strength to use (SHA-256 or AES-256, 248 * 128 or 256). Strength related fields must also be defined or redefined 249 * here. Called in {@link #configure}. A mechanism uses 250 * {@link #requestedAlgorithm}, 251 * {@link #requestedInstantiationSecurityStrength}, and 252 * {@link #DEFAULT_STRENGTH} to decide which algorithm and strength to use. 253 * <p> 254 * If {@code requestedAlgorithm} is provided, it will always be used. 255 * If {@code requestedInstantiationSecurityStrength} is also provided, 256 * the algorithm will use the strength (an exception will be thrown if 257 * the strength is not supported), otherwise, the smaller one of 258 * the highest supported strength of the algorithm and the default strength 259 * will be used. 260 * <p> 261 * If {@code requestedAlgorithm} is not provided, an algorithm will be 262 * chosen that supports {@code requestedInstantiationSecurityStrength} 263 * (or {@code DEFAULT_STRENGTH} if there is no request). 264 * <p> 265 * Since every call to {@link #configure} will call this method, 266 * make sure to the calls do not contradict with each other. 267 * <p> 268 * Here are some examples of the algorithm and strength chosen (suppose 269 * {@code DEFAULT_STRENGTH} is 128) for HashDRBG: 270 * <pre> 271 * requested effective 272 * (SHA-224, 256) IAE 273 * (SHA-256, -1) (SHA-256,128) 274 * (SHA-256, 112) (SHA-256,112) 275 * (SHA-256, 128) (SHA-256,128) 276 * (SHA-3, -1) IAE 277 * (null, -1) (SHA-256,128) 278 * (null, 112) (SHA-256,112) 279 * (null, 192) (SHA-256,192) 280 * (null, 256) (SHA-256,256) 281 * (null, 384) IAE 282 * </pre> 283 * 284 * @throws IllegalArgumentException if the requested parameters 285 * can not be supported or contradict with each other. 286 */ 287 protected abstract void chooseAlgorithmAndStrength(); 288 289 /** 290 * Initiates security engines ({@code MessageDigest}, {@code Mac}, 291 * or {@code Cipher}). This method is called during instantiation. 292 */ 293 protected abstract void initEngine(); 294 295 /** 296 * Instantiates a DRBG. Called automatically before the first 297 * {@code nextBytes} call. 298 * <p> 299 * Note that the other parameters (nonce, strength, ps) are already 300 * stored inside at configuration. 301 * 302 * @param ei the entropy input, its length is already conditioned to be 303 * between {@link #minLength} and {@link #maxLength}. 304 */ 305 protected abstract void instantiateAlgorithm(byte[] ei); 306 307 /** 308 * The generate function. 309 * 310 * @param result fill result here, not null 311 * @param additionalInput additional input, can be null. If not null, 312 * its length is smaller than {@link #maxAdditionalInputLength} 313 */ 314 protected abstract void generateAlgorithm( 315 byte[] result, byte[] additionalInput); 316 317 /** 318 * The reseed function. 319 * 320 * @param ei the entropy input, its length is already conditioned to be 321 * between {@link #minLength} and {@link #maxLength}. 322 * @param additionalInput additional input, can be null. If not null, 323 * its length is smaller than {@link #maxAdditionalInputLength} 324 * @throws UnsupportedOperationException if reseed is not supported 325 */ 326 protected void reseedAlgorithm( 327 byte[] ei, byte[] additionalInput) { 328 throw new UnsupportedOperationException("No reseed function"); 329 } 330 331 // SecureRandomSpi methods taken care of here. All final. 332 333 protected final void engineNextBytes(byte[] result) { 334 engineNextBytes(result, DrbgParameters.nextBytes( 335 -1, predictionResistanceFlag, null)); 336 } 337 338 protected final void engineNextBytes( 339 byte[] result, SecureRandomParameters params) { 340 341 Objects.requireNonNull(result); 342 343 if (debug != null) { 344 debug.println(this, "nextBytes"); 345 } 346 if (params instanceof DrbgParameters.NextBytes) { 347 348 // 800-90Ar1 9.3: Generate Process. 349 350 DrbgParameters.NextBytes dp = (DrbgParameters.NextBytes) params; 351 352 // Step 2: max_number_of_bits_per_request 353 if (result.length > maxNumberOfBytesPerRequest) { 354 // generateAlgorithm should be called multiple times to fill 355 // up result. Unimplemented since maxNumberOfBytesPerRequest 356 // is now Integer.MAX_VALUE. 357 } 358 359 // Step 3: check requested_security_strength 360 if (dp.getStrength() > securityStrength) { 361 throw new IllegalArgumentException("strength too high: " 362 + dp.getStrength()); 363 } 364 365 // Step 4: check max_additional_input_length 366 byte[] ai = dp.getAdditionalInput(); 367 if (ai != null && ai.length > maxAdditionalInputLength) { 368 throw new IllegalArgumentException("ai too long: " 369 + ai.length); 370 } 371 372 // Step 5: check prediction_resistance_flag 373 boolean pr = dp.getPredictionResistance(); 374 if (!predictionResistanceFlag && pr) { 375 throw new IllegalArgumentException("pr not available"); 376 } 377 378 instantiateIfNecessary(null); 379 380 // Step 7: Auto reseed (reseedCounter might overflow) 381 // Double checked locking, safe because reseedCounter is volatile 382 if (reseedCounter < 0 || reseedCounter > reseedInterval || pr) { 383 synchronized (this) { 384 if (reseedCounter < 0 || reseedCounter > reseedInterval 385 || pr) { 386 reseedAlgorithm(getEntropyInput(pr), ai); 387 ai = null; 388 } 389 } 390 } 391 392 // Step 8, 10: Generate_algorithm 393 // Step 9: Unnecessary. reseedCounter only updated after generation 394 generateAlgorithm(result, ai); 395 396 // Step 11: Return 397 } else { 398 throw new IllegalArgumentException("unknown params type:" 399 + params.getClass()); 400 } 401 } 402 403 public final void engineReseed(SecureRandomParameters params) { 404 if (debug != null) { 405 debug.println(this, "reseed with params"); 406 } 407 if (!supportReseeding) { 408 throw new UnsupportedOperationException("Reseed not supported"); 409 } 410 if (params == null) { 411 params = DrbgParameters.reseed(predictionResistanceFlag, null); 412 } 413 if (params instanceof DrbgParameters.Reseed) { 414 DrbgParameters.Reseed dp = (DrbgParameters.Reseed) params; 415 416 // 800-90Ar1 9.2: Reseed Process. 417 418 // Step 2: Check prediction_resistance_request 419 boolean pr = dp.getPredictionResistance(); 420 if (!predictionResistanceFlag && pr) { 421 throw new IllegalArgumentException("pr not available"); 422 } 423 424 // Step 3: Check additional_input length 425 byte[] ai = dp.getAdditionalInput(); 426 if (ai != null && ai.length > maxAdditionalInputLength) { 427 throw new IllegalArgumentException("ai too long: " 428 + ai.length); 429 } 430 instantiateIfNecessary(null); 431 432 // Step 4: Get_entropy_input 433 // Step 5: Check step 4 434 // Step 6-7: Reseed_algorithm 435 reseedAlgorithm(getEntropyInput(pr), ai); 436 437 // Step 8: Return 438 } else { 439 throw new IllegalArgumentException("unknown params type: " 440 + params.getClass()); 441 } 442 } 443 444 /** 445 * Returns the given number of seed bytes. A DRBG always uses 446 * {@link SeedGenerator} to get an array with full-entropy. 447 * <p> 448 * The implementation is identical to SHA1PRNG's 449 * {@link SecureRandom#engineGenerateSeed}. 450 * 451 * @param numBytes the number of seed bytes to generate. 452 * @return the seed bytes. 453 */ 454 public final byte[] engineGenerateSeed(int numBytes) { 455 byte[] b = new byte[numBytes]; 456 SeedGenerator.generateSeed(b); 457 return b; 458 } 459 460 /** 461 * Reseeds this random object with the given seed. A DRBG always expands 462 * or truncates the input to be between {@link #minLength} and 463 * {@link #maxLength} and uses it to instantiate or reseed itself 464 * (depending on whether the DRBG is instantiated). 465 * 466 * @param input the seed 467 */ 468 public final synchronized void engineSetSeed(byte[] input) { 469 if (debug != null) { 470 debug.println(this, "setSeed"); 471 } 472 if (input.length < minLength) { 473 input = Arrays.copyOf(input, minLength); 474 } else if (input.length > maxLength) { 475 input = Arrays.copyOf(input, maxLength); 476 } 477 if (!instantiated) { 478 instantiateIfNecessary(input); 479 } else { 480 reseedAlgorithm(input, null); 481 } 482 } 483 484 // get_entropy_input 485 486 private byte[] getEntropyInput(boolean isPr) { 487 // Should the 1st arg be minEntropy or minLength? 488 // 489 // Technically it should be minEntropy, but CtrDRBG 490 // (not using derivation function) is so confusing 491 // (does it need only strength or seedlen of entropy?) 492 // that it's safer to assume minLength. In all other 493 // cases minLength is equal to minEntropy. 494 return getEntropyInput(minLength, minLength, maxLength, isPr); 495 } 496 497 private byte[] getEntropyInput(int minEntropy, int minLength, 498 int maxLength, boolean pr) { 499 if (debug != null) { 500 debug.println(this, "getEntropy(" + minEntropy + "," + minLength + 501 "," + maxLength + "," + pr + ")"); 502 } 503 EntropySource esNow = es; 504 if (esNow == null) { 505 esNow = pr ? SeederHolder.prseeder : SeederHolder.seeder; 506 } 507 return esNow.getEntropy(minEntropy, minLength, maxLength, pr); 508 } 509 510 // Defaults 511 512 /** 513 * The default {@code EntropySource} determined by system property 514 * "java.security.egd" or security property "securerandom.source". 515 * <p> 516 * This object uses {@link SeedGenerator#generateSeed(byte[])} to 517 * return a byte array containing {@code minLength} bytes. It is 518 * assumed to support prediction resistance and always contains 519 * full-entropy. 520 */ 521 private final static EntropySource defaultES = 522 (minE, minLen, maxLen, pr) -> { 523 byte[] result = new byte[minLen]; 524 SeedGenerator.generateSeed(result); 525 return result; 526 }; 527 528 private static class SeederHolder { 529 530 /** 531 * Default EntropySource for SecureRandom with prediction resistance, 532 */ 533 static final EntropySource prseeder; 534 535 /** 536 * Default EntropySource for SecureRandom without prediction resistance, 537 * which is backed by a DRBG whose EntropySource is {@link #prseeder}. 538 */ 539 static final EntropySource seeder; 540 541 static { 542 prseeder = defaultES; 543 // According to SP800-90C section 7, a DRBG without live 544 // entropy (drbg here, with pr being false) can instantiate 545 // another DRBG with weaker strength. So we choose highest 546 // strength we support. 547 HashDrbg first = new HashDrbg(new MoreDrbgParameters( 548 prseeder, null, "SHA-256", null, false, 549 DrbgParameters.instantiation( 550 256, NONE, 551 SeedGenerator.getSystemEntropy()))); 552 seeder = (entropy, minLen, maxLen, pr) -> { 553 if (pr) { 554 // This SEI does not support pr 555 throw new IllegalArgumentException("pr not supported"); 556 } 557 byte[] result = new byte[minLen]; 558 first.engineNextBytes(result); 559 return result; 560 }; 561 } 562 } 563 564 // Constructor called by overridden methods, initializer... 565 566 /** 567 * A constructor without argument so that an implementation does not 568 * need to always write {@code super(params)}. 569 */ 570 protected AbstractDrbg() { 571 // Nothing 572 } 573 574 /** 575 * A mechanism shall override this constructor to setup {@link #mechName}, 576 * {@link #highestSupportedSecurityStrength}, 577 * {@link #supportPredictionResistance}, {@link #supportReseeding} 578 * or other features like {@link #DEFAULT_STRENGTH}. Finally it shall 579 * call {@link #configure} on {@code params}. 580 * 581 * @param params the {@link SecureRandomParameters} object. 582 * This argument can be {@code null}. 583 * @throws IllegalArgumentException if {@code params} is 584 * inappropriate for this SecureRandom. 585 */ 586 protected AbstractDrbg(SecureRandomParameters params) { 587 // Nothing 588 } 589 590 /** 591 * Returns the current configuration as a {@link DrbgParameters.Instantiation} 592 * object. 593 * 594 * @return the curent configuration 595 */ 596 protected SecureRandomParameters engineGetParameters() { 597 // Or read from variable. 598 return DrbgParameters.instantiation( 599 securityStrength, 600 predictionResistanceFlag ? PR_AND_RESEED : 601 (supportReseeding ? RESEED_ONLY : NONE), 602 personalizationString); 603 } 604 605 /** 606 * Configure this DRBG. This method calls 607 * {@link #chooseAlgorithmAndStrength()} and {@link #initEngine()} 608 * but does not do the actual instantiation. 609 * 610 * @param params configuration, if null, default configuration (default 611 * strength, pr_false, no personalization string) is used. 612 * @throws IllegalArgumentException if {@code params} is 613 * inappropriate for this SecureRandom. 614 */ 615 protected final void configure(SecureRandomParameters params) { 616 if (debug != null) { 617 debug.println(this, "configure " + this + " with " + params); 618 } 619 if (params == null) { 620 params = DrbgParameters.instantiation(-1, RESEED_ONLY, null); 621 } 622 if (params instanceof MoreDrbgParameters) { 623 MoreDrbgParameters m = (MoreDrbgParameters)params; 624 this.requestedNonce = m.nonce; 625 this.es = m.es; 626 this.requestedAlgorithm = m.algorithm; 627 this.usedf = m.usedf; 628 params = DrbgParameters.instantiation(m.strength, 629 m.capability, m.personalizationString); 630 } 631 if (params != null) { 632 if (params instanceof DrbgParameters.Instantiation) { 633 DrbgParameters.Instantiation inst = 634 (DrbgParameters.Instantiation) params; 635 636 // 800-90Ar1 9.1: Instantiate Process. Steps 1-5. 637 638 // Step 1: Check requested_instantiation_security_strength 639 if (inst.getStrength() > highestSupportedSecurityStrength) { 640 throw new IllegalArgumentException("strength too big: " 641 + inst.getStrength()); 642 } 643 644 // Step 2: Check prediction_resistance_flag 645 if (inst.getCapability().supportsPredictionResistance() 646 && !supportPredictionResistance) { 647 throw new IllegalArgumentException("pr not supported"); 648 } 649 650 // Step 3: Check personalization_string 651 byte[] ps = inst.getPersonalizationString(); 652 if (ps != null && ps.length > maxPersonalizationStringLength) { 653 throw new IllegalArgumentException("ps too long: " 654 + ps.length); 655 } 656 657 if (inst.getCapability().supportsReseeding() 658 && !supportReseeding) { 659 throw new IllegalArgumentException("reseed not supported"); 660 } 661 this.personalizationString = ps; 662 this.predictionResistanceFlag = 663 inst.getCapability().supportsPredictionResistance(); 664 this.requestedInstantiationSecurityStrength = inst.getStrength(); 665 } else { 666 throw new IllegalArgumentException("unknown params: " 667 + params.getClass()); 668 } 669 } 670 671 // Step 4: Set security_strength 672 chooseAlgorithmAndStrength(); 673 instantiated = false; 674 675 // Step 5: no-op. 676 677 if (debug != null) { 678 debug.println(this, "configured " + this); 679 } 680 } 681 682 /** 683 * Instantiate if necessary, 684 * 685 * @param entropy a user-provided entropy, the length is already good. 686 * If null, will fetch entropy input automatically. 687 */ 688 private synchronized void instantiateIfNecessary(byte[] entropy) { 689 if (!instantiated) { 690 691 // 800-90Ar1 9.1: Instantiate Process. Steps 6-12. 692 693 // Step 6: Get_entropy_input 694 // Step 7: check error (getEntropyInput throw no exception now) 695 if (entropy == null) { 696 entropy = getEntropyInput(predictionResistanceFlag); 697 } 698 699 // Step 8. nonce 700 if (requestedNonce != null) { 701 nonce = requestedNonce; 702 } else { 703 nonce = NonceProvider.next(); 704 } 705 initEngine(); 706 707 // Step 9-11: Instantiate_algorithm 708 instantiateAlgorithm(entropy); 709 instantiated = true; 710 711 // Step 12: Return 712 } 713 } 714 715 // Nonce provider 716 717 private static class NonceProvider { 718 719 // 128 bits of nonce can be used by 256-bit strength DRBG 720 private static final byte[] block = new byte[16]; 721 722 private static synchronized byte[] next() { 723 int k = 15; 724 while ((k >= 0) && (++block[k] == 0)) { 725 k--; 726 } 727 return block.clone(); 728 } 729 } 730 731 // Misc 732 733 /** A handy method returning hexdump string with no colon or new line. 734 * 735 * @param in input byte array 736 * @return the hexdump string 737 */ 738 protected static String hex(byte[] in) { 739 StringBuilder sb = new StringBuilder(); 740 for (byte b : in) { 741 sb.append(String.format("%02x", b&0xff)); 742 } 743 return sb.toString(); 744 } 745 746 /** 747 * Returns the smallest standard strength (112, 128, 192, 256) that is 748 * greater or equal to the input. 749 * 750 * @param input the input strength 751 * @return the standard strength 752 */ 753 protected static int getStandardStrength(int input) { 754 if (input <= 112) return 112; 755 if (input <= 128) return 128; 756 if (input <= 192) return 192; 757 if (input <= 256) return 256; 758 throw new IllegalArgumentException("input too big: " + input); 759 } 760 761 @Override 762 public String toString() { 763 return mechName + "," + algorithm 764 + "," + securityStrength + "," 765 + (predictionResistanceFlag ? "pr_and_reseed" 766 : (supportReseeding ? "reseed_only" : "none")); 767 } 768 }