OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / java / security / KeyStoreSpi.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 package java.security;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.security.cert.Certificate;
24 import java.security.cert.CertificateException;
25 import java.util.Date;
26 import java.util.Enumeration;
27 import javax.crypto.SecretKey;
28 import javax.security.auth.callback.CallbackHandler;
29 import javax.security.auth.callback.PasswordCallback;
30
31 /**
32  * {@code KeyStoreSpi} is the Service Provider Interface (SPI) definition for
33  * {@link KeyStore}.
34  *
35  * @see KeyStore
36  */
37 public abstract class KeyStoreSpi {
38
39     /**
40      * Returns the key with the given alias, using the password to recover the
41      * key from the store.
42      *
43      * @param alias
44      *            the alias for the entry.
45      * @param password
46      *            the password used to recover the key.
47      * @return the key with the specified alias, or {@code null} if the
48      *         specified alias is not bound to an entry.
49      * @throws NoSuchAlgorithmException
50      *             if the algorithm for recovering the key is not available.
51      * @throws UnrecoverableKeyException
52      *             if the key can not be recovered.
53      */
54     public abstract Key engineGetKey(String alias, char[] password)
55             throws NoSuchAlgorithmException, UnrecoverableKeyException;
56
57     /**
58      * Returns the certificate chain for the entry with the given alias.
59      *
60      * @param alias
61      *            the alias for the entry
62      * @return the certificate chain for the entry with the given alias, or
63      *         {@code null} if the specified alias is not bound to an entry.
64      */
65     public abstract Certificate[] engineGetCertificateChain(String alias);
66
67     /**
68      * Returns the trusted certificate for the entry with the given alias.
69      *
70      * @param alias
71      *            the alias for the entry.
72      * @return the trusted certificate for the entry with the given alias, or
73      *         {@code null} if the specified alias is not bound to an entry.
74      */
75     public abstract Certificate engineGetCertificate(String alias);
76
77     /**
78      * Returns the creation date of the entry with the given alias.
79      *
80      * @param alias
81      *            the alias for the entry.
82      * @return the creation date, or {@code null} if the specified alias is not
83      *         bound to an entry.
84      */
85     public abstract Date engineGetCreationDate(String alias);
86
87     /**
88      * Associates the given alias with the key, password and certificate chain.
89      * <p>
90      * If the specified alias already exists, it will be reassigned.
91      *
92      * @param alias
93      *            the alias for the key.
94      * @param key
95      *            the key.
96      * @param password
97      *            the password.
98      * @param chain
99      *            the certificate chain.
100      * @throws KeyStoreException
101      *             if the specified key can not be protected, or if this
102      *             operation fails for another reason.
103      * @throws IllegalArgumentException
104      *             if {@code key} is a {@code PrivateKey} and {@code chain} does
105      *             not contain any certificates.
106      */
107     public abstract void engineSetKeyEntry(String alias, Key key,
108             char[] password, Certificate[] chain) throws KeyStoreException;
109
110     /**
111      * Associates the given alias with a key and a certificate chain.
112      * <p>
113      * If the specified alias already exists, it will be reassigned.
114      *
115      * @param alias
116      *            the alias for the key.
117      * @param key
118      *            the key in an encoded format.
119      * @param chain
120      *            the certificate chain.
121      * @throws KeyStoreException
122      *             if this operation fails.
123      * @throws IllegalArgumentException
124      *             if {@code key} is a {@code PrivateKey} and {@code chain}
125      *             does.
126      */
127     public abstract void engineSetKeyEntry(String alias, byte[] key,
128             Certificate[] chain) throws KeyStoreException;
129
130     /**
131      * Associates the given alias with a certificate.
132      * <p>
133      * If the specified alias already exists, it will be reassigned.
134      *
135      * @param alias
136      *            the alias for the certificate.
137      * @param cert
138      *            the certificate.
139      * @throws KeyStoreException
140      *             if an existing alias is not associated to an entry containing
141      *             a trusted certificate, or this method fails for any other
142      *             reason.
143      */
144     public abstract void engineSetCertificateEntry(String alias,
145             Certificate cert) throws KeyStoreException;
146
147     /**
148      * Deletes the entry identified with the given alias from this {@code
149      * KeyStoreSpi}.
150      *
151      * @param alias
152      *            the alias for the entry.
153      * @throws KeyStoreException
154      *             if the entry can not be deleted.
155      */
156     public abstract void engineDeleteEntry(String alias)
157             throws KeyStoreException;
158
159     /**
160      * Returns an {@code Enumeration} over all alias names stored in this
161      * {@code KeyStoreSpi}.
162      *
163      * @return an {@code Enumeration} over all alias names stored in this
164      *         {@code KeyStoreSpi}.
165      */
166     public abstract Enumeration<String> engineAliases();
167
168     /**
169      * Indicates whether the given alias is present in this {@code KeyStoreSpi}.
170      *
171      * @param alias
172      *            the alias of an entry.
173      * @return {@code true} if the alias exists, {@code false} otherwise.
174      */
175     public abstract boolean engineContainsAlias(String alias);
176
177     /**
178      * Returns the number of entries stored in this {@code KeyStoreSpi}.
179      *
180      * @return the number of entries stored in this {@code KeyStoreSpi}.
181      */
182     public abstract int engineSize();
183
184     /**
185      * Indicates whether the specified alias is associated with either a
186      * {@link KeyStore.PrivateKeyEntry} or a {@link KeyStore.SecretKeyEntry}.
187      *
188      * @param alias
189      *            the alias of an entry.
190      * @return {@code true} if the given alias is associated with a key entry.
191      */
192     public abstract boolean engineIsKeyEntry(String alias);
193
194     /**
195      * Indicates whether the specified alias is associated with a
196      * {@link KeyStore.TrustedCertificateEntry}.
197      *
198      * @param alias
199      *            the alias of an entry.
200      * @return {@code true} if the given alias is associated with a certificate
201      *         entry.
202      */
203     public abstract boolean engineIsCertificateEntry(String alias);
204
205     /**
206      * Returns the alias associated with the first entry whose certificate
207      * matches the specified certificate.
208      *
209      * @param cert
210      *            the certificate to find the associated entry's alias for.
211      * @return the alias or {@code null} if no entry with the specified
212      *         certificate can be found.
213      */
214     public abstract String engineGetCertificateAlias(Certificate cert);
215
216     /**
217      * Writes this {@code KeyStoreSpi} to the specified {@code OutputStream}.
218      * The data written to the {@code OutputStream} is protected by the
219      * specified password.
220      *
221      * @param stream
222      *            the {@code OutputStream} to write the store's data to.
223      * @param password
224      *            the password to protect the data.
225      * @throws IOException
226      *             if a problem occurred while writing to the stream.
227      * @throws NoSuchAlgorithmException
228      *             if the required algorithm is not available.
229      * @throws CertificateException
230      *             if the an exception occurred while storing the certificates
231      *             of this code {@code KeyStoreSpi}.
232      */
233     public abstract void engineStore(OutputStream stream, char[] password)
234             throws IOException, NoSuchAlgorithmException, CertificateException;
235
236     /**
237      * Stores this {@code KeyStoreSpi} using the specified {@code
238      * LoadStoreParameter}.
239      *
240      * @param param
241      *            the {@code LoadStoreParameter} that specifies how to store
242      *            this {@code KeyStoreSpi}, maybe {@code null}.
243      * @throws IOException
244      *             if a problem occurred while writing to the stream.
245      * @throws NoSuchAlgorithmException
246      *             if the required algorithm is not available.
247      * @throws CertificateException
248      *             if the an exception occurred while storing the certificates
249      *             of this code {@code KeyStoreSpi}.
250      * @throws IllegalArgumentException
251      *             if the given {@link KeyStore.LoadStoreParameter} is not
252      *             recognized.
253      */
254     public void engineStore(KeyStore.LoadStoreParameter param)
255             throws IOException, NoSuchAlgorithmException, CertificateException {
256         throw new UnsupportedOperationException();
257     }
258
259     /**
260      * Loads this {@code KeyStoreSpi} from the given {@code InputStream}.
261      * Utilizes the given password to verify the stored data.
262      *
263      * @param stream
264      *            the {@code InputStream} to load this {@code KeyStoreSpi}'s
265      *            data from.
266      * @param password
267      *            the password to verify the stored data, maybe {@code null}.
268      * @throws IOException
269      *             if a problem occurred while reading from the stream.
270      * @throws NoSuchAlgorithmException
271      *             if the required algorithm is not available.
272      * @throws CertificateException
273      *             if the an exception occurred while loading the certificates
274      *             of this code {@code KeyStoreSpi}.
275      */
276     public abstract void engineLoad(InputStream stream, char[] password)
277             throws IOException, NoSuchAlgorithmException, CertificateException;
278
279     /**
280      * Loads this {@code KeyStoreSpi} using the specified {@code
281      * LoadStoreParameter}.
282      *
283      * @param param
284      *            the {@code LoadStoreParameter} that specifies how to load this
285      *            {@code KeyStoreSpi}, maybe {@code null}.
286      * @throws IOException
287      *             if a problem occurred while reading from the stream.
288      * @throws NoSuchAlgorithmException
289      *             if the required algorithm is not available.
290      * @throws CertificateException
291      *             if the an exception occurred while loading the certificates
292      *             of this code {@code KeyStoreSpi}.
293      * @throws IllegalArgumentException
294      *             if the given {@link KeyStore.LoadStoreParameter} is not
295      *             recognized.
296      */
297     public void engineLoad(KeyStore.LoadStoreParameter param)
298             throws IOException, NoSuchAlgorithmException, CertificateException {
299         if (param == null) {
300             engineLoad(null, null);
301             return;
302         }
303         char[] pwd;
304         KeyStore.ProtectionParameter pp = param.getProtectionParameter();
305         if (pp instanceof KeyStore.PasswordProtection) {
306             try {
307                 pwd = ((KeyStore.PasswordProtection) pp).getPassword();
308                 engineLoad(null, pwd);
309                 return;
310             } catch (IllegalStateException e) {
311                 throw new IllegalArgumentException(e);
312             }
313         }
314         if (pp instanceof KeyStore.CallbackHandlerProtection) {
315             try {
316                 pwd = getPasswordFromCallBack(pp);
317                 engineLoad(null, pwd);
318                 return;
319             } catch (UnrecoverableEntryException e) {
320                 throw new IllegalArgumentException(e);
321             }
322         }
323         throw new UnsupportedOperationException("protectionParameter is neither PasswordProtection "
324                                                 + "nor CallbackHandlerProtection instance");
325     }
326
327     /**
328      * Returns the {@code Entry} with the given alias, using the specified
329      * {@code ProtectionParameter}.
330      *
331      * @param alias
332      *            the alias of the requested entry.
333      * @param protParam
334      *            the {@code ProtectionParameter}, used to protect the requested
335      *            entry, maybe {@code null}.
336      * @return he {@code Entry} with the given alias, using the specified
337      *         {@code ProtectionParameter}.
338      * @throws NoSuchAlgorithmException
339      *             if the required algorithm is not available.
340      * @throws UnrecoverableEntryException
341      *             if the entry can not be recovered.
342      * @throws KeyStoreException
343      *             if this operation fails
344      */
345     public KeyStore.Entry engineGetEntry(String alias,
346             KeyStore.ProtectionParameter protParam) throws KeyStoreException,
347             NoSuchAlgorithmException, UnrecoverableEntryException {
348         if (!engineContainsAlias(alias)) {
349             return null;
350         }
351         if (engineIsCertificateEntry(alias)) {
352             return new KeyStore.TrustedCertificateEntry(
353                     engineGetCertificate(alias));
354         }
355         char[] passW = null;
356         if (protParam != null) {
357             if (protParam instanceof KeyStore.PasswordProtection) {
358                 try {
359                     passW = ((KeyStore.PasswordProtection) protParam)
360                             .getPassword();
361                 } catch (IllegalStateException ee) {
362                     throw new KeyStoreException("Password was destroyed", ee);
363                 }
364             } else if (protParam instanceof KeyStore.CallbackHandlerProtection) {
365                 passW = getPasswordFromCallBack(protParam);
366             } else {
367                 throw new UnrecoverableEntryException("ProtectionParameter object is not "
368                                                       + "PasswordProtection: " + protParam);
369             }
370         }
371         if (engineIsKeyEntry(alias)) {
372             Key key = engineGetKey(alias, passW);
373             if (key instanceof PrivateKey) {
374                 return new KeyStore.PrivateKeyEntry((PrivateKey) key,
375                                                     engineGetCertificateChain(alias));
376             }
377             if (key instanceof SecretKey) {
378                 return new KeyStore.SecretKeyEntry((SecretKey) key);
379             }
380         }
381         throw new NoSuchAlgorithmException("Unknown KeyStore.Entry object");
382     }
383
384     /**
385      * Stores the given {@code Entry} in this {@code KeyStoreSpi} and associates
386      * the entry with the given {@code alias}. The entry is protected by the
387      * specified {@code ProtectionParameter}.
388      * <p>
389      * If the specified alias already exists, it will be reassigned.
390      *
391      * @param alias
392      *            the alias for the entry.
393      * @param entry
394      *            the entry to store.
395      * @param protParam
396      *            the {@code ProtectionParameter} to protect the entry.
397      * @throws KeyStoreException
398      *             if this operation fails.
399      */
400     public void engineSetEntry(String alias, KeyStore.Entry entry,
401             KeyStore.ProtectionParameter protParam) throws KeyStoreException {
402         if (entry == null) {
403             throw new KeyStoreException("entry == null");
404         }
405
406         if (engineContainsAlias(alias)) {
407             engineDeleteEntry(alias);
408         }
409
410         if (entry instanceof KeyStore.TrustedCertificateEntry) {
411             KeyStore.TrustedCertificateEntry trE = (KeyStore.TrustedCertificateEntry) entry;
412             engineSetCertificateEntry(alias, trE.getTrustedCertificate());
413             return;
414         }
415
416         char[] passW = null;
417         if (protParam instanceof KeyStore.PasswordProtection) {
418             try {
419                 passW = ((KeyStore.PasswordProtection) protParam).getPassword();
420             } catch (IllegalStateException ee) {
421                 throw new KeyStoreException("Password was destroyed", ee);
422             }
423         } else {
424             if (protParam instanceof KeyStore.CallbackHandlerProtection) {
425                 try {
426                     passW = getPasswordFromCallBack(protParam);
427                 } catch (Exception e) {
428                     throw new KeyStoreException(e);
429                 }
430             } else {
431                 throw new KeyStoreException("protParam should be PasswordProtection or "
432                                             + "CallbackHandlerProtection");
433             }
434         }
435
436         if (entry instanceof KeyStore.PrivateKeyEntry) {
437             KeyStore.PrivateKeyEntry prE = (KeyStore.PrivateKeyEntry) entry;
438             engineSetKeyEntry(alias, prE.getPrivateKey(), passW, prE
439                     .getCertificateChain());
440             return;
441         }
442
443         if (entry instanceof KeyStore.SecretKeyEntry) {
444             KeyStore.SecretKeyEntry skE = (KeyStore.SecretKeyEntry) entry;
445             engineSetKeyEntry(alias, skE.getSecretKey(), passW, null);
446             //            engineSetKeyEntry(alias, skE.getSecretKey().getEncoded(), null);
447             return;
448         }
449
450         throw new KeyStoreException("Entry object is neither PrivateKeyObject nor SecretKeyEntry "
451                                     + "nor TrustedCertificateEntry: " + entry);
452     }
453
454     /**
455      * Indicates whether the entry for the given alias is assignable to the
456      * provided {@code Class}.
457      *
458      * @param alias
459      *            the alias for the entry.
460      * @param entryClass
461      *            the type of the entry.
462      * @return {@code true} if the {@code Entry} for the alias is assignable to
463      *         the specified {@code entryClass}.
464      */
465     public boolean engineEntryInstanceOf(String alias,
466             Class<? extends KeyStore.Entry> entryClass) {
467         if (!engineContainsAlias(alias)) {
468             return false;
469         }
470
471         try {
472             if (engineIsCertificateEntry(alias)) {
473                 return entryClass
474                         .isAssignableFrom(Class
475                                 .forName("java.security.KeyStore$TrustedCertificateEntry"));
476             }
477
478             if (engineIsKeyEntry(alias)) {
479                 if (entryClass.isAssignableFrom(Class
480                         .forName("java.security.KeyStore$PrivateKeyEntry"))) {
481                     return engineGetCertificate(alias) != null;
482                 }
483
484                 if (entryClass.isAssignableFrom(Class
485                         .forName("java.security.KeyStore$SecretKeyEntry"))) {
486                     return engineGetCertificate(alias) == null;
487                 }
488             }
489         } catch (ClassNotFoundException ignore) {}
490
491         return false;
492     }
493
494     /*
495      * This method returns password which is encapsulated in
496      * CallbackHandlerProtection object If there is no implementation of
497      * CallbackHandler then this method returns null
498      */
499     static char[] getPasswordFromCallBack(KeyStore.ProtectionParameter protParam)
500             throws UnrecoverableEntryException {
501
502         if (protParam == null) {
503             return null;
504         }
505
506         if (!(protParam instanceof KeyStore.CallbackHandlerProtection)) {
507             throw new UnrecoverableEntryException("Incorrect ProtectionParameter");
508         }
509
510         String clName = Security.getProperty("auth.login.defaultCallbackHandler");
511         if (clName == null) {
512             throw new UnrecoverableEntryException("Default CallbackHandler was not defined");
513
514         }
515
516         try {
517             Class<?> cl = Class.forName(clName);
518             CallbackHandler cbHand = (CallbackHandler) cl.newInstance();
519             PasswordCallback[] pwCb = { new PasswordCallback("password: ", true) };
520             cbHand.handle(pwCb);
521             return pwCb[0].getPassword();
522         } catch (Exception e) {
523             throw new UnrecoverableEntryException(e.toString());
524         }
525     }
526 }