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