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