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