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