1/*
2 * Copyright (c) 1999, 2012, 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
26package javax.net.ssl;
27
28import java.security.Security;
29import java.security.*;
30
31import sun.security.jca.GetInstance;
32
33/**
34 * This class acts as a factory for key managers based on a
35 * source of key material. Each key manager manages a specific
36 * type of key material for use by secure sockets. The key
37 * material is based on a KeyStore and/or provider specific sources.
38 *
39 * <p> Android provides the following <code>KeyManagerFactory</code> algorithms:
40 * <table>
41 *   <thead>
42 *     <tr>
43 *       <th>Algorithm</th>
44 *       <th>Supported API Levels</th>
45 *     </tr>
46 *   </thead>
47 *   <tbody>
48 *     <tr>
49 *       <td>PKIX</td>
50 *       <td>1+</td>
51 *     </tr>
52 *   </tbody>
53 * </table>
54 *
55 * @since 1.4
56 * @see KeyManager
57 */
58public class KeyManagerFactory {
59    // The provider
60    private Provider provider;
61
62    // The provider implementation (delegate)
63    private KeyManagerFactorySpi factorySpi;
64
65    // The name of the key management algorithm.
66    private String algorithm;
67
68    /**
69     * Obtains the default KeyManagerFactory algorithm name.
70     *
71     * <p>The default algorithm can be changed at runtime by setting
72     * the value of the {@code ssl.KeyManagerFactory.algorithm}
73     * security property to the desired algorithm name.
74     *
75     * @see java.security.Security security properties
76     * @return the default algorithm name as specified by the
77     *          {@code ssl.KeyManagerFactory.algorithm} security property, or an
78     *          implementation-specific default if no such property exists.
79     */
80    public final static String getDefaultAlgorithm() {
81        String type;
82        type = AccessController.doPrivileged(new PrivilegedAction<String>() {
83            @Override
84            public String run() {
85                return Security.getProperty(
86                    "ssl.KeyManagerFactory.algorithm");
87            }
88        });
89        if (type == null) {
90            type = "SunX509";
91        }
92        return type;
93    }
94
95    /**
96     * Creates a KeyManagerFactory object.
97     *
98     * @param factorySpi the delegate
99     * @param provider the provider
100     * @param algorithm the algorithm
101     */
102    protected KeyManagerFactory(KeyManagerFactorySpi factorySpi,
103                                Provider provider, String algorithm) {
104        this.factorySpi = factorySpi;
105        this.provider = provider;
106        this.algorithm = algorithm;
107    }
108
109    /**
110     * Returns the algorithm name of this <code>KeyManagerFactory</code> object.
111     *
112     * <p>This is the same name that was specified in one of the
113     * <code>getInstance</code> calls that created this
114     * <code>KeyManagerFactory</code> object.
115     *
116     * @return the algorithm name of this <code>KeyManagerFactory</code> object.
117     */
118    public final String getAlgorithm() {
119        return this.algorithm;
120    }
121
122    /**
123     * Returns a <code>KeyManagerFactory</code> object that acts as a
124     * factory for key managers.
125     *
126     * <p> This method traverses the list of registered security Providers,
127     * starting with the most preferred Provider.
128     * A new KeyManagerFactory object encapsulating the
129     * KeyManagerFactorySpi implementation from the first
130     * Provider that supports the specified algorithm is returned.
131     *
132     * <p> Note that the list of registered providers may be retrieved via
133     * the {@link Security#getProviders() Security.getProviders()} method.
134     *
135     * @param algorithm the standard name of the requested algorithm.
136     *          See the <a href=
137     *  "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/jsse/JSSERefGuide.html">
138     *          Java Secure Socket Extension Reference Guide </a>
139     *          for information about standard algorithm names.
140     *
141     * @return the new <code>KeyManagerFactory</code> object.
142     *
143     * @exception NoSuchAlgorithmException if no Provider supports a
144     *          KeyManagerFactorySpi implementation for the
145     *          specified algorithm.
146     * @exception NullPointerException if <code>algorithm</code> is null.
147     *
148     * @see java.security.Provider
149     */
150    public static final KeyManagerFactory getInstance(String algorithm)
151            throws NoSuchAlgorithmException {
152        GetInstance.Instance instance = GetInstance.getInstance
153                ("KeyManagerFactory", KeyManagerFactorySpi.class,
154                algorithm);
155        return new KeyManagerFactory((KeyManagerFactorySpi)instance.impl,
156                instance.provider, algorithm);
157    }
158
159    /**
160     * Returns a <code>KeyManagerFactory</code> object that acts as a
161     * factory for key managers.
162     *
163     * <p> A new KeyManagerFactory object encapsulating the
164     * KeyManagerFactorySpi implementation from the specified provider
165     * is returned.  The specified provider must be registered
166     * in the security provider list.
167     *
168     * <p> Note that the list of registered providers may be retrieved via
169     * the {@link Security#getProviders() Security.getProviders()} method.
170
171     * @param algorithm the standard name of the requested algorithm.
172     *          See the <a href=
173     *  "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/jsse/JSSERefGuide.html">
174     *          Java Secure Socket Extension Reference Guide </a>
175     *          for information about standard algorithm names.
176     *
177     * @param provider the name of the provider.
178     *
179     * @return the new <code>KeyManagerFactory</code> object.
180     *
181     * @throws NoSuchAlgorithmException if a KeyManagerFactorySpi
182     *          implementation for the specified algorithm is not
183     *          available from the specified provider.
184     *
185     * @throws NoSuchProviderException if the specified provider is not
186     *          registered in the security provider list.
187     *
188     * @throws IllegalArgumentException if the provider name is null or empty.
189     * @throws NullPointerException if <code>algorithm</code> is null.
190     *
191     * @see java.security.Provider
192     */
193    public static final KeyManagerFactory getInstance(String algorithm,
194            String provider) throws NoSuchAlgorithmException,
195            NoSuchProviderException {
196        GetInstance.Instance instance = GetInstance.getInstance
197                ("KeyManagerFactory", KeyManagerFactorySpi.class,
198                algorithm, provider);
199        return new KeyManagerFactory((KeyManagerFactorySpi)instance.impl,
200                instance.provider, algorithm);
201    }
202
203    /**
204     * Returns a <code>KeyManagerFactory</code> object that acts as a
205     * factory for key managers.
206     *
207     * <p> A new KeyManagerFactory object encapsulating the
208     * KeyManagerFactorySpi implementation from the specified Provider
209     * object is returned.  Note that the specified Provider object
210     * does not have to be registered in the provider list.
211     *
212     * @param algorithm the standard name of the requested algorithm.
213     *          See the <a href=
214     *  "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/jsse/JSSERefGuide.html">
215     *          Java Secure Socket Extension Reference Guide </a>
216     *          for information about standard algorithm names.
217     *
218     * @param provider an instance of the provider.
219     *
220     * @return the new <code>KeyManagerFactory</code> object.
221     *
222     * @throws NoSuchAlgorithmException if a KeyManagerFactorySpi
223     *          implementation for the specified algorithm is not available
224     *          from the specified Provider object.
225     *
226     * @throws IllegalArgumentException if provider is null.
227     * @throws NullPointerException if <code>algorithm</code> is null.
228     *
229     * @see java.security.Provider
230     */
231    public static final KeyManagerFactory getInstance(String algorithm,
232            Provider provider) throws NoSuchAlgorithmException {
233        GetInstance.Instance instance = GetInstance.getInstance
234                ("KeyManagerFactory", KeyManagerFactorySpi.class,
235                algorithm, provider);
236        return new KeyManagerFactory((KeyManagerFactorySpi)instance.impl,
237                instance.provider, algorithm);
238    }
239
240    /**
241     * Returns the provider of this <code>KeyManagerFactory</code> object.
242     *
243     * @return the provider of this <code>KeyManagerFactory</code> object
244     */
245    public final Provider getProvider() {
246        return this.provider;
247    }
248
249
250    /**
251     * Initializes this factory with a source of key material.
252     * <P>
253     * The provider typically uses a KeyStore for obtaining
254     * key material for use during secure socket negotiations.
255     * The KeyStore is generally password-protected.
256     * <P>
257     * For more flexible initialization, please see
258     * {@link #init(ManagerFactoryParameters)}.
259     * <P>
260     *
261     * @param ks the key store or null
262     * @param password the password for recovering keys in the KeyStore
263     * @throws KeyStoreException if this operation fails
264     * @throws NoSuchAlgorithmException if the specified algorithm is not
265     *          available from the specified provider.
266     * @throws UnrecoverableKeyException if the key cannot be recovered
267     *          (e.g. the given password is wrong).
268     */
269    public final void init(KeyStore ks, char[] password) throws
270            KeyStoreException, NoSuchAlgorithmException,
271            UnrecoverableKeyException {
272        factorySpi.engineInit(ks, password);
273    }
274
275
276    /**
277     * Initializes this factory with a source of provider-specific
278     * key material.
279     * <P>
280     * In some cases, initialization parameters other than a keystore
281     * and password may be needed by a provider.  Users of that
282     * particular provider are expected to pass an implementation of
283     * the appropriate <CODE>ManagerFactoryParameters</CODE> as
284     * defined by the provider.  The provider can then call the
285     * specified methods in the <CODE>ManagerFactoryParameters</CODE>
286     * implementation to obtain the needed information.
287     *
288     * @param spec an implementation of a provider-specific parameter
289     *          specification
290     * @throws InvalidAlgorithmParameterException if an error is encountered
291     */
292    public final void init(ManagerFactoryParameters spec) throws
293            InvalidAlgorithmParameterException {
294        factorySpi.engineInit(spec);
295    }
296
297
298    /**
299     * Returns one key manager for each type of key material.
300     *
301     * @return the key managers
302     * @throws IllegalStateException if the KeyManagerFactory is not initialized
303     */
304    public final KeyManager[] getKeyManagers() {
305        return factorySpi.engineGetKeyManagers();
306    }
307}
308