• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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