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