001/* KeyStore.java --- Key Store Class
002   Copyright (C) 1999, 2002, 2003, 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 java.security;
040
041import gnu.java.security.Engine;
042
043import java.io.IOException;
044import java.io.InputStream;
045import java.io.OutputStream;
046import java.lang.reflect.InvocationTargetException;
047import java.security.cert.CertificateException;
048import java.util.Date;
049import java.util.Enumeration;
050
051/**
052 * Keystore represents an in-memory collection of keys and
053 * certificates. There are two types of entries:
054 *
055 * <dl>
056 * <dt>Key Entry</dt>
057 *
058 * <dd><p>This type of keystore entry store sensitive crytographic key
059 * information in a protected format.Typically this is a secret
060 * key or a private key with a certificate chain.</p></dd>
061 *
062 * <dt>Trusted Ceritificate Entry</dt>
063 *
064 * <dd><p>This type of keystore entry contains a single public key
065 * certificate belonging to annother entity. It is called trusted
066 * because the keystore owner trusts that the certificates
067 * belongs to the subject (owner) of the certificate.</p></dd>
068 * </dl>
069 *
070 * <p>Entries in a key store are referred to by their "alias": a simple
071 * unique string.
072 *
073 * <p>The structure and persistentence of the key store is not
074 * specified. Any method could be used to protect sensitive
075 * (private or secret) keys. Smart cards or integrated
076 * cryptographic engines could be used or the keystore could
077 * be simply stored in a file.</p>
078 *
079 * @see java.security.cert.Certificate
080 * @see Key
081 */
082public class KeyStore
083{
084
085  // Constants and fields.
086  // ------------------------------------------------------------------------
087
088  /** Service name for key stores. */
089  private static final String KEY_STORE = "KeyStore";
090
091  private KeyStoreSpi keyStoreSpi;
092  private Provider provider;
093  private String type;
094
095  // Constructors.
096  // ------------------------------------------------------------------------
097
098  /**
099     Creates an instance of KeyStore
100
101     @param keyStoreSpi A KeyStore engine to use
102     @param provider A provider to use
103     @param type The type of KeyStore
104   */
105  protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
106  {
107    this.keyStoreSpi = keyStoreSpi;
108    this.provider = provider;
109    this.type = type;
110  }
111
112  /**
113   * Returns an instance of a <code>KeyStore</code> representing the specified
114   * type, from the first provider that implements it.
115   *
116   * @param type the type of keystore to create.
117   * @return a <code>KeyStore</code> repesenting the desired type.
118   * @throws KeyStoreException if the designated type of is not implemented by
119   *           any provider, or the implementation could not be instantiated.
120   * @throws IllegalArgumentException if <code>type</code> is
121   *           <code>null</code> or is an empty string.
122   */
123  public static KeyStore getInstance(String type) throws KeyStoreException
124  {
125    Provider[] p = Security.getProviders();
126    KeyStoreException lastException = null;
127    for (int i = 0; i < p.length; i++)
128      try
129        {
130          return getInstance(type, p[i]);
131        }
132      catch (KeyStoreException x)
133        {
134          lastException = x;
135        }
136    if (lastException != null)
137      throw lastException;
138    throw new KeyStoreException(type);
139  }
140
141  /**
142   * Returns an instance of a <code>KeyStore</code> representing the specified
143   * type, from the named provider.
144   *
145   * @param type the type of keystore to create.
146   * @param provider the name of the provider to use.
147   * @return a <code>KeyStore</code> repesenting the desired type.
148   * @throws KeyStoreException if the designated type is not implemented by the
149   *           given provider.
150   * @throws NoSuchProviderException if the provider is not found.
151   * @throws IllegalArgumentException if either <code>type</code> or
152   *           <code>provider</code> is <code>null</code> or empty.
153   */
154  public static KeyStore getInstance(String type, String provider)
155    throws KeyStoreException, NoSuchProviderException
156  {
157    if (provider == null)
158      throw new IllegalArgumentException("provider MUST NOT be null");
159    provider = provider.trim();
160    if (provider.length() == 0)
161      throw new IllegalArgumentException("provider MUST NOT be empty");
162    Provider p = Security.getProvider(provider);
163    if (p == null)
164      throw new NoSuchProviderException(provider);
165    return getInstance(type, p);
166  }
167
168  /**
169   * Returns an instance of a <code>KeyStore</code> representing the specified
170   * type, from the specified provider.
171   *
172   * @param type the type of keystore to create.
173   * @param provider the provider to use.
174   * @return a <code>KeyStore</code> repesenting the desired type.
175   * @throws KeyStoreException if the designated type is not implemented by the
176   *           given provider.
177   * @throws IllegalArgumentException if either <code>type</code> or
178   *           <code>provider</code> is <code>null</code>, or if
179   *           <code>type</code> is an empty string.
180   * @since 1.4
181   */
182  public static KeyStore getInstance(String type, Provider provider)
183      throws KeyStoreException
184  {
185    Throwable cause;
186    try
187      {
188        Object spi = Engine.getInstance(KEY_STORE, type, provider);
189        return new KeyStore((KeyStoreSpi) spi, provider, type);
190      }
191    catch (NoSuchAlgorithmException x)
192      {
193        cause = x;
194      }
195    catch (InvocationTargetException x)
196      {
197        cause = x.getCause() != null ? x.getCause() : x;
198      }
199    catch (ClassCastException x)
200      {
201        cause = x;
202      }
203    KeyStoreException x = new KeyStoreException(type);
204    x.initCause(cause);
205    throw x;
206  }
207
208  /**
209   * Returns the default KeyStore type. This method looks up the
210   * type in &lt;JAVA_HOME&gt;/lib/security/java.security with the
211   * property "keystore.type" or if that fails then "gkr" .
212   */
213  public static final String getDefaultType()
214  {
215    // Security reads every property in java.security so it
216    // will return this property if it exists.
217    String tmp = AccessController.doPrivileged(new PrivilegedAction<String> () {
218        public String run()
219        {
220          return Security.getProperty("keystore.type");
221        }
222      });
223
224    if (tmp == null)
225      tmp = "gkr";
226
227    return tmp;
228  }
229
230  // Instance methods.
231  // ------------------------------------------------------------------------
232
233  /**
234     Gets the provider that the class is from.
235
236     @return the provider of this class
237   */
238  public final Provider getProvider()
239  {
240    return provider;
241  }
242
243  /**
244     Returns the type of the KeyStore supported
245
246     @return A string with the type of KeyStore
247   */
248  public final String getType()
249  {
250    return type;
251  }
252
253  /**
254     Returns the key associated with given alias using the
255     supplied password.
256
257     @param alias an alias for the key to get
258     @param password password to access key with
259
260     @return the requested key, or null otherwise
261
262     @throws NoSuchAlgorithmException if there is no algorithm
263     for recovering the key
264     @throws UnrecoverableKeyException key cannot be reocovered
265     (wrong password).
266   */
267  public final Key getKey(String alias, char[]password)
268    throws KeyStoreException, NoSuchAlgorithmException,
269    UnrecoverableKeyException
270  {
271    return keyStoreSpi.engineGetKey(alias, password);
272  }
273
274  /**
275     Gets a Certificate chain for the specified alias.
276
277     @param alias the alias name
278
279     @return a chain of Certificates ( ordered from the user's
280     certificate to the Certificate Authority's ) or
281     null if the alias does not exist or there is no
282     certificate chain for the alias ( the alias refers
283     to a trusted certificate entry or there is no entry).
284   */
285  public final java.security.cert.
286    Certificate[] getCertificateChain(String alias) throws KeyStoreException
287  {
288    return keyStoreSpi.engineGetCertificateChain(alias);
289  }
290
291  /**
292     Gets a Certificate for the specified alias.
293
294     If there is a trusted certificate entry then that is returned.
295     it there is a key entry with a certificate chain then the
296     first certificate is return or else null.
297
298     @param alias the alias name
299
300     @return a Certificate or null if the alias does not exist
301     or there is no certificate for the alias
302   */
303  public final java.security.cert.Certificate getCertificate(String alias)
304    throws KeyStoreException
305  {
306    return keyStoreSpi.engineGetCertificate(alias);
307  }
308
309  /**
310     Gets entry creation date for the specified alias.
311
312     @param alias the alias name
313
314     @returns the entry creation date or null
315   */
316  public final Date getCreationDate(String alias) throws KeyStoreException
317  {
318    return keyStoreSpi.engineGetCreationDate(alias);
319  }
320
321  /**
322     Assign the key to the alias in the keystore, protecting it
323     with the given password. It will overwrite an existing
324     entry and if the key is a PrivateKey, also add the
325     certificate chain representing the corresponding public key.
326
327     @param alias the alias name
328     @param key the key to add
329     @password the password to protect with
330     @param chain the certificate chain for the corresponding
331     public key
332
333     @throws KeyStoreException if it fails
334   */
335  public final void setKeyEntry(String alias, Key key, char[]password,
336                                java.security.cert.
337                                Certificate[]chain) throws KeyStoreException
338  {
339    keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
340  }
341
342  /**
343     Assign the key to the alias in the keystore. It will overwrite
344     an existing entry and if the key is a PrivateKey, also
345     add the certificate chain representing the corresponding
346     public key.
347
348     @param alias the alias name
349     @param key the key to add
350     @param chain the certificate chain for the corresponding
351     public key
352
353     @throws KeyStoreException if it fails
354   */
355  public final void setKeyEntry(String alias, byte[]key,
356                                java.security.cert.
357                                Certificate[]chain) throws KeyStoreException
358  {
359    keyStoreSpi.engineSetKeyEntry(alias, key, chain);
360  }
361
362  /**
363     Assign the certificate to the alias in the keystore. It
364     will overwrite an existing entry.
365
366     @param alias the alias name
367     @param cert the certificate to add
368
369     @throws KeyStoreException if it fails
370   */
371  public final void setCertificateEntry(String alias,
372                                        java.security.cert.
373                                        Certificate cert) throws
374    KeyStoreException
375  {
376    keyStoreSpi.engineSetCertificateEntry(alias, cert);
377  }
378
379  /**
380     Deletes the entry for the specified entry.
381
382     @param alias the alias name
383
384     @throws KeyStoreException if it fails
385   */
386  public final void deleteEntry(String alias) throws KeyStoreException
387  {
388    keyStoreSpi.engineDeleteEntry(alias);
389  }
390
391  /**
392     Generates a list of all the aliases in the keystore.
393
394     @return an Enumeration of the aliases
395   */
396  public final Enumeration<String> aliases() throws KeyStoreException
397  {
398    return keyStoreSpi.engineAliases();
399  }
400
401  /**
402     Determines if the keystore contains the specified alias.
403
404     @param alias the alias name
405
406     @return true if it contains the alias, false otherwise
407   */
408  public final boolean containsAlias(String alias) throws KeyStoreException
409  {
410    return keyStoreSpi.engineContainsAlias(alias);
411  }
412
413  /**
414     Returns the number of entries in the keystore.
415
416     @returns the number of keystore entries.
417   */
418  public final int size() throws KeyStoreException
419  {
420    return keyStoreSpi.engineSize();
421  }
422
423  /**
424     Determines if the keystore contains a key entry for
425     the specified alias.
426
427     @param alias the alias name
428
429     @return true if it is a key entry, false otherwise
430   */
431  public final boolean isKeyEntry(String alias) throws KeyStoreException
432  {
433    return keyStoreSpi.engineIsKeyEntry(alias);
434  }
435
436
437  /**
438     Determines if the keystore contains a certificate entry for
439     the specified alias.
440
441     @param alias the alias name
442
443     @return true if it is a certificate entry, false otherwise
444   */
445  public final boolean isCertificateEntry(String alias)
446    throws KeyStoreException
447  {
448    return keyStoreSpi.engineIsCertificateEntry(alias);
449  }
450
451  /**
452     Determines if the keystore contains the specified certificate
453     entry and returns the alias.
454
455     It checks every entry and for a key entry checks only the
456     first certificate in the chain.
457
458     @param cert Certificate to look for
459
460     @return alias of first matching certificate, null if it
461     does not exist.
462   */
463  public final String getCertificateAlias(java.security.cert.Certificate cert)
464    throws KeyStoreException
465  {
466    return keyStoreSpi.engineGetCertificateAlias(cert);
467  }
468
469  /**
470     Stores the keystore in the specified output stream and it
471     uses the specified key it keep it secure.
472
473     @param stream the output stream to save the keystore to
474     @param password the password to protect the keystore integrity with
475
476     @throws IOException if an I/O error occurs.
477     @throws NoSuchAlgorithmException the data integrity algorithm
478     used cannot be found.
479     @throws CertificateException if any certificates could not be
480     stored in the output stream.
481   */
482  public final void store(OutputStream stream, char[]password)
483    throws KeyStoreException, IOException, NoSuchAlgorithmException,
484    CertificateException
485  {
486    keyStoreSpi.engineStore(stream, password);
487  }
488
489  /**
490     Loads the keystore from the specified input stream and it
491     uses the specified password to check for integrity if supplied.
492
493     @param stream the input stream to load the keystore from
494     @param password the password to check the keystore integrity with
495
496     @throws IOException if an I/O error occurs.
497     @throws NoSuchAlgorithmException the data integrity algorithm
498     used cannot be found.
499     @throws CertificateException if any certificates could not be
500     stored in the output stream.
501   */
502  public final void load(InputStream stream, char[]password)
503    throws IOException, NoSuchAlgorithmException, CertificateException
504  {
505    keyStoreSpi.engineLoad(stream, password);
506  }
507
508}