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 }