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