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