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