1 /*
2  * Copyright (c) 1997, 2017, 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.*;
29 
30 import java.security.spec.AlgorithmParameterSpec;
31 
32 import java.security.Provider.Service;
33 
34 import sun.security.jca.*;
35 import sun.security.jca.GetInstance.Instance;
36 import sun.security.util.Debug;
37 
38 /**
39  * The KeyPairGenerator class is used to generate pairs of
40  * public and private keys. Key pair generators are constructed using the
41  * {@code getInstance} factory methods (static methods that
42  * return instances of a given class).
43  *
44  * <p>A Key pair generator for a particular algorithm creates a public/private
45  * key pair that can be used with this algorithm. It also associates
46  * algorithm-specific parameters with each of the generated keys.
47  *
48  * <p>There are two ways to generate a key pair: in an algorithm-independent
49  * manner, and in an algorithm-specific manner.
50  * The only difference between the two is the initialization of the object:
51  *
52  * <ul>
53  * <li><b>Algorithm-Independent Initialization</b>
54  * <p>All key pair generators share the concepts of a keysize and a
55  * source of randomness. The keysize is interpreted differently for different
56  * algorithms (e.g., in the case of the <i>DSA</i> algorithm, the keysize
57  * corresponds to the length of the modulus).
58  * There is an
59  * {@link #initialize(int, java.security.SecureRandom) initialize}
60  * method in this KeyPairGenerator class that takes these two universally
61  * shared types of arguments. There is also one that takes just a
62  * {@code keysize} argument, and uses the {@code SecureRandom}
63  * implementation of the highest-priority installed provider as the source
64  * of randomness. (If none of the installed providers supply an implementation
65  * of {@code SecureRandom}, a system-provided source of randomness is
66  * used.)
67  *
68  * <p>Since no other parameters are specified when you call the above
69  * algorithm-independent {@code initialize} methods, it is up to the
70  * provider what to do about the algorithm-specific parameters (if any) to be
71  * associated with each of the keys.
72  *
73  * <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus
74  * size) is 512, 768, 1024, or 2048, then the <i>Sun</i> provider uses a set of
75  * precomputed values for the {@code p}, {@code q}, and
76  * {@code g} parameters. If the modulus size is not one of the above
77  * values, the <i>Sun</i> provider creates a new set of parameters. Other
78  * providers might have precomputed parameter sets for more than just the
79  * modulus sizes mentioned above. Still others might not have a list of
80  * precomputed parameters at all and instead always create new parameter sets.
81  *
82  * <li><b>Algorithm-Specific Initialization</b>
83  * <p>For situations where a set of algorithm-specific parameters already
84  * exists (e.g., so-called <i>community parameters</i> in DSA), there are two
85  * {@link #initialize(java.security.spec.AlgorithmParameterSpec)
86  * initialize} methods that have an {@code AlgorithmParameterSpec}
87  * argument. One also has a {@code SecureRandom} argument, while
88  * the other uses the {@code SecureRandom}
89  * implementation of the highest-priority installed provider as the source
90  * of randomness. (If none of the installed providers supply an implementation
91  * of {@code SecureRandom}, a system-provided source of randomness is
92  * used.)
93  * </ul>
94  *
95  * <p>In case the client does not explicitly initialize the KeyPairGenerator
96  * (via a call to an {@code initialize} method), each provider must
97  * supply (and document) a default initialization.
98  * See the Keysize Restriction sections of the
99  * {@extLink security_guide_jdk_providers JDK Providers}
100  * document for information on the KeyPairGenerator defaults used by
101  * JDK providers.
102  * However, note that defaults may vary across different providers.
103  * Additionally, the default value for a provider may change in a future
104  * version. Therefore, it is recommended to explicitly initialize the
105  * KeyPairGenerator instead of relying on provider-specific defaults.
106  *
107  * <p>Note that this class is abstract and extends from
108  * {@code KeyPairGeneratorSpi} for historical reasons.
109  * Application developers should only take notice of the methods defined in
110  * this {@code KeyPairGenerator} class; all the methods in
111  * the superclass are intended for cryptographic service providers who wish to
112  * supply their own implementations of key pair generators.
113  *
114  * <p> Every implementation of the Java platform is required to support the
115  * following standard {@code KeyPairGenerator} algorithms and keysizes in
116  * parentheses:
117  * <ul>
118  * <li>{@code DiffieHellman} (1024, 2048, 4096)</li>
119  * <li>{@code DSA} (1024, 2048)</li>
120  * <li>{@code RSA} (1024, 2048, 4096)</li>
121  * </ul>
122  * These algorithms are described in the <a href=
123  * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
124  * KeyPairGenerator section</a> of the
125  * Java Security Standard Algorithm Names Specification.
126  * Consult the release documentation for your implementation to see if any
127  * other algorithms are supported.
128  *
129  * @author Benjamin Renaud
130  * @since 1.1
131  *
132  * @see java.security.spec.AlgorithmParameterSpec
133  */
134 
135 public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
136 
137     private static final Debug pdebug =
138                         Debug.getInstance("provider", "Provider");
139     private static final boolean skipDebug =
140         Debug.isOn("engine=") && !Debug.isOn("keypairgenerator");
141 
142     private final String algorithm;
143 
144     // The provider
145     Provider provider;
146 
147     /**
148      * Creates a KeyPairGenerator object for the specified algorithm.
149      *
150      * @param algorithm the standard string name of the algorithm.
151      * See the KeyPairGenerator section in the <a href=
152      * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
153      * Java Security Standard Algorithm Names Specification</a>
154      * for information about standard algorithm names.
155      */
KeyPairGenerator(String algorithm)156     protected KeyPairGenerator(String algorithm) {
157         this.algorithm = algorithm;
158     }
159 
160     /**
161      * Returns the standard name of the algorithm for this key pair generator.
162      * See the KeyPairGenerator section in the <a href=
163      * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
164      * Java Security Standard Algorithm Names Specification</a>
165      * for information about standard algorithm names.
166      *
167      * @return the standard string name of the algorithm.
168      */
getAlgorithm()169     public String getAlgorithm() {
170         return this.algorithm;
171     }
172 
getInstance(Instance instance, String algorithm)173     private static KeyPairGenerator getInstance(Instance instance,
174             String algorithm) {
175         KeyPairGenerator kpg;
176         if (instance.impl instanceof KeyPairGenerator) {
177             kpg = (KeyPairGenerator)instance.impl;
178         } else {
179             KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl;
180             kpg = new Delegate(spi, algorithm);
181         }
182         kpg.provider = instance.provider;
183 
184         if (!skipDebug && pdebug != null) {
185             pdebug.println("KeyPairGenerator." + algorithm +
186                 " algorithm from: " + kpg.provider.getName());
187         }
188 
189         return kpg;
190     }
191 
192     /**
193      * Returns a KeyPairGenerator object that generates public/private
194      * key pairs for the specified algorithm.
195      *
196      * <p> This method traverses the list of registered security Providers,
197      * starting with the most preferred Provider.
198      * A new KeyPairGenerator object encapsulating the
199      * KeyPairGeneratorSpi implementation from the first
200      * Provider that supports the specified algorithm is returned.
201      *
202      * <p> Note that the list of registered providers may be retrieved via
203      * the {@link Security#getProviders() Security.getProviders()} method.
204      *
205      * @implNote
206      * The JDK Reference Implementation additionally uses the
207      * {@code jdk.security.provider.preferred}
208      * {@link Security#getProperty(String) Security} property to determine
209      * the preferred provider order for the specified algorithm. This
210      * may be different than the order of providers returned by
211      * {@link Security#getProviders() Security.getProviders()}.
212      *
213      * @param algorithm the standard string name of the algorithm.
214      * See the KeyPairGenerator section in the <a href=
215      * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
216      * Java Security Standard Algorithm Names Specification</a>
217      * for information about standard algorithm names.
218      *
219      * @return the new {@code KeyPairGenerator} object
220      *
221      * @throws NoSuchAlgorithmException if no {@code Provider} supports a
222      *         {@code KeyPairGeneratorSpi} implementation for the
223      *         specified algorithm
224      *
225      * @throws NullPointerException if {@code algorithm} is {@code null}
226      *
227      * @see Provider
228      */
getInstance(String algorithm)229     public static KeyPairGenerator getInstance(String algorithm)
230             throws NoSuchAlgorithmException {
231         Objects.requireNonNull(algorithm, "null algorithm name");
232         List<Service> list =
233                 GetInstance.getServices("KeyPairGenerator", algorithm);
234         Iterator<Service> t = list.iterator();
235         if (t.hasNext() == false) {
236             throw new NoSuchAlgorithmException
237                 (algorithm + " KeyPairGenerator not available");
238         }
239         // find a working Spi or KeyPairGenerator subclass
240         NoSuchAlgorithmException failure = null;
241         do {
242             Service s = t.next();
243             try {
244                 Instance instance =
245                     GetInstance.getInstance(s, KeyPairGeneratorSpi.class);
246                 if (instance.impl instanceof KeyPairGenerator) {
247                     return getInstance(instance, algorithm);
248                 } else {
249                     return new Delegate(instance, t, algorithm);
250                 }
251             } catch (NoSuchAlgorithmException e) {
252                 if (failure == null) {
253                     failure = e;
254                 }
255             }
256         } while (t.hasNext());
257         throw failure;
258     }
259 
260     /**
261      * Returns a KeyPairGenerator object that generates public/private
262      * key pairs for the specified algorithm.
263      *
264      * <p> A new KeyPairGenerator object encapsulating the
265      * KeyPairGeneratorSpi implementation from the specified provider
266      * is returned.  The specified provider must be registered
267      * in the security provider list.
268      *
269      * <p> Note that the list of registered providers may be retrieved via
270      * the {@link Security#getProviders() Security.getProviders()} method.
271      *
272      * @param algorithm the standard string name of the algorithm.
273      * See the KeyPairGenerator section in the <a href=
274      * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
275      * Java Security Standard Algorithm Names Specification</a>
276      * for information about standard algorithm names.
277      *
278      * @param provider the string name of the provider.
279      *
280      * @return the new {@code KeyPairGenerator} object
281      *
282      * @throws IllegalArgumentException if the provider name is {@code null}
283      *         or empty
284      *
285      * @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}
286      *         implementation for the specified algorithm is not
287      *         available from the specified provider
288      *
289      * @throws NoSuchProviderException if the specified provider is not
290      *         registered in the security provider list
291      *
292      * @throws NullPointerException if {@code algorithm} is {@code null}
293      *
294      * @see Provider
295      */
getInstance(String algorithm, String provider)296     public static KeyPairGenerator getInstance(String algorithm,
297             String provider)
298             throws NoSuchAlgorithmException, NoSuchProviderException {
299         Objects.requireNonNull(algorithm, "null algorithm name");
300         Instance instance = GetInstance.getInstance("KeyPairGenerator",
301                 KeyPairGeneratorSpi.class, algorithm, provider);
302         return getInstance(instance, algorithm);
303     }
304 
305     /**
306      * Returns a KeyPairGenerator object that generates public/private
307      * key pairs for the specified algorithm.
308      *
309      * <p> A new KeyPairGenerator object encapsulating the
310      * KeyPairGeneratorSpi implementation from the specified Provider
311      * object is returned.  Note that the specified Provider object
312      * does not have to be registered in the provider list.
313      *
314      * @param algorithm the standard string name of the algorithm.
315      * See the KeyPairGenerator section in the <a href=
316      * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
317      * Java Security Standard Algorithm Names Specification</a>
318      * for information about standard algorithm names.
319      *
320      * @param provider the provider.
321      *
322      * @return the new {@code KeyPairGenerator} object
323      *
324      * @throws IllegalArgumentException if the specified provider is
325      *         {@code null}
326      *
327      * @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}
328      *         implementation for the specified algorithm is not available
329      *         from the specified {@code Provider} object
330      *
331      * @throws NullPointerException if {@code algorithm} is {@code null}
332      *
333      * @see Provider
334      *
335      * @since 1.4
336      */
getInstance(String algorithm, Provider provider)337     public static KeyPairGenerator getInstance(String algorithm,
338             Provider provider) throws NoSuchAlgorithmException {
339         Objects.requireNonNull(algorithm, "null algorithm name");
340         Instance instance = GetInstance.getInstance("KeyPairGenerator",
341                 KeyPairGeneratorSpi.class, algorithm, provider);
342         return getInstance(instance, algorithm);
343     }
344 
345     /**
346      * Returns the provider of this key pair generator object.
347      *
348      * @return the provider of this key pair generator object
349      */
getProvider()350     public final Provider getProvider() {
351         disableFailover();
352         return this.provider;
353     }
354 
disableFailover()355     void disableFailover() {
356         // empty, overridden in Delegate
357     }
358 
359     /**
360      * Initializes the key pair generator for a certain keysize using
361      * a default parameter set and the {@code SecureRandom}
362      * implementation of the highest-priority installed provider as the source
363      * of randomness.
364      * (If none of the installed providers supply an implementation of
365      * {@code SecureRandom}, a system-provided source of randomness is
366      * used.)
367      *
368      * @param keysize the keysize. This is an
369      * algorithm-specific metric, such as modulus length, specified in
370      * number of bits.
371      *
372      * @exception InvalidParameterException if the {@code keysize} is not
373      * supported by this KeyPairGenerator object.
374      */
initialize(int keysize)375     public void initialize(int keysize) {
376         initialize(keysize, JCAUtil.getSecureRandom());
377     }
378 
379     /**
380      * Initializes the key pair generator for a certain keysize with
381      * the given source of randomness (and a default parameter set).
382      *
383      * @param keysize the keysize. This is an
384      * algorithm-specific metric, such as modulus length, specified in
385      * number of bits.
386      * @param random the source of randomness.
387      *
388      * @exception InvalidParameterException if the {@code keysize} is not
389      * supported by this KeyPairGenerator object.
390      *
391      * @since 1.2
392      */
initialize(int keysize, SecureRandom random)393     public void initialize(int keysize, SecureRandom random) {
394         // This does nothing, because either
395         // 1. the implementation object returned by getInstance() is an
396         //    instance of KeyPairGenerator which has its own
397         //    initialize(keysize, random) method, so the application would
398         //    be calling that method directly, or
399         // 2. the implementation returned by getInstance() is an instance
400         //    of Delegate, in which case initialize(keysize, random) is
401         //    overridden to call the corresponding SPI method.
402         // (This is a special case, because the API and SPI method have the
403         // same name.)
404     }
405 
406     /**
407      * Initializes the key pair generator using the specified parameter
408      * set and the {@code SecureRandom}
409      * implementation of the highest-priority installed provider as the source
410      * of randomness.
411      * (If none of the installed providers supply an implementation of
412      * {@code SecureRandom}, a system-provided source of randomness is
413      * used.)
414      *
415      * <p>This concrete method has been added to this previously-defined
416      * abstract class.
417      * This method calls the KeyPairGeneratorSpi
418      * {@link KeyPairGeneratorSpi#initialize(
419      * java.security.spec.AlgorithmParameterSpec,
420      * java.security.SecureRandom) initialize} method,
421      * passing it {@code params} and a source of randomness (obtained
422      * from the highest-priority installed provider or system-provided if none
423      * of the installed providers supply one).
424      * That {@code initialize} method always throws an
425      * UnsupportedOperationException if it is not overridden by the provider.
426      *
427      * @param params the parameter set used to generate the keys.
428      *
429      * @exception InvalidAlgorithmParameterException if the given parameters
430      * are inappropriate for this key pair generator.
431      *
432      * @since 1.2
433      */
initialize(AlgorithmParameterSpec params)434     public void initialize(AlgorithmParameterSpec params)
435             throws InvalidAlgorithmParameterException {
436         initialize(params, JCAUtil.getSecureRandom());
437     }
438 
439     /**
440      * Initializes the key pair generator with the given parameter
441      * set and source of randomness.
442      *
443      * <p>This concrete method has been added to this previously-defined
444      * abstract class.
445      * This method calls the KeyPairGeneratorSpi {@link
446      * KeyPairGeneratorSpi#initialize(
447      * java.security.spec.AlgorithmParameterSpec,
448      * java.security.SecureRandom) initialize} method,
449      * passing it {@code params} and {@code random}.
450      * That {@code initialize}
451      * method always throws an
452      * UnsupportedOperationException if it is not overridden by the provider.
453      *
454      * @param params the parameter set used to generate the keys.
455      * @param random the source of randomness.
456      *
457      * @exception InvalidAlgorithmParameterException if the given parameters
458      * are inappropriate for this key pair generator.
459      *
460      * @since 1.2
461      */
initialize(AlgorithmParameterSpec params, SecureRandom random)462     public void initialize(AlgorithmParameterSpec params,
463                            SecureRandom random)
464         throws InvalidAlgorithmParameterException
465     {
466         // This does nothing, because either
467         // 1. the implementation object returned by getInstance() is an
468         //    instance of KeyPairGenerator which has its own
469         //    initialize(params, random) method, so the application would
470         //    be calling that method directly, or
471         // 2. the implementation returned by getInstance() is an instance
472         //    of Delegate, in which case initialize(params, random) is
473         //    overridden to call the corresponding SPI method.
474         // (This is a special case, because the API and SPI method have the
475         // same name.)
476     }
477 
478     /**
479      * Generates a key pair.
480      *
481      * <p>If this KeyPairGenerator has not been initialized explicitly,
482      * provider-specific defaults will be used for the size and other
483      * (algorithm-specific) values of the generated keys.
484      *
485      * <p>This will generate a new key pair every time it is called.
486      *
487      * <p>This method is functionally equivalent to
488      * {@link #generateKeyPair() generateKeyPair}.
489      *
490      * @return the generated key pair
491      *
492      * @since 1.2
493      */
genKeyPair()494     public final KeyPair genKeyPair() {
495         return generateKeyPair();
496     }
497 
498     /**
499      * Generates a key pair.
500      *
501      * <p>If this KeyPairGenerator has not been initialized explicitly,
502      * provider-specific defaults will be used for the size and other
503      * (algorithm-specific) values of the generated keys.
504      *
505      * <p>This will generate a new key pair every time it is called.
506      *
507      * <p>This method is functionally equivalent to
508      * {@link #genKeyPair() genKeyPair}.
509      *
510      * @return the generated key pair
511      */
generateKeyPair()512     public KeyPair generateKeyPair() {
513         // This does nothing (except returning null), because either:
514         //
515         // 1. the implementation object returned by getInstance() is an
516         //    instance of KeyPairGenerator which has its own implementation
517         //    of generateKeyPair (overriding this one), so the application
518         //    would be calling that method directly, or
519         //
520         // 2. the implementation returned by getInstance() is an instance
521         //    of Delegate, in which case generateKeyPair is
522         //    overridden to invoke the corresponding SPI method.
523         //
524         // (This is a special case, because in JDK 1.1.x the generateKeyPair
525         // method was used both as an API and a SPI method.)
526         return null;
527     }
528 
529 
530     /*
531      * The following class allows providers to extend from KeyPairGeneratorSpi
532      * rather than from KeyPairGenerator. It represents a KeyPairGenerator
533      * with an encapsulated, provider-supplied SPI object (of type
534      * KeyPairGeneratorSpi).
535      * If the provider implementation is an instance of KeyPairGeneratorSpi,
536      * the getInstance() methods above return an instance of this class, with
537      * the SPI object encapsulated.
538      *
539      * Note: All SPI methods from the original KeyPairGenerator class have been
540      * moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has
541      * been interposed in the hierarchy between the API (KeyPairGenerator)
542      * and its original parent (Object).
543      */
544 
545     //
546     // error failover notes:
547     //
548     //  . we failover if the implementation throws an error during init
549     //    by retrying the init on other providers
550     //
551     //  . we also failover if the init succeeded but the subsequent call
552     //    to generateKeyPair() fails. In order for this to work, we need
553     //    to remember the parameters to the last successful call to init
554     //    and initialize() the next spi using them.
555     //
556     //  . although not specified, KeyPairGenerators could be thread safe,
557     //    so we make sure we do not interfere with that
558     //
559     //  . failover is not available, if:
560     //    . getInstance(algorithm, provider) was used
561     //    . a provider extends KeyPairGenerator rather than
562     //      KeyPairGeneratorSpi (JDK 1.1 style)
563     //    . once getProvider() is called
564     //
565 
566     private static final class Delegate extends KeyPairGenerator {
567 
568         // The provider implementation (delegate)
569         private volatile KeyPairGeneratorSpi spi;
570 
571         private final Object lock = new Object();
572 
573         private Iterator<Service> serviceIterator;
574 
575         private static final int I_NONE   = 1;
576         private static final int I_SIZE   = 2;
577         private static final int I_PARAMS = 3;
578 
579         private int initType;
580         private int initKeySize;
581         private AlgorithmParameterSpec initParams;
582         private SecureRandom initRandom;
583 
584         // constructor
Delegate(KeyPairGeneratorSpi spi, String algorithm)585         Delegate(KeyPairGeneratorSpi spi, String algorithm) {
586             super(algorithm);
587             this.spi = spi;
588         }
589 
Delegate(Instance instance, Iterator<Service> serviceIterator, String algorithm)590         Delegate(Instance instance, Iterator<Service> serviceIterator,
591                 String algorithm) {
592             super(algorithm);
593             spi = (KeyPairGeneratorSpi)instance.impl;
594             provider = instance.provider;
595             this.serviceIterator = serviceIterator;
596             initType = I_NONE;
597 
598             if (!skipDebug && pdebug != null) {
599                 pdebug.println("KeyPairGenerator." + algorithm +
600                     " algorithm from: " + provider.getName());
601             }
602         }
603 
604         /**
605          * Update the active spi of this class and return the next
606          * implementation for failover. If no more implemenations are
607          * available, this method returns null. However, the active spi of
608          * this class is never set to null.
609          */
nextSpi(KeyPairGeneratorSpi oldSpi, boolean reinit)610         private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi,
611                 boolean reinit) {
612             synchronized (lock) {
613                 // somebody else did a failover concurrently
614                 // try that spi now
615                 if ((oldSpi != null) && (oldSpi != spi)) {
616                     return spi;
617                 }
618                 if (serviceIterator == null) {
619                     return null;
620                 }
621                 while (serviceIterator.hasNext()) {
622                     Service s = serviceIterator.next();
623                     try {
624                         Object inst = s.newInstance(null);
625                         // ignore non-spis
626                         if (inst instanceof KeyPairGeneratorSpi == false) {
627                             continue;
628                         }
629                         if (inst instanceof KeyPairGenerator) {
630                             continue;
631                         }
632                         KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)inst;
633                         if (reinit) {
634                             if (initType == I_SIZE) {
635                                 spi.initialize(initKeySize, initRandom);
636                             } else if (initType == I_PARAMS) {
637                                 spi.initialize(initParams, initRandom);
638                             } else if (initType != I_NONE) {
639                                 throw new AssertionError
640                                     ("KeyPairGenerator initType: " + initType);
641                             }
642                         }
643                         provider = s.getProvider();
644                         this.spi = spi;
645                         return spi;
646                     } catch (Exception e) {
647                         // ignore
648                     }
649                 }
650                 disableFailover();
651                 return null;
652             }
653         }
654 
disableFailover()655         void disableFailover() {
656             serviceIterator = null;
657             initType = 0;
658             initParams = null;
659             initRandom = null;
660         }
661 
662         // engine method
initialize(int keysize, SecureRandom random)663         public void initialize(int keysize, SecureRandom random) {
664             if (serviceIterator == null) {
665                 spi.initialize(keysize, random);
666                 return;
667             }
668             RuntimeException failure = null;
669             KeyPairGeneratorSpi mySpi = spi;
670             do {
671                 try {
672                     mySpi.initialize(keysize, random);
673                     initType = I_SIZE;
674                     initKeySize = keysize;
675                     initParams = null;
676                     initRandom = random;
677                     return;
678                 } catch (RuntimeException e) {
679                     if (failure == null) {
680                         failure = e;
681                     }
682                     mySpi = nextSpi(mySpi, false);
683                 }
684             } while (mySpi != null);
685             throw failure;
686         }
687 
688         // engine method
initialize(AlgorithmParameterSpec params, SecureRandom random)689         public void initialize(AlgorithmParameterSpec params,
690                 SecureRandom random) throws InvalidAlgorithmParameterException {
691             if (serviceIterator == null) {
692                 spi.initialize(params, random);
693                 return;
694             }
695             Exception failure = null;
696             KeyPairGeneratorSpi mySpi = spi;
697             do {
698                 try {
699                     mySpi.initialize(params, random);
700                     initType = I_PARAMS;
701                     initKeySize = 0;
702                     initParams = params;
703                     initRandom = random;
704                     return;
705                 } catch (Exception e) {
706                     if (failure == null) {
707                         failure = e;
708                     }
709                     mySpi = nextSpi(mySpi, false);
710                 }
711             } while (mySpi != null);
712             if (failure instanceof RuntimeException) {
713                 throw (RuntimeException)failure;
714             }
715             // must be an InvalidAlgorithmParameterException
716             throw (InvalidAlgorithmParameterException)failure;
717         }
718 
719         // engine method
generateKeyPair()720         public KeyPair generateKeyPair() {
721             if (serviceIterator == null) {
722                 return spi.generateKeyPair();
723             }
724             RuntimeException failure = null;
725             KeyPairGeneratorSpi mySpi = spi;
726             do {
727                 try {
728                     return mySpi.generateKeyPair();
729                 } catch (RuntimeException e) {
730                     if (failure == null) {
731                         failure = e;
732                     }
733                     mySpi = nextSpi(mySpi, true);
734                 }
735             } while (mySpi != null);
736             throw failure;
737         }
738     }
739 
740 }
741