1 /* KeyStore.java --- Key Store Class
2    Copyright (C) 1999, 2002, 2003, 2004  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.security;
40 
41 import gnu.java.security.Engine;
42 
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.OutputStream;
46 import java.lang.reflect.InvocationTargetException;
47 import java.security.cert.CertificateException;
48 import java.util.Date;
49 import java.util.Enumeration;
50 
51 /**
52  * Keystore represents an in-memory collection of keys and
53  * certificates. There are two types of entries:
54  *
55  * <dl>
56  * <dt>Key Entry</dt>
57  *
58  * <dd><p>This type of keystore entry store sensitive crytographic key
59  * information in a protected format.Typically this is a secret
60  * key or a private key with a certificate chain.</p></dd>
61  *
62  * <dt>Trusted Ceritificate Entry</dt>
63  *
64  * <dd><p>This type of keystore entry contains a single public key
65  * certificate belonging to annother entity. It is called trusted
66  * because the keystore owner trusts that the certificates
67  * belongs to the subject (owner) of the certificate.</p></dd>
68  * </dl>
69  *
70  * <p>Entries in a key store are referred to by their "alias": a simple
71  * unique string.
72  *
73  * <p>The structure and persistentence of the key store is not
74  * specified. Any method could be used to protect sensitive
75  * (private or secret) keys. Smart cards or integrated
76  * cryptographic engines could be used or the keystore could
77  * be simply stored in a file.</p>
78  *
79  * @see java.security.cert.Certificate
80  * @see Key
81  */
82 public class KeyStore
83 {
84 
85   // Constants and fields.
86   // ------------------------------------------------------------------------
87 
88   /** Service name for key stores. */
89   private static final String KEY_STORE = "KeyStore";
90 
91   private KeyStoreSpi keyStoreSpi;
92   private Provider provider;
93   private String type;
94 
95   // Constructors.
96   // ------------------------------------------------------------------------
97 
98   /**
99      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    */
KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)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    */
getInstance(String type)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    */
getInstance(String type, String provider)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    */
getInstance(String type, Provider provider)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    */
getDefaultType()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    */
getProvider()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    */
getType()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    */
getKey(String alias, char[]password)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.
getCertificateChain(String alias)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    */
getCertificate(String alias)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    */
getCreationDate(String alias)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    */
setKeyEntry(String alias, Key key, char[]password, java.security.cert. Certificate[]chain)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    */
setKeyEntry(String alias, byte[]key, java.security.cert. Certificate[]chain)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    */
setCertificateEntry(String alias, java.security.cert. Certificate cert)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    */
deleteEntry(String alias)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    */
aliases()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    */
containsAlias(String alias)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    */
size()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    */
isKeyEntry(String alias)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    */
isCertificateEntry(String alias)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    */
getCertificateAlias(java.security.cert.Certificate cert)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    */
store(OutputStream stream, char[]password)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    */
load(InputStream stream, char[]password)502   public final void load(InputStream stream, char[]password)
503     throws IOException, NoSuchAlgorithmException, CertificateException
504   {
505     keyStoreSpi.engineLoad(stream, password);
506   }
507 
508 }
509