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