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