• 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  *     <tr>
103  *       <td>XDH</td>
104  *       <td>33+</td>
105  *     </tr>
106  *   </tbody>
107  * </table>
108  *
109  * @author Jan Luehe
110  *
111  * @see Key
112  * @see PublicKey
113  * @see PrivateKey
114  * @see java.security.spec.KeySpec
115  * @see java.security.spec.DSAPublicKeySpec
116  * @see java.security.spec.X509EncodedKeySpec
117  *
118  * @since 1.2
119  */
120 
121 public class KeyFactory {
122 
123     private static final Debug debug =
124                         Debug.getInstance("jca", "KeyFactory");
125 
126     // The algorithm associated with this key factory
127     private final String algorithm;
128 
129     // The provider
130     private Provider provider;
131 
132     // The provider implementation (delegate)
133     private volatile KeyFactorySpi spi;
134 
135     // lock for mutex during provider selection
136     private final Object lock = new Object();
137 
138     // remaining services to try in provider selection
139     // null once provider is selected
140     private Iterator<Service> serviceIterator;
141 
142     /**
143      * Creates a KeyFactory object.
144      *
145      * @param keyFacSpi the delegate
146      * @param provider the provider
147      * @param algorithm the name of the algorithm
148      * to associate with this {@code KeyFactory}
149      */
KeyFactory(KeyFactorySpi keyFacSpi, Provider provider, String algorithm)150     protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider,
151                          String algorithm) {
152         this.spi = keyFacSpi;
153         this.provider = provider;
154         this.algorithm = algorithm;
155     }
156 
KeyFactory(String algorithm)157     private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
158         this.algorithm = algorithm;
159         List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
160         serviceIterator = list.iterator();
161         // fetch and instantiate initial spi
162         if (nextSpi(null) == null) {
163             throw new NoSuchAlgorithmException
164                 (algorithm + " KeyFactory not available");
165         }
166     }
167 
168     /**
169      * Returns a KeyFactory object that converts
170      * public/private keys of the specified algorithm.
171      *
172      * <p> This method traverses the list of registered security Providers,
173      * starting with the most preferred Provider.
174      * A new KeyFactory object encapsulating the
175      * KeyFactorySpi 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 name of the requested key algorithm.
182      *
183      * @return the new {@code KeyFactory} object
184      *
185      * @throws NoSuchAlgorithmException if no {@code Provider} supports a
186      *         {@code KeyFactorySpi} implementation for the
187      *         specified algorithm
188      *
189      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
190      *
191      * @see Provider
192      */
getInstance(String algorithm)193     public static KeyFactory getInstance(String algorithm)
194             throws NoSuchAlgorithmException {
195         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
196         // Objects.requireNonNull(algorithm, "null algorithm name");
197         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
198             Objects.requireNonNull(algorithm, "null algorithm name");
199         }
200         return new KeyFactory(algorithm);
201     }
202 
203     /**
204      * Returns a KeyFactory object that converts
205      * public/private keys of the specified algorithm.
206      *
207      * <p> A new KeyFactory object encapsulating the
208      * KeyFactorySpi implementation from the specified provider
209      * is returned.  The specified provider must be registered
210      * in the security provider list.
211      *
212      * <p> Note that the list of registered providers may be retrieved via
213      * the {@link Security#getProviders() Security.getProviders()} method.
214      *
215      * @param algorithm the name of the requested key algorithm.
216      *
217      * @param provider the name of the provider.
218      *
219      * @return the new {@code KeyFactory} object
220      *
221      * @throws IllegalArgumentException if the provider name is {@code null}
222      *         or empty
223      *
224      * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
225      *         implementation for the specified algorithm is not
226      *         available from the specified provider
227      *
228      * @throws NoSuchProviderException if the specified provider is not
229      *         registered in the security provider list
230      *
231      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
232      *
233      * @see Provider
234      */
getInstance(String algorithm, String provider)235     public static KeyFactory getInstance(String algorithm, String provider)
236             throws NoSuchAlgorithmException, NoSuchProviderException {
237         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
238         // Objects.requireNonNull(algorithm, "null algorithm name");
239         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
240             Objects.requireNonNull(algorithm, "null algorithm name");
241         }
242         // Android-added: Check for Bouncy Castle deprecation
243         Providers.checkBouncyCastleDeprecation(provider, "KeyFactory", algorithm);
244         Instance instance = GetInstance.getInstance("KeyFactory",
245             KeyFactorySpi.class, algorithm, provider);
246         return new KeyFactory((KeyFactorySpi)instance.impl,
247             instance.provider, algorithm);
248     }
249 
250     /**
251      * Returns a KeyFactory object that converts
252      * public/private keys of the specified algorithm.
253      *
254      * <p> A new KeyFactory object encapsulating the
255      * KeyFactorySpi implementation from the specified Provider
256      * object is returned.  Note that the specified Provider object
257      * does not have to be registered in the provider list.
258      *
259      * @param algorithm the name of the requested key algorithm.
260      *
261      * @param provider the provider.
262      *
263      * @return the new {@code KeyFactory} object
264      *
265      * @throws IllegalArgumentException if the specified provider is
266      *         {@code null}
267      *
268      * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
269      *         implementation for the specified algorithm is not available
270      *         from the specified {@code Provider} object
271      *
272      * @throws NullPointerException if {@code algorithm} is {@code null} on Android 14 or above
273      *
274      * @see Provider
275      *
276      * @since 1.4
277      */
getInstance(String algorithm, Provider provider)278     public static KeyFactory getInstance(String algorithm, Provider provider)
279             throws NoSuchAlgorithmException {
280         // Android-changed: To be compat with the older Android, don't throw NPE on Android 13-.
281         // Objects.requireNonNull(algorithm, "null algorithm name");
282         if (VMRuntime.getSdkVersion() >= VersionCodes.UPSIDE_DOWN_CAKE) {
283             Objects.requireNonNull(algorithm, "null algorithm name");
284         }
285         // Android-added: Check for Bouncy Castle deprecation
286         Providers.checkBouncyCastleDeprecation(provider, "KeyFactory", algorithm);
287         Instance instance = GetInstance.getInstance("KeyFactory",
288             KeyFactorySpi.class, algorithm, provider);
289         return new KeyFactory((KeyFactorySpi)instance.impl,
290             instance.provider, algorithm);
291     }
292 
293     /**
294      * Returns the provider of this key factory object.
295      *
296      * @return the provider of this key factory object
297      */
getProvider()298     public final Provider getProvider() {
299         synchronized (lock) {
300             // disable further failover after this call
301             serviceIterator = null;
302             return provider;
303         }
304     }
305 
306     /**
307      * Gets the name of the algorithm
308      * associated with this {@code KeyFactory}.
309      *
310      * @return the name of the algorithm associated with this
311      * {@code KeyFactory}
312      */
getAlgorithm()313     public final String getAlgorithm() {
314         return this.algorithm;
315     }
316 
317     /**
318      * Update the active KeyFactorySpi of this class and return the next
319      * implementation for failover. If no more implemenations are
320      * available, this method returns null. However, the active spi of
321      * this class is never set to null.
322      */
nextSpi(KeyFactorySpi oldSpi)323     private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) {
324         synchronized (lock) {
325             // somebody else did a failover concurrently
326             // try that spi now
327             if ((oldSpi != null) && (oldSpi != spi)) {
328                 return spi;
329             }
330             if (serviceIterator == null) {
331                 return null;
332             }
333             while (serviceIterator.hasNext()) {
334                 Service s = serviceIterator.next();
335                 try {
336                     Object obj = s.newInstance(null);
337                     if (obj instanceof KeyFactorySpi == false) {
338                         continue;
339                     }
340                     KeyFactorySpi spi = (KeyFactorySpi)obj;
341                     provider = s.getProvider();
342                     this.spi = spi;
343                     return spi;
344                 } catch (NoSuchAlgorithmException e) {
345                     // ignore
346                 }
347             }
348             serviceIterator = null;
349             return null;
350         }
351     }
352 
353     /**
354      * Generates a public key object from the provided key specification
355      * (key material).
356      *
357      * @param keySpec the specification (key material) of the public key.
358      *
359      * @return the public key.
360      *
361      * @exception InvalidKeySpecException if the given key specification
362      * is inappropriate for this key factory to produce a public key.
363      */
generatePublic(KeySpec keySpec)364     public final PublicKey generatePublic(KeySpec keySpec)
365             throws InvalidKeySpecException {
366         if (serviceIterator == null) {
367             return spi.engineGeneratePublic(keySpec);
368         }
369         Exception failure = null;
370         KeyFactorySpi mySpi = spi;
371         do {
372             try {
373                 return mySpi.engineGeneratePublic(keySpec);
374             } catch (Exception e) {
375                 if (failure == null) {
376                     failure = e;
377                 }
378                 mySpi = nextSpi(mySpi);
379             }
380         } while (mySpi != null);
381         if (failure instanceof RuntimeException) {
382             throw (RuntimeException)failure;
383         }
384         if (failure instanceof InvalidKeySpecException) {
385             throw (InvalidKeySpecException)failure;
386         }
387         throw new InvalidKeySpecException
388                 ("Could not generate public key", failure);
389     }
390 
391     /**
392      * Generates a private key object from the provided key specification
393      * (key material).
394      *
395      * @param keySpec the specification (key material) of the private key.
396      *
397      * @return the private key.
398      *
399      * @exception InvalidKeySpecException if the given key specification
400      * is inappropriate for this key factory to produce a private key.
401      */
generatePrivate(KeySpec keySpec)402     public final PrivateKey generatePrivate(KeySpec keySpec)
403             throws InvalidKeySpecException {
404         if (serviceIterator == null) {
405             return spi.engineGeneratePrivate(keySpec);
406         }
407         Exception failure = null;
408         KeyFactorySpi mySpi = spi;
409         do {
410             try {
411                 return mySpi.engineGeneratePrivate(keySpec);
412             } catch (Exception e) {
413                 if (failure == null) {
414                     failure = e;
415                 }
416                 mySpi = nextSpi(mySpi);
417             }
418         } while (mySpi != null);
419         if (failure instanceof RuntimeException) {
420             throw (RuntimeException)failure;
421         }
422         if (failure instanceof InvalidKeySpecException) {
423             throw (InvalidKeySpecException)failure;
424         }
425         throw new InvalidKeySpecException
426                 ("Could not generate private key", failure);
427     }
428 
429     /**
430      * Returns a specification (key material) of the given key object.
431      * {@code keySpec} identifies the specification class in which
432      * the key material should be returned. It could, for example, be
433      * {@code DSAPublicKeySpec.class}, to indicate that the
434      * key material should be returned in an instance of the
435      * {@code DSAPublicKeySpec} class.
436      *
437      * @param <T> the type of the key specification to be returned
438      *
439      * @param key the key.
440      *
441      * @param keySpec the specification class in which
442      * the key material should be returned.
443      *
444      * @return the underlying key specification (key material) in an instance
445      * of the requested specification class.
446      *
447      * @exception InvalidKeySpecException if the requested key specification is
448      * inappropriate for the given key, or the given key cannot be processed
449      * (e.g., the given key has an unrecognized algorithm or format).
450      */
getKeySpec(Key key, Class<T> keySpec)451     public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
452             throws InvalidKeySpecException {
453         if (serviceIterator == null) {
454             return spi.engineGetKeySpec(key, keySpec);
455         }
456         Exception failure = null;
457         KeyFactorySpi mySpi = spi;
458         do {
459             try {
460                 return mySpi.engineGetKeySpec(key, keySpec);
461             } catch (Exception e) {
462                 if (failure == null) {
463                     failure = e;
464                 }
465                 mySpi = nextSpi(mySpi);
466             }
467         } while (mySpi != null);
468         if (failure instanceof RuntimeException) {
469             throw (RuntimeException)failure;
470         }
471         if (failure instanceof InvalidKeySpecException) {
472             throw (InvalidKeySpecException)failure;
473         }
474         throw new InvalidKeySpecException
475                 ("Could not get key spec", failure);
476     }
477 
478     /**
479      * Translates a key object, whose provider may be unknown or potentially
480      * untrusted, into a corresponding key object of this key factory.
481      *
482      * @param key the key whose provider is unknown or untrusted.
483      *
484      * @return the translated key.
485      *
486      * @exception InvalidKeyException if the given key cannot be processed
487      * by this key factory.
488      */
translateKey(Key key)489     public final Key translateKey(Key key) throws InvalidKeyException {
490         if (serviceIterator == null) {
491             return spi.engineTranslateKey(key);
492         }
493         Exception failure = null;
494         KeyFactorySpi mySpi = spi;
495         do {
496             try {
497                 return mySpi.engineTranslateKey(key);
498             } catch (Exception e) {
499                 if (failure == null) {
500                     failure = e;
501                 }
502                 mySpi = nextSpi(mySpi);
503             }
504         } while (mySpi != null);
505         if (failure instanceof RuntimeException) {
506             throw (RuntimeException)failure;
507         }
508         if (failure instanceof InvalidKeyException) {
509             throw (InvalidKeyException)failure;
510         }
511         throw new InvalidKeyException
512                 ("Could not translate key", failure);
513     }
514 
515 }
516