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