1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package javax.crypto; 28 29 import java.util.*; 30 31 import java.security.*; 32 import java.security.Provider.Service; 33 import java.security.spec.*; 34 35 import sun.security.jca.*; 36 import sun.security.jca.GetInstance.Instance; 37 38 /** 39 * This class provides the functionality of a key agreement (or key 40 * exchange) protocol. 41 * <p> 42 * The keys involved in establishing a shared secret are created by one of the 43 * key generators (<code>KeyPairGenerator</code> or 44 * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from 45 * an intermediate phase of the key agreement protocol. 46 * 47 * <p> For each of the correspondents in the key exchange, <code>doPhase</code> 48 * needs to be called. For example, if this key exchange is with one other 49 * party, <code>doPhase</code> needs to be called once, with the 50 * <code>lastPhase</code> flag set to <code>true</code>. 51 * If this key exchange is 52 * with two other parties, <code>doPhase</code> needs to be called twice, 53 * the first time setting the <code>lastPhase</code> flag to 54 * <code>false</code>, and the second time setting it to <code>true</code>. 55 * There may be any number of parties involved in a key exchange. 56 * 57 * <p> Android provides the following <code>KeyAgreement</code> algorithms: 58 * <table> 59 * <thead> 60 * <tr> 61 * <th>Algorithm</th> 62 * <th>Supported API Levels</th> 63 * </tr> 64 * </thead> 65 * <tbody> 66 * <tr> 67 * <td>DH</td> 68 * <td>1+</td> 69 * </tr> 70 * <tr> 71 * <td>ECDH</td> 72 * <td>11+</td> 73 * </tr> 74 * </tbody> 75 * </table> 76 * 77 * This algorithm is described in the <a href= 78 * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> 79 * KeyAgreement section</a> of the 80 * Java Cryptography Architecture Standard Algorithm Name Documentation. 81 * 82 * @author Jan Luehe 83 * 84 * @see KeyGenerator 85 * @see SecretKey 86 * @since 1.4 87 */ 88 89 public class KeyAgreement { 90 91 // Android-removed: this debugging mechanism is not used in Android. 92 /* 93 private static final Debug debug = 94 Debug.getInstance("jca", "KeyAgreement"); 95 96 private static final Debug pdebug = 97 Debug.getInstance("provider", "Provider"); 98 private static final boolean skipDebug = 99 Debug.isOn("engine=") && !Debug.isOn("keyagreement"); 100 */ 101 102 // The provider 103 private Provider provider; 104 105 // The provider implementation (delegate) 106 private KeyAgreementSpi spi; 107 108 // The name of the key agreement algorithm. 109 private final String algorithm; 110 111 // BEGIN Android-removed: Redo the provider selection logic to allow reselecting provider. 112 // When only the algorithm is specified, we want to allow the KeyAgreement provider for that 113 // algorithm to change if multiple providers exist and they support different subsets of 114 // keys. To that end, we don't hold an iterator and exhaust it when we need to choose 115 // a provider like the upstream implementation, we reestablish the list of providers 116 // each time. 117 /* 118 // next service to try in provider selection 119 // null once provider is selected 120 private Service firstService; 121 122 // remaining services to try in provider selection 123 // null once provider is selected 124 private Iterator<Service> serviceIterator; 125 */ 126 // END Android-removed: Redo the provider selection logic to allow reselecting provider. 127 128 private final Object lock; 129 130 /** 131 * Creates a KeyAgreement object. 132 * 133 * @param keyAgreeSpi the delegate 134 * @param provider the provider 135 * @param algorithm the algorithm 136 */ KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider, String algorithm)137 protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider, 138 String algorithm) { 139 this.spi = keyAgreeSpi; 140 this.provider = provider; 141 this.algorithm = algorithm; 142 lock = null; 143 } 144 145 // Android-changed: Remove Service and Iterator from constructor args. KeyAgreement(String algorithm)146 private KeyAgreement(String algorithm) { 147 this.algorithm = algorithm; 148 lock = new Object(); 149 } 150 151 /** 152 * Returns the algorithm name of this <code>KeyAgreement</code> object. 153 * 154 * <p>This is the same name that was specified in one of the 155 * <code>getInstance</code> calls that created this 156 * <code>KeyAgreement</code> object. 157 * 158 * @return the algorithm name of this <code>KeyAgreement</code> object. 159 */ getAlgorithm()160 public final String getAlgorithm() { 161 return this.algorithm; 162 } 163 164 /** 165 * Returns a <code>KeyAgreement</code> object that implements the 166 * specified key agreement algorithm. 167 * 168 * <p> This method traverses the list of registered security Providers, 169 * starting with the most preferred Provider. 170 * A new KeyAgreement object encapsulating the 171 * KeyAgreementSpi implementation from the first 172 * Provider that supports the specified algorithm is returned. 173 * 174 * <p> Note that the list of registered providers may be retrieved via 175 * the {@link Security#getProviders() Security.getProviders()} method. 176 * 177 * @param algorithm the standard name of the requested key agreement 178 * algorithm. 179 * See the KeyAgreement section in the <a href= 180 * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> 181 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 182 * for information about standard algorithm names. 183 * 184 * @return the new <code>KeyAgreement</code> object. 185 * 186 * @exception NullPointerException if the specified algorithm 187 * is null. 188 * 189 * @exception NoSuchAlgorithmException if no Provider supports a 190 * KeyAgreementSpi implementation for the 191 * specified algorithm. 192 * 193 * @see java.security.Provider 194 */ getInstance(String algorithm)195 public static final KeyAgreement getInstance(String algorithm) 196 throws NoSuchAlgorithmException { 197 List<Service> services = 198 GetInstance.getServices("KeyAgreement", algorithm); 199 // make sure there is at least one service from a signed provider 200 Iterator<Service> t = services.iterator(); 201 while (t.hasNext()) { 202 Service s = t.next(); 203 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 204 continue; 205 } 206 // Android-changed: Remove Service and Iterator from constructor args. 207 // return new KeyAgreement(s, t, algorithm); 208 return new KeyAgreement(algorithm); 209 } 210 throw new NoSuchAlgorithmException 211 ("Algorithm " + algorithm + " not available"); 212 } 213 214 /** 215 * Returns a <code>KeyAgreement</code> object that implements the 216 * specified key agreement algorithm. 217 * 218 * <p> A new KeyAgreement object encapsulating the 219 * KeyAgreementSpi implementation from the specified provider 220 * is returned. The specified provider must be registered 221 * in the security provider list. 222 * 223 * <p> Note that the list of registered providers may be retrieved via 224 * the {@link Security#getProviders() Security.getProviders()} method. 225 * 226 * @param algorithm the standard name of the requested key agreement 227 * algorithm. 228 * See the KeyAgreement section in the <a href= 229 * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> 230 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 231 * for information about standard algorithm names. 232 * 233 * @param provider the name of the provider. 234 * 235 * @return the new <code>KeyAgreement</code> object. 236 * 237 * @exception NullPointerException if the specified algorithm 238 * is null. 239 * 240 * @exception NoSuchAlgorithmException if a KeyAgreementSpi 241 * implementation for the specified algorithm is not 242 * available from the specified provider. 243 * 244 * @exception NoSuchProviderException if the specified provider is not 245 * registered in the security provider list. 246 * 247 * @exception IllegalArgumentException if the <code>provider</code> 248 * is null or empty. 249 * 250 * @see java.security.Provider 251 */ getInstance(String algorithm, String provider)252 public static final KeyAgreement getInstance(String algorithm, 253 String provider) throws NoSuchAlgorithmException, 254 NoSuchProviderException { 255 // Android-added: Check for Bouncy Castle deprecation 256 Providers.checkBouncyCastleDeprecation(provider, "KeyAgreement", algorithm); 257 Instance instance = JceSecurity.getInstance 258 ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider); 259 return new KeyAgreement((KeyAgreementSpi)instance.impl, 260 instance.provider, algorithm); 261 } 262 263 /** 264 * Returns a <code>KeyAgreement</code> object that implements the 265 * specified key agreement algorithm. 266 * 267 * <p> A new KeyAgreement object encapsulating the 268 * KeyAgreementSpi implementation from the specified Provider 269 * object is returned. Note that the specified Provider object 270 * does not have to be registered in the provider list. 271 * 272 * @param algorithm the standard name of the requested key agreement 273 * algorithm. 274 * See the KeyAgreement section in the <a href= 275 * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement"> 276 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 277 * for information about standard algorithm names. 278 * 279 * @param provider the provider. 280 * 281 * @return the new <code>KeyAgreement</code> object. 282 * 283 * @exception NullPointerException if the specified algorithm 284 * is null. 285 * 286 * @exception NoSuchAlgorithmException if a KeyAgreementSpi 287 * implementation for the specified algorithm is not available 288 * from the specified Provider object. 289 * 290 * @exception IllegalArgumentException if the <code>provider</code> 291 * is null. 292 * 293 * @see java.security.Provider 294 */ getInstance(String algorithm, Provider provider)295 public static final KeyAgreement getInstance(String algorithm, 296 Provider provider) throws NoSuchAlgorithmException { 297 // Android-added: Check for Bouncy Castle deprecation 298 Providers.checkBouncyCastleDeprecation(provider, "KeyAgreement", algorithm); 299 Instance instance = JceSecurity.getInstance 300 ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider); 301 return new KeyAgreement((KeyAgreementSpi)instance.impl, 302 instance.provider, algorithm); 303 } 304 305 // max number of debug warnings to print from chooseFirstProvider() 306 private static int warnCount = 10; 307 308 /** 309 * Choose the Spi from the first provider available. Used if 310 * delayed provider selection is not possible because init() 311 * is not the first method called. 312 */ chooseFirstProvider()313 void chooseFirstProvider() { 314 if (spi != null) { 315 return; 316 } 317 synchronized (lock) { 318 if (spi != null) { 319 return; 320 } 321 // Android-removed: this debugging mechanism is not used in Android. 322 /* 323 if (debug != null) { 324 int w = --warnCount; 325 if (w >= 0) { 326 debug.println("KeyAgreement.init() not first method " 327 + "called, disabling delayed provider selection"); 328 if (w == 0) { 329 debug.println("Further warnings of this type will " 330 + "be suppressed"); 331 } 332 new Exception("Call trace").printStackTrace(); 333 } 334 } 335 */ 336 Exception lastException = null; 337 // Android-changed: Provider selection; loop over a new list each time. 338 for (Service s : GetInstance.getServices("KeyAgreement", algorithm)) { 339 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 340 continue; 341 } 342 try { 343 Object obj = s.newInstance(null); 344 if (obj instanceof KeyAgreementSpi == false) { 345 continue; 346 } 347 spi = (KeyAgreementSpi)obj; 348 provider = s.getProvider(); 349 // Android-removed: Provider selection; loop over a new list each time. 350 /* 351 // not needed any more 352 firstService = null; 353 serviceIterator = null; 354 */ 355 return; 356 } catch (Exception e) { 357 lastException = e; 358 } 359 } 360 ProviderException e = new ProviderException 361 ("Could not construct KeyAgreementSpi instance"); 362 if (lastException != null) { 363 e.initCause(lastException); 364 } 365 throw e; 366 } 367 } 368 369 private final static int I_NO_PARAMS = 1; 370 private final static int I_PARAMS = 2; 371 implInit(KeyAgreementSpi spi, int type, Key key, AlgorithmParameterSpec params, SecureRandom random)372 private void implInit(KeyAgreementSpi spi, int type, Key key, 373 AlgorithmParameterSpec params, SecureRandom random) 374 throws InvalidKeyException, InvalidAlgorithmParameterException { 375 if (type == I_NO_PARAMS) { 376 spi.engineInit(key, random); 377 } else { // I_PARAMS 378 spi.engineInit(key, params, random); 379 } 380 } 381 chooseProvider(int initType, Key key, AlgorithmParameterSpec params, SecureRandom random)382 private void chooseProvider(int initType, Key key, 383 AlgorithmParameterSpec params, SecureRandom random) 384 throws InvalidKeyException, InvalidAlgorithmParameterException { 385 synchronized (lock) { 386 // Android-changed: Use the currently-selected provider only if no key was provided. 387 // if (spi != null) { 388 if (spi != null && key == null) { 389 implInit(spi, initType, key, params, random); 390 return; 391 } 392 Exception lastException = null; 393 // Android-changed: Provider selection; loop over a new list each time. 394 for (Service s : GetInstance.getServices("KeyAgreement", algorithm)) { 395 // if provider says it does not support this key, ignore it 396 if (s.supportsParameter(key) == false) { 397 continue; 398 } 399 if (JceSecurity.canUseProvider(s.getProvider()) == false) { 400 continue; 401 } 402 try { 403 KeyAgreementSpi spi = (KeyAgreementSpi)s.newInstance(null); 404 implInit(spi, initType, key, params, random); 405 provider = s.getProvider(); 406 this.spi = spi; 407 // Android-removed: Provider selection; loop over a new list each time. 408 /* 409 firstService = null; 410 serviceIterator = null; 411 */ 412 return; 413 } catch (Exception e) { 414 // NoSuchAlgorithmException from newInstance() 415 // InvalidKeyException from init() 416 // RuntimeException (ProviderException) from init() 417 if (lastException == null) { 418 lastException = e; 419 } 420 } 421 } 422 // no working provider found, fail 423 if (lastException instanceof InvalidKeyException) { 424 throw (InvalidKeyException)lastException; 425 } 426 if (lastException instanceof InvalidAlgorithmParameterException) { 427 throw (InvalidAlgorithmParameterException)lastException; 428 } 429 if (lastException instanceof RuntimeException) { 430 throw (RuntimeException)lastException; 431 } 432 String kName = (key != null) ? key.getClass().getName() : "(null)"; 433 throw new InvalidKeyException 434 ("No installed provider supports this key: " 435 + kName, lastException); 436 } 437 } 438 439 /** 440 * Returns the provider of this <code>KeyAgreement</code> object. 441 * 442 * @return the provider of this <code>KeyAgreement</code> object 443 */ getProvider()444 public final Provider getProvider() { 445 chooseFirstProvider(); 446 return this.provider; 447 } 448 449 /** 450 * Initializes this key agreement with the given key, which is required to 451 * contain all the algorithm parameters required for this key agreement. 452 * 453 * <p> If this key agreement requires any random bytes, it will get 454 * them using the 455 * {@link java.security.SecureRandom} 456 * implementation of the highest-priority 457 * installed provider as the source of randomness. 458 * (If none of the installed providers supply an implementation of 459 * SecureRandom, a system-provided source of randomness will be used.) 460 * 461 * @param key the party's private information. For example, in the case 462 * of the Diffie-Hellman key agreement, this would be the party's own 463 * Diffie-Hellman private key. 464 * 465 * @exception InvalidKeyException if the given key is 466 * inappropriate for this key agreement, e.g., is of the wrong type or 467 * has an incompatible algorithm type. 468 */ init(Key key)469 public final void init(Key key) throws InvalidKeyException { 470 init(key, JceSecurity.RANDOM); 471 } 472 473 /** 474 * Initializes this key agreement with the given key and source of 475 * randomness. The given key is required to contain all the algorithm 476 * parameters required for this key agreement. 477 * 478 * <p> If the key agreement algorithm requires random bytes, it gets them 479 * from the given source of randomness, <code>random</code>. 480 * However, if the underlying 481 * algorithm implementation does not require any random bytes, 482 * <code>random</code> is ignored. 483 * 484 * @param key the party's private information. For example, in the case 485 * of the Diffie-Hellman key agreement, this would be the party's own 486 * Diffie-Hellman private key. 487 * @param random the source of randomness 488 * 489 * @exception InvalidKeyException if the given key is 490 * inappropriate for this key agreement, e.g., is of the wrong type or 491 * has an incompatible algorithm type. 492 */ init(Key key, SecureRandom random)493 public final void init(Key key, SecureRandom random) 494 throws InvalidKeyException { 495 // Android-changed: Use the currently-selected provider only if no key was provided. 496 // if (spi != null) { 497 if (spi != null && (key == null || lock == null)) { 498 spi.engineInit(key, random); 499 } else { 500 try { 501 chooseProvider(I_NO_PARAMS, key, null, random); 502 } catch (InvalidAlgorithmParameterException e) { 503 // should never occur 504 throw new InvalidKeyException(e); 505 } 506 } 507 508 // Android-removed: this debugging mechanism is not used in Android. 509 /* 510 if (!skipDebug && pdebug != null) { 511 pdebug.println("KeyAgreement." + algorithm + " algorithm from: " + 512 this.provider.getName()); 513 } 514 */ 515 } 516 517 /** 518 * Initializes this key agreement with the given key and set of 519 * algorithm parameters. 520 * 521 * <p> If this key agreement requires any random bytes, it will get 522 * them using the 523 * {@link java.security.SecureRandom} 524 * implementation of the highest-priority 525 * installed provider as the source of randomness. 526 * (If none of the installed providers supply an implementation of 527 * SecureRandom, a system-provided source of randomness will be used.) 528 * 529 * @param key the party's private information. For example, in the case 530 * of the Diffie-Hellman key agreement, this would be the party's own 531 * Diffie-Hellman private key. 532 * @param params the key agreement parameters 533 * 534 * @exception InvalidKeyException if the given key is 535 * inappropriate for this key agreement, e.g., is of the wrong type or 536 * has an incompatible algorithm type. 537 * @exception InvalidAlgorithmParameterException if the given parameters 538 * are inappropriate for this key agreement. 539 */ init(Key key, AlgorithmParameterSpec params)540 public final void init(Key key, AlgorithmParameterSpec params) 541 throws InvalidKeyException, InvalidAlgorithmParameterException 542 { 543 init(key, params, JceSecurity.RANDOM); 544 } 545 546 /** 547 * Initializes this key agreement with the given key, set of 548 * algorithm parameters, and source of randomness. 549 * 550 * @param key the party's private information. For example, in the case 551 * of the Diffie-Hellman key agreement, this would be the party's own 552 * Diffie-Hellman private key. 553 * @param params the key agreement parameters 554 * @param random the source of randomness 555 * 556 * @exception InvalidKeyException if the given key is 557 * inappropriate for this key agreement, e.g., is of the wrong type or 558 * has an incompatible algorithm type. 559 * @exception InvalidAlgorithmParameterException if the given parameters 560 * are inappropriate for this key agreement. 561 */ init(Key key, AlgorithmParameterSpec params, SecureRandom random)562 public final void init(Key key, AlgorithmParameterSpec params, 563 SecureRandom random) 564 throws InvalidKeyException, InvalidAlgorithmParameterException 565 { 566 if (spi != null) { 567 spi.engineInit(key, params, random); 568 } else { 569 chooseProvider(I_PARAMS, key, params, random); 570 } 571 572 // Android-removed: this debugging mechanism is not used in Android. 573 /* 574 if (!skipDebug && pdebug != null) { 575 pdebug.println("KeyAgreement." + algorithm + " algorithm from: " + 576 this.provider.getName()); 577 } 578 */ 579 } 580 581 /** 582 * Executes the next phase of this key agreement with the given 583 * key that was received from one of the other parties involved in this key 584 * agreement. 585 * 586 * @param key the key for this phase. For example, in the case of 587 * Diffie-Hellman between 2 parties, this would be the other party's 588 * Diffie-Hellman public key. 589 * @param lastPhase flag which indicates whether or not this is the last 590 * phase of this key agreement. 591 * 592 * @return the (intermediate) key resulting from this phase, or null 593 * if this phase does not yield a key 594 * 595 * @exception InvalidKeyException if the given key is inappropriate for 596 * this phase. 597 * @exception IllegalStateException if this key agreement has not been 598 * initialized. 599 */ doPhase(Key key, boolean lastPhase)600 public final Key doPhase(Key key, boolean lastPhase) 601 throws InvalidKeyException, IllegalStateException 602 { 603 chooseFirstProvider(); 604 return spi.engineDoPhase(key, lastPhase); 605 } 606 607 /** 608 * Generates the shared secret and returns it in a new buffer. 609 * 610 * <p>This method resets this <code>KeyAgreement</code> object, so that it 611 * can be reused for further key agreements. Unless this key agreement is 612 * reinitialized with one of the <code>init</code> methods, the same 613 * private information and algorithm parameters will be used for 614 * subsequent key agreements. 615 * 616 * @return the new buffer with the shared secret 617 * 618 * @exception IllegalStateException if this key agreement has not been 619 * completed yet 620 */ generateSecret()621 public final byte[] generateSecret() throws IllegalStateException { 622 chooseFirstProvider(); 623 return spi.engineGenerateSecret(); 624 } 625 626 /** 627 * Generates the shared secret, and places it into the buffer 628 * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive. 629 * 630 * <p>If the <code>sharedSecret</code> buffer is too small to hold the 631 * result, a <code>ShortBufferException</code> is thrown. 632 * In this case, this call should be repeated with a larger output buffer. 633 * 634 * <p>This method resets this <code>KeyAgreement</code> object, so that it 635 * can be reused for further key agreements. Unless this key agreement is 636 * reinitialized with one of the <code>init</code> methods, the same 637 * private information and algorithm parameters will be used for 638 * subsequent key agreements. 639 * 640 * @param sharedSecret the buffer for the shared secret 641 * @param offset the offset in <code>sharedSecret</code> where the 642 * shared secret will be stored 643 * 644 * @return the number of bytes placed into <code>sharedSecret</code> 645 * 646 * @exception IllegalStateException if this key agreement has not been 647 * completed yet 648 * @exception ShortBufferException if the given output buffer is too small 649 * to hold the secret 650 */ generateSecret(byte[] sharedSecret, int offset)651 public final int generateSecret(byte[] sharedSecret, int offset) 652 throws IllegalStateException, ShortBufferException 653 { 654 chooseFirstProvider(); 655 return spi.engineGenerateSecret(sharedSecret, offset); 656 } 657 658 /** 659 * Creates the shared secret and returns it as a <code>SecretKey</code> 660 * object of the specified algorithm. 661 * 662 * <p>This method resets this <code>KeyAgreement</code> object, so that it 663 * can be reused for further key agreements. Unless this key agreement is 664 * reinitialized with one of the <code>init</code> methods, the same 665 * private information and algorithm parameters will be used for 666 * subsequent key agreements. 667 * 668 * @param algorithm the requested secret-key algorithm 669 * 670 * @return the shared secret key 671 * 672 * @exception IllegalStateException if this key agreement has not been 673 * completed yet 674 * @exception NoSuchAlgorithmException if the specified secret-key 675 * algorithm is not available 676 * @exception InvalidKeyException if the shared secret-key material cannot 677 * be used to generate a secret key of the specified algorithm (e.g., 678 * the key material is too short) 679 */ generateSecret(String algorithm)680 public final SecretKey generateSecret(String algorithm) 681 throws IllegalStateException, NoSuchAlgorithmException, 682 InvalidKeyException 683 { 684 chooseFirstProvider(); 685 return spi.engineGenerateSecret(algorithm); 686 } 687 } 688