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 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 equals 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 }