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