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