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