blob: 8589e6a7d205303d6d229500e6fa60b9e08d3204 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.security;
27
28import java.io.*;
29import java.util.*;
30
31import java.security.KeyStore.*;
32import java.security.cert.Certificate;
33import java.security.cert.CertificateException;
34
35import javax.crypto.SecretKey;
36
37import javax.security.auth.callback.*;
38
39/**
40 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
41 * for the <code>KeyStore</code> class.
42 * All the abstract methods in this class must be implemented by each
43 * cryptographic service provider who wishes to supply the implementation
44 * of a keystore for a particular keystore type.
45 *
46 * @author Jan Luehe
47 *
48 *
49 * @see KeyStore
50 *
51 * @since 1.2
52 */
53
54public abstract class KeyStoreSpi {
55
56 /**
57 * Returns the key associated with the given alias, using the given
58 * password to recover it. The key must have been associated with
59 * the alias by a call to <code>setKeyEntry</code>,
60 * or by a call to <code>setEntry</code> with a
61 * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>.
62 *
63 * @param alias the alias name
64 * @param password the password for recovering the key
65 *
66 * @return the requested key, or null if the given alias does not exist
67 * or does not identify a key-related entry.
68 *
69 * @exception NoSuchAlgorithmException if the algorithm for recovering the
70 * key cannot be found
71 * @exception UnrecoverableKeyException if the key cannot be recovered
72 * (e.g., the given password is wrong).
73 */
74 public abstract Key engineGetKey(String alias, char[] password)
75 throws NoSuchAlgorithmException, UnrecoverableKeyException;
76
77 /**
78 * Returns the certificate chain associated with the given alias.
79 * The certificate chain must have been associated with the alias
80 * by a call to <code>setKeyEntry</code>,
81 * or by a call to <code>setEntry</code> with a
82 * <code>PrivateKeyEntry</code>.
83 *
84 * @param alias the alias name
85 *
86 * @return the certificate chain (ordered with the user's certificate first
87 * and the root certificate authority last), or null if the given alias
88 * does not exist or does not contain a certificate chain
89 */
90 public abstract Certificate[] engineGetCertificateChain(String alias);
91
92 /**
93 * Returns the certificate associated with the given alias.
94 *
95 * <p> If the given alias name identifies an entry
96 * created by a call to <code>setCertificateEntry</code>,
97 * or created by a call to <code>setEntry</code> with a
98 * <code>TrustedCertificateEntry</code>,
99 * then the trusted certificate contained in that entry is returned.
100 *
101 * <p> If the given alias name identifies an entry
102 * created by a call to <code>setKeyEntry</code>,
103 * or created by a call to <code>setEntry</code> with a
104 * <code>PrivateKeyEntry</code>,
105 * then the first element of the certificate chain in that entry
106 * (if a chain exists) is returned.
107 *
108 * @param alias the alias name
109 *
110 * @return the certificate, or null if the given alias does not exist or
111 * does not contain a certificate.
112 */
113 public abstract Certificate engineGetCertificate(String alias);
114
115 /**
116 * Returns the creation date of the entry identified by the given alias.
117 *
118 * @param alias the alias name
119 *
120 * @return the creation date of this entry, or null if the given alias does
121 * not exist
122 */
123 public abstract Date engineGetCreationDate(String alias);
124
125 /**
126 * Assigns the given key to the given alias, protecting it with the given
127 * password.
128 *
129 * <p>If the given key is of type <code>java.security.PrivateKey</code>,
130 * it must be accompanied by a certificate chain certifying the
131 * corresponding public key.
132 *
133 * <p>If the given alias already exists, the keystore information
134 * associated with it is overridden by the given key (and possibly
135 * certificate chain).
136 *
137 * @param alias the alias name
138 * @param key the key to be associated with the alias
139 * @param password the password to protect the key
140 * @param chain the certificate chain for the corresponding public
141 * key (only required if the given key is of type
142 * <code>java.security.PrivateKey</code>).
143 *
144 * @exception KeyStoreException if the given key cannot be protected, or
145 * this operation fails for some other reason
146 */
147 public abstract void engineSetKeyEntry(String alias, Key key,
148 char[] password,
149 Certificate[] chain)
150 throws KeyStoreException;
151
152 /**
153 * Assigns the given key (that has already been protected) to the given
154 * alias.
155 *
156 * <p>If the protected key is of type
157 * <code>java.security.PrivateKey</code>,
158 * it must be accompanied by a certificate chain certifying the
159 * corresponding public key.
160 *
161 * <p>If the given alias already exists, the keystore information
162 * associated with it is overridden by the given key (and possibly
163 * certificate chain).
164 *
165 * @param alias the alias name
166 * @param key the key (in protected format) to be associated with the alias
167 * @param chain the certificate chain for the corresponding public
168 * key (only useful if the protected key is of type
169 * <code>java.security.PrivateKey</code>).
170 *
171 * @exception KeyStoreException if this operation fails.
172 */
173 public abstract void engineSetKeyEntry(String alias, byte[] key,
174 Certificate[] chain)
175 throws KeyStoreException;
176
177 /**
178 * Assigns the given certificate to the given alias.
179 *
180 * <p> If the given alias identifies an existing entry
181 * created by a call to <code>setCertificateEntry</code>,
182 * or created by a call to <code>setEntry</code> with a
183 * <code>TrustedCertificateEntry</code>,
184 * the trusted certificate in the existing entry
185 * is overridden by the given certificate.
186 *
187 * @param alias the alias name
188 * @param cert the certificate
189 *
190 * @exception KeyStoreException if the given alias already exists and does
191 * not identify an entry containing a trusted certificate,
192 * or this operation fails for some other reason.
193 */
194 public abstract void engineSetCertificateEntry(String alias,
195 Certificate cert)
196 throws KeyStoreException;
197
198 /**
199 * Deletes the entry identified by the given alias from this keystore.
200 *
201 * @param alias the alias name
202 *
203 * @exception KeyStoreException if the entry cannot be removed.
204 */
205 public abstract void engineDeleteEntry(String alias)
206 throws KeyStoreException;
207
208 /**
209 * Lists all the alias names of this keystore.
210 *
211 * @return enumeration of the alias names
212 */
213 public abstract Enumeration<String> engineAliases();
214
215 /**
216 * Checks if the given alias exists in this keystore.
217 *
218 * @param alias the alias name
219 *
220 * @return true if the alias exists, false otherwise
221 */
222 public abstract boolean engineContainsAlias(String alias);
223
224 /**
225 * Retrieves the number of entries in this keystore.
226 *
227 * @return the number of entries in this keystore
228 */
229 public abstract int engineSize();
230
231 /**
232 * Returns true if the entry identified by the given alias
233 * was created by a call to <code>setKeyEntry</code>,
234 * or created by a call to <code>setEntry</code> with a
235 * <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>.
236 *
237 * @param alias the alias for the keystore entry to be checked
238 *
239 * @return true if the entry identified by the given alias is a
240 * key-related, false otherwise.
241 */
242 public abstract boolean engineIsKeyEntry(String alias);
243
244 /**
245 * Returns true if the entry identified by the given alias
246 * was created by a call to <code>setCertificateEntry</code>,
247 * or created by a call to <code>setEntry</code> with a
248 * <code>TrustedCertificateEntry</code>.
249 *
250 * @param alias the alias for the keystore entry to be checked
251 *
252 * @return true if the entry identified by the given alias contains a
253 * trusted certificate, false otherwise.
254 */
255 public abstract boolean engineIsCertificateEntry(String alias);
256
257 /**
258 * Returns the (alias) name of the first keystore entry whose certificate
259 * matches the given certificate.
260 *
261 * <p>This method attempts to match the given certificate with each
262 * keystore entry. If the entry being considered was
263 * created by a call to <code>setCertificateEntry</code>,
264 * or created by a call to <code>setEntry</code> with a
265 * <code>TrustedCertificateEntry</code>,
266 * then the given certificate is compared to that entry's certificate.
267 *
268 * <p> If the entry being considered was
269 * created by a call to <code>setKeyEntry</code>,
270 * or created by a call to <code>setEntry</code> with a
271 * <code>PrivateKeyEntry</code>,
272 * then the given certificate is compared to the first
273 * element of that entry's certificate chain.
274 *
275 * @param cert the certificate to match with.
276 *
277 * @return the alias name of the first entry with matching certificate,
278 * or null if no such entry exists in this keystore.
279 */
280 public abstract String engineGetCertificateAlias(Certificate cert);
281
282 /**
283 * Stores this keystore to the given output stream, and protects its
284 * integrity with the given password.
285 *
286 * @param stream the output stream to which this keystore is written.
287 * @param password the password to generate the keystore integrity check
288 *
289 * @exception IOException if there was an I/O problem with data
290 * @exception NoSuchAlgorithmException if the appropriate data integrity
291 * algorithm could not be found
292 * @exception CertificateException if any of the certificates included in
293 * the keystore data could not be stored
294 */
295 public abstract void engineStore(OutputStream stream, char[] password)
296 throws IOException, NoSuchAlgorithmException, CertificateException;
297
298 /**
299 * Stores this keystore using the given
300 * <code>KeyStore.LoadStoreParmeter</code>.
301 *
302 * @param param the <code>KeyStore.LoadStoreParmeter</code>
303 * that specifies how to store the keystore,
304 * which may be <code>null</code>
305 *
306 * @exception IllegalArgumentException if the given
307 * <code>KeyStore.LoadStoreParmeter</code>
308 * input is not recognized
309 * @exception IOException if there was an I/O problem with data
310 * @exception NoSuchAlgorithmException if the appropriate data integrity
311 * algorithm could not be found
312 * @exception CertificateException if any of the certificates included in
313 * the keystore data could not be stored
314 *
315 * @since 1.5
316 */
317 public void engineStore(KeyStore.LoadStoreParameter param)
318 throws IOException, NoSuchAlgorithmException,
319 CertificateException {
320 throw new UnsupportedOperationException();
321 }
322
323 /**
324 * Loads the keystore from the given input stream.
325 *
326 * <p>A password may be given to unlock the keystore
327 * (e.g. the keystore resides on a hardware token device),
328 * or to check the integrity of the keystore data.
329 * If a password is not given for integrity checking,
330 * then integrity checking is not performed.
331 *
332 * @param stream the input stream from which the keystore is loaded,
333 * or <code>null</code>
334 * @param password the password used to check the integrity of
335 * the keystore, the password used to unlock the keystore,
336 * or <code>null</code>
337 *
338 * @exception IOException if there is an I/O or format problem with the
339 * keystore data, if a password is required but not given,
340 * or if the given password was incorrect. If the error is due to a
341 * wrong password, the {@link Throwable#getCause cause} of the
342 * <code>IOException</code> should be an
343 * <code>UnrecoverableKeyException</code>
344 * @exception NoSuchAlgorithmException if the algorithm used to check
345 * the integrity of the keystore cannot be found
346 * @exception CertificateException if any of the certificates in the
347 * keystore could not be loaded
348 */
349 public abstract void engineLoad(InputStream stream, char[] password)
350 throws IOException, NoSuchAlgorithmException, CertificateException;
351
352 /**
353 * Loads the keystore using the given
354 * <code>KeyStore.LoadStoreParameter</code>.
355 *
356 * <p> Note that if this KeyStore has already been loaded, it is
357 * reinitialized and loaded again from the given parameter.
358 *
359 * @param param the <code>KeyStore.LoadStoreParameter</code>
360 * that specifies how to load the keystore,
361 * which may be <code>null</code>
362 *
363 * @exception IllegalArgumentException if the given
364 * <code>KeyStore.LoadStoreParameter</code>
365 * input is not recognized
366 * @exception IOException if there is an I/O or format problem with the
367 * keystore data. If the error is due to an incorrect
368 * <code>ProtectionParameter</code> (e.g. wrong password)
369 * the {@link Throwable#getCause cause} of the
370 * <code>IOException</code> should be an
371 * <code>UnrecoverableKeyException</code>
372 * @exception NoSuchAlgorithmException if the algorithm used to check
373 * the integrity of the keystore cannot be found
374 * @exception CertificateException if any of the certificates in the
375 * keystore could not be loaded
376 *
377 * @since 1.5
378 */
379 public void engineLoad(KeyStore.LoadStoreParameter param)
380 throws IOException, NoSuchAlgorithmException,
381 CertificateException {
382
383 if (param == null) {
384 engineLoad((InputStream)null, (char[])null);
385 return;
386 }
387
388 if (param instanceof KeyStore.SimpleLoadStoreParameter) {
389 ProtectionParameter protection = param.getProtectionParameter();
390 char[] password;
391 if (protection instanceof PasswordProtection) {
392 password = ((PasswordProtection)protection).getPassword();
393 } else if (protection instanceof CallbackHandlerProtection) {
394 CallbackHandler handler =
395 ((CallbackHandlerProtection)protection).getCallbackHandler();
396 PasswordCallback callback =
397 new PasswordCallback("Password: ", false);
398 try {
399 handler.handle(new Callback[] {callback});
400 } catch (UnsupportedCallbackException e) {
401 throw new NoSuchAlgorithmException
402 ("Could not obtain password", e);
403 }
404 password = callback.getPassword();
405 callback.clearPassword();
406 if (password == null) {
407 throw new NoSuchAlgorithmException
408 ("No password provided");
409 }
410 } else {
411 throw new NoSuchAlgorithmException("ProtectionParameter must"
412 + " be PasswordProtection or CallbackHandlerProtection");
413 }
414 engineLoad(null, password);
415 return;
416 }
417
418 throw new UnsupportedOperationException();
419 }
420
421 /**
422 * Gets a <code>KeyStore.Entry</code> for the specified alias
423 * with the specified protection parameter.
424 *
425 * @param alias get the <code>KeyStore.Entry</code> for this alias
426 * @param protParam the <code>ProtectionParameter</code>
427 * used to protect the <code>Entry</code>,
428 * which may be <code>null</code>
429 *
430 * @return the <code>KeyStore.Entry</code> for the specified alias,
431 * or <code>null</code> if there is no such entry
432 *
433 * @exception KeyStoreException if the operation failed
434 * @exception NoSuchAlgorithmException if the algorithm for recovering the
435 * entry cannot be found
436 * @exception UnrecoverableEntryException if the specified
437 * <code>protParam</code> were insufficient or invalid
438 * @exception UnrecoverableKeyException if the entry is a
439 * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>
440 * and the specified <code>protParam</code> does not contain
441 * the information needed to recover the key (e.g. wrong password)
442 *
443 * @since 1.5
444 */
445 public KeyStore.Entry engineGetEntry(String alias,
446 KeyStore.ProtectionParameter protParam)
447 throws KeyStoreException, NoSuchAlgorithmException,
448 UnrecoverableEntryException {
449
450 if (!engineContainsAlias(alias)) {
451 return null;
452 }
453
454 if (protParam == null) {
455 if (engineIsCertificateEntry(alias)) {
456 return new KeyStore.TrustedCertificateEntry
457 (engineGetCertificate(alias));
458 } else {
459 throw new UnrecoverableKeyException
460 ("requested entry requires a password");
461 }
462 }
463
464 if (protParam instanceof KeyStore.PasswordProtection) {
465 if (engineIsCertificateEntry(alias)) {
466 throw new UnsupportedOperationException
467 ("trusted certificate entries are not password-protected");
468 } else if (engineIsKeyEntry(alias)) {
469 KeyStore.PasswordProtection pp =
470 (KeyStore.PasswordProtection)protParam;
471 char[] password = pp.getPassword();
472
473 Key key = engineGetKey(alias, password);
474 if (key instanceof PrivateKey) {
475 Certificate[] chain = engineGetCertificateChain(alias);
476 return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain);
477 } else if (key instanceof SecretKey) {
478 return new KeyStore.SecretKeyEntry((SecretKey)key);
479 }
480 }
481 }
482
483 throw new UnsupportedOperationException();
484 }
485
486 /**
487 * Saves a <code>KeyStore.Entry</code> under the specified alias.
488 * The specified protection parameter is used to protect the
489 * <code>Entry</code>.
490 *
491 * <p> If an entry already exists for the specified alias,
492 * it is overridden.
493 *
494 * @param alias save the <code>KeyStore.Entry</code> under this alias
495 * @param entry the <code>Entry</code> to save
496 * @param protParam the <code>ProtectionParameter</code>
497 * used to protect the <code>Entry</code>,
498 * which may be <code>null</code>
499 *
500 * @exception KeyStoreException if this operation fails
501 *
502 * @since 1.5
503 */
504 public void engineSetEntry(String alias, KeyStore.Entry entry,
505 KeyStore.ProtectionParameter protParam)
506 throws KeyStoreException {
507
508 // get password
509 if (protParam != null &&
510 !(protParam instanceof KeyStore.PasswordProtection)) {
511 throw new KeyStoreException("unsupported protection parameter");
512 }
513 KeyStore.PasswordProtection pProtect = null;
514 if (protParam != null) {
515 pProtect = (KeyStore.PasswordProtection)protParam;
516 }
517
518 // set entry
519 if (entry instanceof KeyStore.TrustedCertificateEntry) {
520 if (protParam != null && pProtect.getPassword() != null) {
521 // pre-1.5 style setCertificateEntry did not allow password
522 throw new KeyStoreException
523 ("trusted certificate entries are not password-protected");
524 } else {
525 KeyStore.TrustedCertificateEntry tce =
526 (KeyStore.TrustedCertificateEntry)entry;
527 engineSetCertificateEntry(alias, tce.getTrustedCertificate());
528 return;
529 }
530 } else if (entry instanceof KeyStore.PrivateKeyEntry) {
531 if (pProtect == null || pProtect.getPassword() == null) {
532 // pre-1.5 style setKeyEntry required password
533 throw new KeyStoreException
534 ("non-null password required to create PrivateKeyEntry");
535 } else {
536 engineSetKeyEntry
537 (alias,
538 ((KeyStore.PrivateKeyEntry)entry).getPrivateKey(),
539 pProtect.getPassword(),
540 ((KeyStore.PrivateKeyEntry)entry).getCertificateChain());
541 return;
542 }
543 } else if (entry instanceof KeyStore.SecretKeyEntry) {
544 if (pProtect == null || pProtect.getPassword() == null) {
545 // pre-1.5 style setKeyEntry required password
546 throw new KeyStoreException
547 ("non-null password required to create SecretKeyEntry");
548 } else {
549 engineSetKeyEntry
550 (alias,
551 ((KeyStore.SecretKeyEntry)entry).getSecretKey(),
552 pProtect.getPassword(),
553 (Certificate[])null);
554 return;
555 }
556 }
557
558 throw new KeyStoreException
559 ("unsupported entry type: " + entry.getClass().getName());
560 }
561
562 /**
563 * Determines if the keystore <code>Entry</code> for the specified
564 * <code>alias</code> is an instance or subclass of the specified
565 * <code>entryClass</code>.
566 *
567 * @param alias the alias name
568 * @param entryClass the entry class
569 *
570 * @return true if the keystore <code>Entry</code> for the specified
571 * <code>alias</code> is an instance or subclass of the
572 * specified <code>entryClass</code>, false otherwise
573 *
574 * @since 1.5
575 */
576 public boolean
577 engineEntryInstanceOf(String alias,
578 Class<? extends KeyStore.Entry> entryClass)
579 {
580 if (entryClass == KeyStore.TrustedCertificateEntry.class) {
581 return engineIsCertificateEntry(alias);
582 }
583 if (entryClass == KeyStore.PrivateKeyEntry.class) {
584 return engineIsKeyEntry(alias) &&
585 engineGetCertificate(alias) != null;
586 }
587 if (entryClass == KeyStore.SecretKeyEntry.class) {
588 return engineIsKeyEntry(alias) &&
589 engineGetCertificate(alias) == null;
590 }
591 return false;
592 }
593}