001/* KeyManagerFactory.java -- factory for key managers. 002 Copyright (C) 2004 Free Software Foundation, Inc. 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038 039package javax.net.ssl; 040 041import gnu.java.security.Engine; 042 043import java.lang.reflect.InvocationTargetException; 044import java.security.AccessController; 045import java.security.InvalidAlgorithmParameterException; 046import java.security.KeyStore; 047import java.security.KeyStoreException; 048import java.security.NoSuchAlgorithmException; 049import java.security.NoSuchProviderException; 050import java.security.PrivilegedAction; 051import java.security.Provider; 052import java.security.Security; 053import 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 */ 061public 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}