• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.security;
27 
28 import dalvik.annotation.compat.VersionCodes;
29 import dalvik.system.VMRuntime;
30 
31 import java.util.*;
32 import java.security.Provider.Service;
33 import java.security.spec.KeySpec;
34 import java.security.spec.InvalidKeySpecException;
35 import java.security.spec.RSAPrivateKeySpec;
36 
37 import sun.security.util.Debug;
38 import sun.security.jca.*;
39 import sun.security.jca.GetInstance.Instance;
40 
41 /**
42  * Key factories are used to convert <I>keys</I> (opaque
43  * cryptographic keys of type {@code Key}) into <I>key specifications</I>
44  * (transparent representations of the underlying key material), and vice
45  * versa.
46  *
47  * <P> Key factories are bi-directional. That is, they allow you to build an
48  * opaque key object from a given key specification (key material), or to
49  * retrieve the underlying key material of a key object in a suitable format.
50  *
51  * <P> Multiple compatible key specifications may exist for the same key.
52  * For example, a DSA public key may be specified using
53  * {@code DSAPublicKeySpec} or
54  * {@code X509EncodedKeySpec}. A key factory can be used to translate
55  * between compatible key specifications.
56  *
57  * <P> The following is an example of how to use a key factory in order to
58  * instantiate a DSA public key from its encoding.
59  * Assume Alice has received a digital signature from Bob.
60  * Bob also sent her his public key (in encoded format) to verify
61  * his signature. Alice then performs the following actions:
62  *
63  * <pre>
64  * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
65  * KeyFactory keyFactory = KeyFactory.getInstance("DSA");
66  * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
67  * Signature sig = Signature.getInstance("DSA");
68  * sig.initVerify(bobPubKey);
69  * sig.update(data);
70  * sig.verify(signature);
71  * </pre>
72  *
73  * <p> Android provides the following <code>KeyFactory</code> algorithms:
74  * <table>
75  *   <thead>
76  *     <tr>
77  *       <th>Algorithm</th>
78  *       <th>Supported API Levels</th>
79  *     </tr>
80  *   </thead>
81  *   <tbody>
82  *     <tr>
83  *       <td>DH</td>
84  *       <td>1+</td>
85  *     </tr>
86  *     <tr>
87  *       <td>DSA</td>
88  *       <td>1+</td>
89  *     </tr>
90  *     <tr>
91  *       <td>EC</td>
92  *       <td>11+</td>
93  *     </tr>
94  *     <tr>
95  *       <td>RSA</td>
96  *       <td>1+</td>
97  *     </tr>
98  *     <tr class="deprecated">
99  *       <td>X.509</td>
100  *       <td>1-8</td>
101  *     </tr>
102  *   </tbody>
103  * </table>
104  *
105  * @author Jan Luehe
106  *
107  * @see Key
108  * @see PublicKey
109  * @see PrivateKey
110  * @see java.security.spec.KeySpec
111  * @see java.security.spec.DSAPublicKeySpec
112  * @see java.security.spec.X509EncodedKeySpec
113  *
114  * @since 1.2
115  */
116 
117 public class KeyFactory {
118 
119     private static final Debug debug =
120                         Debug.getInstance("jca", "KeyFactory");
121 
122     // The algorithm associated with this key factory
123     private final String algorithm;
124 
125     // The provider
126     private Provider provider;
127 
128     // The provider implementation (delegate)
129     private volatile KeyFactorySpi spi;
130 
131     // lock for mutex during provider selection
132     private final Object lock = new Object();
133 
134     // remaining services to try in provider selection
135     // null once provider is selected
136     private Iterator<Service> serviceIterator;
137 
138     /**
139      * Creates a KeyFactory object.
140      *
141      * @param keyFacSpi the delegate
142      * @param provider the provider
143      * @param algorithm the name of the algorithm
144      * to associate with this {@code KeyFactory}
145      */
KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, String algorithm)146     protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider,
147                          String algorithm) {
148         this.spi = keyFacSpi;
149         this.provider = provider;
150         this.algorithm = algorithm;
151     }
152 
KeyFactory(String algorithm)153     private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
154         this.algorithm = algorithm;
155         List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
156         serviceIterator = list.iterator();
157         // fetch and instantiate initial spi
158         if (nextSpi(null) == null) {
159             throw new NoSuchAlgorithmException
160                 (algorithm + " KeyFactory not available");
161         }
162     }
163 
164     /**
165      * Returns a KeyFactory object that converts
166      * public/private keys of the specified algorithm.
167      *
168      * <p> This method traverses the list of registered security Providers,
169      * starting with the most preferred Provider.
170      * A new KeyFactory object encapsulating the
171      * KeyFactorySpi 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 name of the requested key algorithm.
178      *
179      * @return the new {@code KeyFactory} object
180      *
181      * @throws NoSuchAlgorithmException if no {@code Provider} supports a
182      *         {@code KeyFactorySpi} implementation for the
183      *         specified algorithm
184      *
185      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
186      *
187      * @see Provider
188      */
getInstance(String algorithm)189     public static KeyFactory getInstance(String algorithm)
190             throws NoSuchAlgorithmException {
191         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
192         // Objects.requireNonNull(algorithm, "null algorithm name");
193         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
194             Objects.requireNonNull(algorithm, "null algorithm name");
195         }
196         return new KeyFactory(algorithm);
197     }
198 
199     /**
200      * Returns a KeyFactory object that converts
201      * public/private keys of the specified algorithm.
202      *
203      * <p> A new KeyFactory object encapsulating the
204      * KeyFactorySpi implementation from the specified provider
205      * is returned.  The specified provider must be registered
206      * in the security provider list.
207      *
208      * <p> Note that the list of registered providers may be retrieved via
209      * the {@link Security#getProviders() Security.getProviders()} method.
210      *
211      * @param algorithm the name of the requested key algorithm.
212      *
213      * @param provider the name of the provider.
214      *
215      * @return the new {@code KeyFactory} object
216      *
217      * @throws IllegalArgumentException if the provider name is {@code null}
218      *         or empty
219      *
220      * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
221      *         implementation for the specified algorithm is not
222      *         available from the specified provider
223      *
224      * @throws NoSuchProviderException if the specified provider is not
225      *         registered in the security provider list
226      *
227      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
228      *
229      * @see Provider
230      */
getInstance(String algorithm, String provider)231     public static KeyFactory getInstance(String algorithm, String provider)
232             throws NoSuchAlgorithmException, NoSuchProviderException {
233         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
234         // Objects.requireNonNull(algorithm, "null algorithm name");
235         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
236             Objects.requireNonNull(algorithm, "null algorithm name");
237         }
238         // Android-added: Check for Bouncy Castle deprecation
239         Providers.checkBouncyCastleDeprecation(provider, "KeyFactory", algorithm);
240         Instance instance = GetInstance.getInstance("KeyFactory",
241             KeyFactorySpi.class, algorithm, provider);
242         return new KeyFactory((KeyFactorySpi)instance.impl,
243             instance.provider, algorithm);
244     }
245 
246     /**
247      * Returns a KeyFactory object that converts
248      * public/private keys of the specified algorithm.
249      *
250      * <p> A new KeyFactory object encapsulating the
251      * KeyFactorySpi implementation from the specified Provider
252      * object is returned.  Note that the specified Provider object
253      * does not have to be registered in the provider list.
254      *
255      * @param algorithm the name of the requested key algorithm.
256      *
257      * @param provider the provider.
258      *
259      * @return the new {@code KeyFactory} object
260      *
261      * @throws IllegalArgumentException if the specified provider is
262      *         {@code null}
263      *
264      * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
265      *         implementation for the specified algorithm is not available
266      *         from the specified {@code Provider} object
267      *
268      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
269      *
270      * @see Provider
271      *
272      * @since 1.4
273      */
getInstance(String algorithm, Provider provider)274     public static KeyFactory getInstance(String algorithm, Provider provider)
275             throws NoSuchAlgorithmException {
276         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
277         // Objects.requireNonNull(algorithm, "null algorithm name");
278         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
279             Objects.requireNonNull(algorithm, "null algorithm name");
280         }
281         // Android-added: Check for Bouncy Castle deprecation
282         Providers.checkBouncyCastleDeprecation(provider, "KeyFactory", algorithm);
283         Instance instance = GetInstance.getInstance("KeyFactory",
284             KeyFactorySpi.class, algorithm, provider);
285         return new KeyFactory((KeyFactorySpi)instance.impl,
286             instance.provider, algorithm);
287     }
288 
289     /**
290      * Returns the provider of this key factory object.
291      *
292      * @return the provider of this key factory object
293      */
getProvider()294     public final Provider getProvider() {
295         synchronized (lock) {
296             // disable further failover after this call
297             serviceIterator = null;
298             return provider;
299         }
300     }
301 
302     /**
303      * Gets the name of the algorithm
304      * associated with this {@code KeyFactory}.
305      *
306      * @return the name of the algorithm associated with this
307      * {@code KeyFactory}
308      */
getAlgorithm()309     public final String getAlgorithm() {
310         return this.algorithm;
311     }
312 
313     /**
314      * Update the active KeyFactorySpi of this class and return the next
315      * implementation for failover. If no more implemenations are
316      * available, this method returns null. However, the active spi of
317      * this class is never set to null.
318      */
nextSpi(KeyFactorySpi oldSpi)319     private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) {
320         synchronized (lock) {
321             // somebody else did a failover concurrently
322             // try that spi now
323             if ((oldSpi != null) && (oldSpi != spi)) {
324                 return spi;
325             }
326             if (serviceIterator == null) {
327                 return null;
328             }
329             while (serviceIterator.hasNext()) {
330                 Service s = serviceIterator.next();
331                 try {
332                     Object obj = s.newInstance(null);
333                     if (obj instanceof KeyFactorySpi == false) {
334                         continue;
335                     }
336                     KeyFactorySpi spi = (KeyFactorySpi)obj;
337                     provider = s.getProvider();
338                     this.spi = spi;
339                     return spi;
340                 } catch (NoSuchAlgorithmException e) {
341                     // ignore
342                 }
343             }
344             serviceIterator = null;
345             return null;
346         }
347     }
348 
349     /**
350      * Generates a public key object from the provided key specification
351      * (key material).
352      *
353      * @param keySpec the specification (key material) of the public key.
354      *
355      * @return the public key.
356      *
357      * @exception InvalidKeySpecException if the given key specification
358      * is inappropriate for this key factory to produce a public key.
359      */
generatePublic(KeySpec keySpec)360     public final PublicKey generatePublic(KeySpec keySpec)
361             throws InvalidKeySpecException {
362         if (serviceIterator == null) {
363             return spi.engineGeneratePublic(keySpec);
364         }
365         Exception failure = null;
366         KeyFactorySpi mySpi = spi;
367         do {
368             try {
369                 return mySpi.engineGeneratePublic(keySpec);
370             } catch (Exception e) {
371                 if (failure == null) {
372                     failure = e;
373                 }
374                 mySpi = nextSpi(mySpi);
375             }
376         } while (mySpi != null);
377         if (failure instanceof RuntimeException) {
378             throw (RuntimeException)failure;
379         }
380         if (failure instanceof InvalidKeySpecException) {
381             throw (InvalidKeySpecException)failure;
382         }
383         throw new InvalidKeySpecException
384                 ("Could not generate public key", failure);
385     }
386 
387     /**
388      * Generates a private key object from the provided key specification
389      * (key material).
390      *
391      * @param keySpec the specification (key material) of the private key.
392      *
393      * @return the private key.
394      *
395      * @exception InvalidKeySpecException if the given key specification
396      * is inappropriate for this key factory to produce a private key.
397      */
generatePrivate(KeySpec keySpec)398     public final PrivateKey generatePrivate(KeySpec keySpec)
399             throws InvalidKeySpecException {
400         if (serviceIterator == null) {
401             return spi.engineGeneratePrivate(keySpec);
402         }
403         Exception failure = null;
404         KeyFactorySpi mySpi = spi;
405         do {
406             try {
407                 return mySpi.engineGeneratePrivate(keySpec);
408             } catch (Exception e) {
409                 if (failure == null) {
410                     failure = e;
411                 }
412                 mySpi = nextSpi(mySpi);
413             }
414         } while (mySpi != null);
415         if (failure instanceof RuntimeException) {
416             throw (RuntimeException)failure;
417         }
418         if (failure instanceof InvalidKeySpecException) {
419             throw (InvalidKeySpecException)failure;
420         }
421         throw new InvalidKeySpecException
422                 ("Could not generate private key", failure);
423     }
424 
425     /**
426      * Returns a specification (key material) of the given key object.
427      * {@code keySpec} identifies the specification class in which
428      * the key material should be returned. It could, for example, be
429      * {@code DSAPublicKeySpec.class}, to indicate that the
430      * key material should be returned in an instance of the
431      * {@code DSAPublicKeySpec} class.
432      *
433      * @param <T> the type of the key specification to be returned
434      *
435      * @param key the key.
436      *
437      * @param keySpec the specification class in which
438      * the key material should be returned.
439      *
440      * @return the underlying key specification (key material) in an instance
441      * of the requested specification class.
442      *
443      * @exception InvalidKeySpecException if the requested key specification is
444      * inappropriate for the given key, or the given key cannot be processed
445      * (e.g., the given key has an unrecognized algorithm or format).
446      */
getKeySpec(Key key, Class<T> keySpec)447     public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
448             throws InvalidKeySpecException {
449         if (serviceIterator == null) {
450             return spi.engineGetKeySpec(key, keySpec);
451         }
452         Exception failure = null;
453         KeyFactorySpi mySpi = spi;
454         do {
455             try {
456                 return mySpi.engineGetKeySpec(key, keySpec);
457             } catch (Exception e) {
458                 if (failure == null) {
459                     failure = e;
460                 }
461                 mySpi = nextSpi(mySpi);
462             }
463         } while (mySpi != null);
464         if (failure instanceof RuntimeException) {
465             throw (RuntimeException)failure;
466         }
467         if (failure instanceof InvalidKeySpecException) {
468             throw (InvalidKeySpecException)failure;
469         }
470         throw new InvalidKeySpecException
471                 ("Could not get key spec", failure);
472     }
473 
474     /**
475      * Translates a key object, whose provider may be unknown or potentially
476      * untrusted, into a corresponding key object of this key factory.
477      *
478      * @param key the key whose provider is unknown or untrusted.
479      *
480      * @return the translated key.
481      *
482      * @exception InvalidKeyException if the given key cannot be processed
483      * by this key factory.
484      */
translateKey(Key key)485     public final Key translateKey(Key key) throws InvalidKeyException {
486         if (serviceIterator == null) {
487             return spi.engineTranslateKey(key);
488         }
489         Exception failure = null;
490         KeyFactorySpi mySpi = spi;
491         do {
492             try {
493                 return mySpi.engineTranslateKey(key);
494             } catch (Exception e) {
495                 if (failure == null) {
496                     failure = e;
497                 }
498                 mySpi = nextSpi(mySpi);
499             }
500         } while (mySpi != null);
501         if (failure instanceof RuntimeException) {
502             throw (RuntimeException)failure;
503         }
504         if (failure instanceof InvalidKeyException) {
505             throw (InvalidKeyException)failure;
506         }
507         throw new InvalidKeyException
508                 ("Could not translate key", failure);
509     }
510 
511 }
512