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 javax.crypto;
27 
28 import java.util.*;
29 
30 import java.security.*;
31 import java.security.Provider.Service;
32 import java.security.spec.*;
33 
34 import sun.security.jca.*;
35 import sun.security.jca.GetInstance.Instance;
36 
37 /**
38  * This class represents a factory for secret keys.
39  *
40  * <P> Key factories are used to convert <I>keys</I> (opaque
41  * cryptographic keys of type <code>Key</code>) into <I>key specifications</I>
42  * (transparent representations of the underlying key material), and vice
43  * versa.
44  * Secret key factories operate only on secret (symmetric) keys.
45  *
46  * <P> Key factories are bi-directional, i.e., they allow to build an opaque
47  * key object from a given key specification (key material), or to retrieve
48  * the underlying key material of a key object in a suitable format.
49  *
50  * <P> Application developers should refer to their provider's documentation
51  * to find out which key specifications are supported by the
52  * {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and
53  * {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec}
54  * methods.
55  * For example, the DES secret-key factory supplied by the "SunJCE" provider
56  * supports <code>DESKeySpec</code> as a transparent representation of DES
57  * keys, and that provider's secret-key factory for Triple DES keys supports
58  * <code>DESedeKeySpec</code> as a transparent representation of Triple DES
59  * keys.
60  *
61  * <p> Android provides the following <code>SecretKeyFactory</code> algorithms:
62  * <table>
63  *   <thead>
64  *     <tr>
65  *       <th>Algorithm</th>
66  *       <th>Supported API Levels</th>
67  *     </tr>
68  *   </thead>
69  *   <tbody>
70  *     <tr>
71  *       <td>AES</td>
72  *       <td>23+</td>
73  *     </tr>
74  *     <tr>
75  *       <td>DES</td>
76  *       <td>1+</td>
77  *     </tr>
78  *     <tr>
79  *       <td>DESede</td>
80  *       <td>1+</td>
81  *     </tr>
82  *     <tr>
83  *       <td>HmacSHA1</td>
84  *       <td>23+</td>
85  *     </tr>
86  *     <tr>
87  *       <td>HmacSHA224</td>
88  *       <td>23+</td>
89  *     </tr>
90  *     <tr>
91  *       <td>HmacSHA256</td>
92  *       <td>23+</td>
93  *     </tr>
94  *     <tr>
95  *       <td>HmacSHA384</td>
96  *       <td>23+</td>
97  *     </tr>
98  *     <tr>
99  *       <td>HmacSHA512</td>
100  *       <td>23+</td>
101  *     </tr>
102  *     <tr>
103  *       <td>PBEwithHmacSHA1</td>
104  *       <td>1+</td>
105  *     </tr>
106  *     <tr>
107  *       <td>PBEwithHmacSHA1AndAES_128</td>
108  *       <td>26+</td>
109  *     </tr>
110  *     <tr>
111  *       <td>PBEwithHmacSHA1AndAES_256</td>
112  *       <td>26+</td>
113  *     </tr>
114  *     <tr>
115  *       <td>PBEwithHmacSHA224AndAES_128</td>
116  *       <td>26+</td>
117  *     </tr>
118  *     <tr>
119  *       <td>PBEwithHmacSHA224AndAES_256</td>
120  *       <td>26+</td>
121  *     </tr>
122  *     <tr>
123  *       <td>PBEwithHmacSHA256AndAES_128</td>
124  *       <td>26+</td>
125  *     </tr>
126  *     <tr>
127  *       <td>PBEwithHmacSHA256AndAES_256</td>
128  *       <td>26+</td>
129  *     </tr>
130  *     <tr>
131  *       <td>PBEwithHmacSHA384AndAES_128</td>
132  *       <td>26+</td>
133  *     </tr>
134  *     <tr>
135  *       <td>PBEwithHmacSHA384AndAES_256</td>
136  *       <td>26+</td>
137  *     </tr>
138  *     <tr>
139  *       <td>PBEwithHmacSHA512AndAES_128</td>
140  *       <td>26+</td>
141  *     </tr>
142  *     <tr>
143  *       <td>PBEwithHmacSHA512AndAES_256</td>
144  *       <td>26+</td>
145  *     </tr>
146  *     <tr>
147  *       <td>PBEwithMD5AND128BITAES-CBC-OPENSSL</td>
148  *       <td>1+</td>
149  *     </tr>
150  *     <tr>
151  *       <td>PBEwithMD5AND192BITAES-CBC-OPENSSL</td>
152  *       <td>1+</td>
153  *     </tr>
154  *     <tr>
155  *       <td>PBEwithMD5AND256BITAES-CBC-OPENSSL</td>
156  *       <td>1+</td>
157  *     </tr>
158  *     <tr>
159  *       <td>PBEwithMD5ANDDES</td>
160  *       <td>1+</td>
161  *     </tr>
162  *     <tr>
163  *       <td>PBEwithMD5ANDRC2</td>
164  *       <td>1+</td>
165  *     </tr>
166  *     <tr>
167  *       <td>PBEwithSHA1ANDDES</td>
168  *       <td>1+</td>
169  *     </tr>
170  *     <tr>
171  *       <td>PBEwithSHA1ANDRC2</td>
172  *       <td>1+</td>
173  *     </tr>
174  *     <tr>
175  *       <td>PBEwithSHA256AND128BITAES-CBC-BC</td>
176  *       <td>1+</td>
177  *     </tr>
178  *     <tr>
179  *       <td>PBEwithSHA256AND192BITAES-CBC-BC</td>
180  *       <td>1+</td>
181  *     </tr>
182  *     <tr>
183  *       <td>PBEwithSHA256AND256BITAES-CBC-BC</td>
184  *       <td>1+</td>
185  *     </tr>
186  *     <tr>
187  *       <td>PBEwithSHAAND128BITAES-CBC-BC</td>
188  *       <td>1+</td>
189  *     </tr>
190  *     <tr>
191  *       <td>PBEwithSHAAND128BITRC2-CBC</td>
192  *       <td>10+</td>
193  *     </tr>
194  *     <tr>
195  *       <td>PBEwithSHAAND128BITRC4</td>
196  *       <td>10+</td>
197  *     </tr>
198  *     <tr>
199  *       <td>PBEwithSHAAND192BITAES-CBC-BC</td>
200  *       <td>1+</td>
201  *     </tr>
202  *     <tr>
203  *       <td>PBEwithSHAAND2-KEYTRIPLEDES-CBC</td>
204  *       <td>1+</td>
205  *     </tr>
206  *     <tr>
207  *       <td>PBEwithSHAAND256BITAES-CBC-BC</td>
208  *       <td>1+</td>
209  *     </tr>
210  *     <tr>
211  *       <td>PBEwithSHAAND3-KEYTRIPLEDES-CBC</td>
212  *       <td>1+</td>
213  *     </tr>
214  *     <tr>
215  *       <td>PBEwithSHAAND40BITRC2-CBC</td>
216  *       <td>1+</td>
217  *     </tr>
218  *     <tr>
219  *       <td>PBEwithSHAAND40BITRC4</td>
220  *       <td>10+</td>
221  *     </tr>
222  *     <tr>
223  *       <td>PBEwithSHAANDTWOFISH-CBC</td>
224  *       <td>10+</td>
225  *     </tr>
226  *     <tr>
227  *       <td>PBKDF2withHmacSHA1</td>
228  *       <td>10+</td>
229  *     </tr>
230  *     <tr>
231  *       <td>PBKDF2withHmacSHA1And8BIT</td>
232  *       <td>19+</td>
233  *     </tr>
234  *     <tr>
235  *       <td>PBKDF2withHmacSHA224</td>
236  *       <td>26+</td>
237  *     </tr>
238  *     <tr>
239  *       <td>PBKDF2withHmacSHA256</td>
240  *       <td>26+</td>
241  *     </tr>
242  *     <tr>
243  *       <td>PBKDF2withHmacSHA384</td>
244  *       <td>26+</td>
245  *     </tr>
246  *     <tr>
247  *       <td>PBKDF2withHmacSHA512</td>
248  *       <td>26+</td>
249  *     </tr>
250  *   </tbody>
251  * </table>
252  *
253  * These algorithms are described in the <a href=
254  * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
255  * SecretKeyFactory section</a> of the
256  * Java Cryptography Architecture Standard Algorithm Name Documentation.
257  *
258  * @author Jan Luehe
259  *
260  * @see SecretKey
261  * @see javax.crypto.spec.DESKeySpec
262  * @see javax.crypto.spec.DESedeKeySpec
263  * @see javax.crypto.spec.PBEKeySpec
264  * @since 1.4
265  */
266 
267 public class SecretKeyFactory {
268 
269     // The provider
270     private Provider provider;
271 
272     // The algorithm associated with this factory
273     private final String algorithm;
274 
275     // The provider implementation (delegate)
276     private volatile SecretKeyFactorySpi spi;
277 
278     // lock for mutex during provider selection
279     private final Object lock = new Object();
280 
281     // remaining services to try in provider selection
282     // null once provider is selected
283     private Iterator<Service> serviceIterator;
284 
285     /**
286      * Creates a SecretKeyFactory object.
287      *
288      * @param keyFacSpi the delegate
289      * @param provider the provider
290      * @param algorithm the secret-key algorithm
291      */
SecretKeyFactory(SecretKeyFactorySpi keyFacSpi, Provider provider, String algorithm)292     protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi,
293                                Provider provider, String algorithm) {
294         this.spi = keyFacSpi;
295         this.provider = provider;
296         this.algorithm = algorithm;
297     }
298 
SecretKeyFactory(String algorithm)299     private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
300         this.algorithm = algorithm;
301         List<Service> list =
302                 GetInstance.getServices("SecretKeyFactory", algorithm);
303         serviceIterator = list.iterator();
304         // fetch and instantiate initial spi
305         if (nextSpi(null) == null) {
306             throw new NoSuchAlgorithmException
307                 (algorithm + " SecretKeyFactory not available");
308         }
309     }
310 
311     /**
312      * Returns a <code>SecretKeyFactory</code> object that converts
313      * secret keys of the specified algorithm.
314      *
315      * <p> This method traverses the list of registered security Providers,
316      * starting with the most preferred Provider.
317      * A new SecretKeyFactory object encapsulating the
318      * SecretKeyFactorySpi implementation from the first
319      * Provider that supports the specified algorithm is returned.
320      *
321      * <p> Note that the list of registered providers may be retrieved via
322      * the {@link Security#getProviders() Security.getProviders()} method.
323      *
324      * @param algorithm the standard name of the requested secret-key
325      * algorithm.
326      * See the SecretKeyFactory section in the <a href=
327      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
328      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
329      * for information about standard algorithm names.
330      *
331      * @return the new <code>SecretKeyFactory</code> object.
332      *
333      * @exception NullPointerException if the specified algorithm
334      *          is null.
335      *
336      * @exception NoSuchAlgorithmException if no Provider supports a
337      *          SecretKeyFactorySpi implementation for the
338      *          specified algorithm.
339      *
340      * @see java.security.Provider
341      */
getInstance(String algorithm)342     public static final SecretKeyFactory getInstance(String algorithm)
343             throws NoSuchAlgorithmException {
344         return new SecretKeyFactory(algorithm);
345     }
346 
347     /**
348      * Returns a <code>SecretKeyFactory</code> object that converts
349      * secret keys of the specified algorithm.
350      *
351      * <p> A new SecretKeyFactory object encapsulating the
352      * SecretKeyFactorySpi implementation from the specified provider
353      * is returned.  The specified provider must be registered
354      * in the security provider list.
355      *
356      * <p> Note that the list of registered providers may be retrieved via
357      * the {@link Security#getProviders() Security.getProviders()} method.
358      *
359      * @param algorithm the standard name of the requested secret-key
360      * algorithm.
361      * See the SecretKeyFactory section in the <a href=
362      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
363      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
364      * for information about standard algorithm names.
365      *
366      * @param provider the name of the provider.
367      *
368      * @return the new <code>SecretKeyFactory</code> object.
369      *
370      * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
371      *          implementation for the specified algorithm is not
372      *          available from the specified provider.
373      *
374      * @exception NullPointerException if the specified algorithm
375      *          is null.
376      *
377      * @throws NoSuchProviderException if the specified provider is not
378      *          registered in the security provider list.
379      *
380      * @exception IllegalArgumentException if the <code>provider</code>
381      *          is null or empty.
382      *
383      * @see java.security.Provider
384      */
getInstance(String algorithm, String provider)385     public static final SecretKeyFactory getInstance(String algorithm,
386             String provider) throws NoSuchAlgorithmException,
387             NoSuchProviderException {
388         Instance instance = JceSecurity.getInstance("SecretKeyFactory",
389                 SecretKeyFactorySpi.class, algorithm, provider);
390         return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
391                 instance.provider, algorithm);
392     }
393 
394     /**
395      * Returns a <code>SecretKeyFactory</code> object that converts
396      * secret keys of the specified algorithm.
397      *
398      * <p> A new SecretKeyFactory object encapsulating the
399      * SecretKeyFactorySpi implementation from the specified Provider
400      * object is returned.  Note that the specified Provider object
401      * does not have to be registered in the provider list.
402      *
403      * @param algorithm the standard name of the requested secret-key
404      * algorithm.
405      * See the SecretKeyFactory section in the <a href=
406      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
407      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
408      * for information about standard algorithm names.
409      *
410      * @param provider the provider.
411      *
412      * @return the new <code>SecretKeyFactory</code> object.
413      *
414      * @exception NullPointerException if the specified algorithm
415      * is null.
416      *
417      * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
418      *          implementation for the specified algorithm is not available
419      *          from the specified Provider object.
420      *
421      * @exception IllegalArgumentException if the <code>provider</code>
422      *          is null.
423      *
424      * @see java.security.Provider
425      */
getInstance(String algorithm, Provider provider)426     public static final SecretKeyFactory getInstance(String algorithm,
427             Provider provider) throws NoSuchAlgorithmException {
428         Instance instance = JceSecurity.getInstance("SecretKeyFactory",
429                 SecretKeyFactorySpi.class, algorithm, provider);
430         return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
431                 instance.provider, algorithm);
432     }
433 
434     /**
435      * Returns the provider of this <code>SecretKeyFactory</code> object.
436      *
437      * @return the provider of this <code>SecretKeyFactory</code> object
438      */
getProvider()439     public final Provider getProvider() {
440         synchronized (lock) {
441             // disable further failover after this call
442             serviceIterator = null;
443             return provider;
444         }
445     }
446 
447     /**
448      * Returns the algorithm name of this <code>SecretKeyFactory</code> object.
449      *
450      * <p>This is the same name that was specified in one of the
451      * <code>getInstance</code> calls that created this
452      * <code>SecretKeyFactory</code> object.
453      *
454      * @return the algorithm name of this <code>SecretKeyFactory</code>
455      * object.
456      */
getAlgorithm()457     public final String getAlgorithm() {
458         return this.algorithm;
459     }
460 
461     /**
462      * Update the active spi of this class and return the next
463      * implementation for failover. If no more implemenations are
464      * available, this method returns null. However, the active spi of
465      * this class is never set to null.
466      */
nextSpi(SecretKeyFactorySpi oldSpi)467     private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) {
468         synchronized (lock) {
469             // somebody else did a failover concurrently
470             // try that spi now
471             if ((oldSpi != null) && (oldSpi != spi)) {
472                 return spi;
473             }
474             if (serviceIterator == null) {
475                 return null;
476             }
477             while (serviceIterator.hasNext()) {
478                 Service s = serviceIterator.next();
479                 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
480                     continue;
481                 }
482                 try {
483                     Object obj = s.newInstance(null);
484                     if (obj instanceof SecretKeyFactorySpi == false) {
485                         continue;
486                     }
487                     SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj;
488                     provider = s.getProvider();
489                     this.spi = spi;
490                     return spi;
491                 } catch (NoSuchAlgorithmException e) {
492                     // ignore
493                 }
494             }
495             serviceIterator = null;
496             return null;
497         }
498     }
499 
500     /**
501      * Generates a <code>SecretKey</code> object from the provided key
502      * specification (key material).
503      *
504      * @param keySpec the specification (key material) of the secret key
505      *
506      * @return the secret key
507      *
508      * @exception InvalidKeySpecException if the given key specification
509      * is inappropriate for this secret-key factory to produce a secret key.
510      */
generateSecret(KeySpec keySpec)511     public final SecretKey generateSecret(KeySpec keySpec)
512             throws InvalidKeySpecException {
513         if (serviceIterator == null) {
514             return spi.engineGenerateSecret(keySpec);
515         }
516         Exception failure = null;
517         SecretKeyFactorySpi mySpi = spi;
518         do {
519             try {
520                 return mySpi.engineGenerateSecret(keySpec);
521             } catch (Exception e) {
522                 if (failure == null) {
523                     failure = e;
524                 }
525                 mySpi = nextSpi(mySpi);
526             }
527         } while (mySpi != null);
528         if (failure instanceof InvalidKeySpecException) {
529             throw (InvalidKeySpecException)failure;
530         }
531         throw new InvalidKeySpecException
532                 ("Could not generate secret key", failure);
533     }
534 
535     /**
536      * Returns a specification (key material) of the given key object
537      * in the requested format.
538      *
539      * @param key the key
540      * @param keySpec the requested format in which the key material shall be
541      * returned
542      *
543      * @return the underlying key specification (key material) in the
544      * requested format
545      *
546      * @exception InvalidKeySpecException if the requested key specification is
547      * inappropriate for the given key (e.g., the algorithms associated with
548      * <code>key</code> and <code>keySpec</code> do not match, or
549      * <code>key</code> references a key on a cryptographic hardware device
550      * whereas <code>keySpec</code> is the specification of a software-based
551      * key), or the given key cannot be dealt with
552      * (e.g., the given key has an algorithm or format not supported by this
553      * secret-key factory).
554      */
getKeySpec(SecretKey key, Class<?> keySpec)555     public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)
556             throws InvalidKeySpecException {
557         if (serviceIterator == null) {
558             return spi.engineGetKeySpec(key, keySpec);
559         }
560         Exception failure = null;
561         SecretKeyFactorySpi mySpi = spi;
562         do {
563             try {
564                 return mySpi.engineGetKeySpec(key, keySpec);
565             } catch (Exception e) {
566                 if (failure == null) {
567                     failure = e;
568                 }
569                 mySpi = nextSpi(mySpi);
570             }
571         } while (mySpi != null);
572         if (failure instanceof InvalidKeySpecException) {
573             throw (InvalidKeySpecException)failure;
574         }
575         throw new InvalidKeySpecException
576                 ("Could not get key spec", failure);
577     }
578 
579     /**
580      * Translates a key object, whose provider may be unknown or potentially
581      * untrusted, into a corresponding key object of this secret-key factory.
582      *
583      * @param key the key whose provider is unknown or untrusted
584      *
585      * @return the translated key
586      *
587      * @exception InvalidKeyException if the given key cannot be processed
588      * by this secret-key factory.
589      */
translateKey(SecretKey key)590     public final SecretKey translateKey(SecretKey key)
591             throws InvalidKeyException {
592         if (serviceIterator == null) {
593             return spi.engineTranslateKey(key);
594         }
595         Exception failure = null;
596         SecretKeyFactorySpi mySpi = spi;
597         do {
598             try {
599                 return mySpi.engineTranslateKey(key);
600             } catch (Exception e) {
601                 if (failure == null) {
602                     failure = e;
603                 }
604                 mySpi = nextSpi(mySpi);
605             }
606         } while (mySpi != null);
607         if (failure instanceof InvalidKeyException) {
608             throw (InvalidKeyException)failure;
609         }
610         throw new InvalidKeyException
611                 ("Could not translate key", failure);
612     }
613 }
614