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 }