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