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 }