001 /* KeyManagerFactory.java -- factory for key managers.
002 Copyright (C) 2004 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.net.ssl;
040
041 import gnu.java.security.Engine;
042
043 import java.lang.reflect.InvocationTargetException;
044 import java.security.AccessController;
045 import java.security.InvalidAlgorithmParameterException;
046 import java.security.KeyStore;
047 import java.security.KeyStoreException;
048 import java.security.NoSuchAlgorithmException;
049 import java.security.NoSuchProviderException;
050 import java.security.PrivilegedAction;
051 import java.security.Provider;
052 import java.security.Security;
053 import java.security.UnrecoverableKeyException;
054
055 /**
056 * A class that creates key manager implementations based on a
057 * requested algorithm.
058 *
059 * @author Casey Marshall (rsdio@metastatic.org)
060 */
061 public class KeyManagerFactory
062 {
063
064 // Constants and fields.
065 // ------------------------------------------------------------------
066
067 /** The service name for key manager factories. */
068 private static final String KEY_MANAGER_FACTORY = "KeyManagerFactory";
069
070 /** The system default trust manager algorithm. */
071 private static final String DEFAULT_ALGORITHM = "JessieX509";
072
073 /** The underlying engine. */
074 private final KeyManagerFactorySpi kmfSpi;
075
076 /** The provider of this implementation. */
077 private final Provider provider;
078
079 /** The name of this algorithm. */
080 private final String algorithm;
081
082 // Constructor.
083 // ------------------------------------------------------------------
084
085 /**
086 * Create a new key manager factory.
087 *
088 * @param kmfSpi The underlying engine.
089 * @param provider The engine's provider.
090 * @param algorithm The name of this algorithm.
091 */
092 protected KeyManagerFactory(KeyManagerFactorySpi kmfSpi,
093 Provider provider, String algorithm)
094 {
095 this.kmfSpi = kmfSpi;
096 this.provider = provider;
097 this.algorithm = algorithm;
098 }
099
100 // Class methods.
101 // ------------------------------------------------------------------
102
103 /**
104 * Get the default algorithm name. This value may be specified at
105 * run-time via the security property
106 * "ssl.KeyManagerFactory.algorithm". If this property is
107 * not specified, this method returns "JessieX509".
108 *
109 * @return The default key manager factory algorithm's name.
110 */
111 public static final String getDefaultAlgorithm()
112 {
113 String alg = null;
114 try
115 {
116 alg = (String) AccessController.doPrivileged(
117 new PrivilegedAction()
118 {
119 public Object run()
120 {
121 return Security.getProperty("ssl.KeyManagerFactory.algorithm");
122 }
123 }
124 );
125 }
126 catch (SecurityException se)
127 {
128 }
129 if (alg == null)
130 alg = DEFAULT_ALGORITHM;
131 return alg;
132 }
133
134 /**
135 * Create an instance of the named key manager factory, from the first
136 * provider that implements it.
137 *
138 * @param algorithm The type of key manager factory to get.
139 * @return An appropriate implementation of that algoritm.
140 * @throws NoSuchAlgorithmException If no provider implements the requested
141 * algorithm.
142 * @throws IllegalArgumentException if <code>algorithm</code> is
143 * <code>null</code> or is an empty string.
144 */
145 public static final KeyManagerFactory getInstance(String algorithm)
146 throws NoSuchAlgorithmException
147 {
148 Provider[] p = Security.getProviders();
149 NoSuchAlgorithmException lastException = null;
150 for (int i = 0; i < p.length; i++)
151 try
152 {
153 return getInstance(algorithm, p[i]);
154 }
155 catch (NoSuchAlgorithmException x)
156 {
157 lastException = x;
158 }
159 if (lastException != null)
160 throw lastException;
161 throw new NoSuchAlgorithmException(algorithm);
162 }
163
164 /**
165 * Create an instance of the named key manager factory, from the named
166 * provider.
167 *
168 * @param algorithm The type of key manager factory to get.
169 * @param provider The name of the provider to get the implementation from.
170 * @return An appropriate implementation of that algorithm.
171 * @throws NoSuchAlgorithmException If the provider does not implement the
172 * requested algorithm.
173 * @throws NoSuchProviderException If the named provider does not exist.
174 * @throws IllegalArgumentException if either <code>algorithm</code> or
175 * <code>provider</code> is <code>null</code>, or if
176 * <code>algorithm</code> is an empty string.
177 */
178 public static final KeyManagerFactory getInstance(String algorithm,
179 String provider)
180 throws NoSuchAlgorithmException, NoSuchProviderException
181 {
182 if (provider == null)
183 throw new IllegalArgumentException("provider MUST NOT be null");
184 Provider p = Security.getProvider(provider);
185 if (p == null)
186 throw new NoSuchProviderException(provider);
187 return getInstance(algorithm, p);
188 }
189
190 /**
191 * Create an instance of the named key manager factory, from the given
192 * provider.
193 *
194 * @param algorithm The type of key manager factory to get.
195 * @param provider The provider to get the implementation from.
196 * @return An appropriate implementation of that algorithm.
197 * @throws NoSuchAlgorithmException If the provider does not implement the
198 * requested algorithm.
199 * @throws IllegalArgumentException if either <code>algorithm</code> or
200 * <code>provider</code> is <code>null</code>, or if
201 * <code>algorithm</code> is an empty string.
202 */
203 public static final KeyManagerFactory getInstance(String algorithm,
204 Provider provider)
205 throws NoSuchAlgorithmException
206 {
207 StringBuilder sb = new StringBuilder("KeyManagerFactory algorithm [")
208 .append(algorithm).append("] from provider[")
209 .append(provider).append("] could not be created");
210 Throwable cause;
211 try
212 {
213 Object spi = Engine.getInstance(KEY_MANAGER_FACTORY, algorithm, provider);
214 return new KeyManagerFactory((KeyManagerFactorySpi) spi, provider, algorithm);
215 }
216 catch (InvocationTargetException x)
217 {
218 cause = x.getCause();
219 if (cause instanceof NoSuchAlgorithmException)
220 throw (NoSuchAlgorithmException) cause;
221 if (cause == null)
222 cause = x;
223 }
224 catch (ClassCastException x)
225 {
226 cause = x;
227 }
228 NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
229 x.initCause(cause);
230 throw x;
231 }
232
233 /**
234 * Returns the name of this key manager factory algorithm.
235 *
236 * @return The name of this key manager factory algorithm.
237 */
238 public final String getAlgorithm()
239 {
240 return algorithm;
241 }
242
243 /**
244 * Get an array of key managers appropriate for this algorithm, with
245 * the most preferred manager first.
246 *
247 * @return The array of key managers.
248 */
249 public final KeyManager[] getKeyManagers()
250 {
251 return kmfSpi.engineGetKeyManagers();
252 }
253
254 /**
255 * Returns the provider of this implementation.
256 *
257 * @return The provider of this implementation.
258 */
259 public final Provider getProvider()
260 {
261 return provider;
262 }
263
264 /**
265 * Initialize this instance with an implementation-dependent
266 * parameter object.
267 *
268 * @param params The parameters to initialize with.
269 * @throws InvalidAlgorithmParameterException If the specified
270 * parameters are inappropriate.
271 */
272 public final void init(ManagerFactoryParameters params)
273 throws InvalidAlgorithmParameterException
274 {
275 kmfSpi.engineInit(params);
276 }
277
278 /**
279 * Initialize this instance with a key store and a password for
280 * private key entries.
281 *
282 * @param store The key store to read.
283 * @param passwd The password protecting private keys in the store.
284 * @throws KeyStoreException If an error occurs reading the keys.
285 * @throws NoSuchAlgorithmException If an algorithm (such as a
286 * certificate algorithm) is not available.
287 * @throws UnrecoverableKeyException If the password is incorrect.
288 */
289 public final void init(KeyStore store, char[] passwd)
290 throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException
291 {
292 kmfSpi.engineInit(store, passwd);
293 }
294 }