1 /*
2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.security;
27 
28 import java.io.*;
29 import java.security.cert.Certificate;
30 import java.security.cert.X509Certificate;
31 import java.security.cert.CertificateException;
32 import java.security.spec.AlgorithmParameterSpec;
33 import java.util.*;
34 import javax.crypto.SecretKey;
35 
36 import javax.security.auth.DestroyFailedException;
37 import javax.security.auth.callback.*;
38 
39 import sun.security.util.Debug;
40 
41 /**
42  * This class represents a storage facility for cryptographic
43  * keys and certificates.
44  *
45  * <p> A {@code KeyStore} manages different types of entries.
46  * Each type of entry implements the {@code KeyStore.Entry} interface.
47  * Three basic {@code KeyStore.Entry} implementations are provided:
48  *
49  * <ul>
50  * <li><b>KeyStore.PrivateKeyEntry</b>
51  * <p> This type of entry holds a cryptographic {@code PrivateKey},
52  * which is optionally stored in a protected format to prevent
53  * unauthorized access.  It is also accompanied by a certificate chain
54  * for the corresponding public key.
55  *
56  * <p> Private keys and certificate chains are used by a given entity for
57  * self-authentication. Applications for this authentication include software
58  * distribution organizations which sign JAR files as part of releasing
59  * and/or licensing software.
60  *
61  * <li><b>KeyStore.SecretKeyEntry</b>
62  * <p> This type of entry holds a cryptographic {@code SecretKey},
63  * which is optionally stored in a protected format to prevent
64  * unauthorized access.
65  *
66  * <li><b>KeyStore.TrustedCertificateEntry</b>
67  * <p> This type of entry contains a single public key {@code Certificate}
68  * belonging to another party. It is called a <i>trusted certificate</i>
69  * because the keystore owner trusts that the public key in the certificate
70  * indeed belongs to the identity identified by the <i>subject</i> (owner)
71  * of the certificate.
72  *
73  * <p>This type of entry can be used to authenticate other parties.
74  * </ul>
75  *
76  * <p> Each entry in a keystore is identified by an "alias" string. In the
77  * case of private keys and their associated certificate chains, these strings
78  * distinguish among the different ways in which the entity may authenticate
79  * itself. For example, the entity may authenticate itself using different
80  * certificate authorities, or using different public key algorithms.
81  *
82  * <p> Whether aliases are case sensitive is implementation dependent. In order
83  * to avoid problems, it is recommended not to use aliases in a KeyStore that
84  * only differ in case.
85  *
86  * <p> Whether keystores are persistent, and the mechanisms used by the
87  * keystore if it is persistent, are not specified here. This allows
88  * use of a variety of techniques for protecting sensitive (e.g., private or
89  * secret) keys. Smart cards or other integrated cryptographic engines
90  * (SafeKeyper) are one option, and simpler mechanisms such as files may also
91  * be used (in a variety of formats).
92  *
93  * <p> Typical ways to request a KeyStore object include
94  * specifying an existing keystore file,
95  * relying on the default type and providing a specific keystore type.
96  *
97  * <ul>
98  * <li>To specify an existing keystore file:
99  * <pre>
100  *    // get keystore password
101  *    char[] password = getPassword();
102  *
103  *    // probe the keystore file and load the keystore entries
104  *    KeyStore ks = KeyStore.getInstance(new File("keyStoreName"), password);
105  *</pre>
106  * The system will probe the specified file to determine its keystore type
107  * and return a keystore implementation with its entries already loaded.
108  * When this approach is used there is no need to call the keystore's
109  * {@link #load(java.io.InputStream, char[]) load} method.
110  *
111  * <li>To rely on the default type:
112  * <pre>
113  *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
114  * </pre>
115  * The system will return a keystore implementation for the default type.
116  *
117  * <li>To provide a specific keystore type:
118  * <pre>
119  *      KeyStore ks = KeyStore.getInstance("JKS");
120  * </pre>
121  * The system will return the most preferred implementation of the
122  * specified keystore type available in the environment.
123  * </ul>
124  *
125  * <p> Before a keystore can be accessed, it must be
126  * {@link #load(java.io.InputStream, char[]) loaded}
127  * (unless it was already loaded during instantiation).
128  * <pre>
129  *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
130  *
131  *    // get user password and file input stream
132  *    char[] password = getPassword();
133  *
134  *    try (FileInputStream fis = new FileInputStream("keyStoreName")) {
135  *        ks.load(fis, password);
136  *    }
137  * </pre>
138  *
139  * To create an empty keystore using the above {@code load} method,
140  * pass {@code null} as the {@code InputStream} argument.
141  *
142  * <p> Once the keystore has been loaded, it is possible
143  * to read existing entries from the keystore, or to write new entries
144  * into the keystore:
145  * <pre>
146  *    KeyStore.ProtectionParameter protParam =
147  *        new KeyStore.PasswordProtection(password);
148  *
149  *    // get my private key
150  *    KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
151  *        ks.getEntry("privateKeyAlias", protParam);
152  *    PrivateKey myPrivateKey = pkEntry.getPrivateKey();
153  *
154  *    // save my secret key
155  *    javax.crypto.SecretKey mySecretKey;
156  *    KeyStore.SecretKeyEntry skEntry =
157  *        new KeyStore.SecretKeyEntry(mySecretKey);
158  *    ks.setEntry("secretKeyAlias", skEntry, protParam);
159  *
160  *    // store away the keystore
161  *    try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {
162  *        ks.store(fos, password);
163  *    }
164  * </pre>
165  *
166  * Note that although the same password may be used to
167  * load the keystore, to protect the private key entry,
168  * to protect the secret key entry, and to store the keystore
169  * (as is shown in the sample code above),
170  * different passwords or other protection parameters
171  * may also be used.
172  *
173  * <p> Every implementation of the Java platform is required to support
174  * the following standard {@code KeyStore} type:
175  * <ul>
176  * <li>{@code PKCS12}</li>
177  * </ul>
178  * This type is described in the <a href=
179  * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
180  * KeyStore section</a> of the
181  * Java Security Standard Algorithm Names Specification.
182  * Consult the release documentation for your implementation to see if any
183  * other types are supported.
184  *
185  * @author Jan Luehe
186  *
187  * @see java.security.PrivateKey
188  * @see javax.crypto.SecretKey
189  * @see java.security.cert.Certificate
190  *
191  * @since 1.2
192  */
193 
194 public class KeyStore {
195 
196     private static final Debug kdebug = Debug.getInstance("keystore");
197     private static final Debug pdebug =
198                         Debug.getInstance("provider", "Provider");
199     private static final boolean skipDebug =
200         Debug.isOn("engine=") && !Debug.isOn("keystore");
201 
202     /*
203      * Constant to lookup in the Security properties file to determine
204      * the default keystore type.
205      * In the Security properties file, the default keystore type is given as:
206      * <pre>
207      * keystore.type=jks
208      * </pre>
209      */
210     private static final String KEYSTORE_TYPE = "keystore.type";
211 
212     // The keystore type
213     private String type;
214 
215     // The provider
216     private Provider provider;
217 
218     // The provider implementation
219     private KeyStoreSpi keyStoreSpi;
220 
221     // Has this keystore been initialized (loaded)?
222     private boolean initialized = false;
223 
224     /**
225      * A marker interface for {@code KeyStore}
226      * {@link #load(KeyStore.LoadStoreParameter) load}
227      * and
228      * {@link #store(KeyStore.LoadStoreParameter) store}
229      * parameters.
230      *
231      * @since 1.5
232      */
233     public static interface LoadStoreParameter {
234         /**
235          * Gets the parameter used to protect keystore data.
236          *
237          * @return the parameter used to protect keystore data, or null
238          */
getProtectionParameter()239         public ProtectionParameter getProtectionParameter();
240     }
241 
242     /**
243      * A marker interface for keystore protection parameters.
244      *
245      * <p> The information stored in a {@code ProtectionParameter}
246      * object protects the contents of a keystore.
247      * For example, protection parameters may be used to check
248      * the integrity of keystore data, or to protect the
249      * confidentiality of sensitive keystore data
250      * (such as a {@code PrivateKey}).
251      *
252      * @since 1.5
253      */
254     public static interface ProtectionParameter { }
255 
256     /**
257      * A password-based implementation of {@code ProtectionParameter}.
258      *
259      * @since 1.5
260      */
261     public static class PasswordProtection implements
262                 ProtectionParameter, javax.security.auth.Destroyable {
263 
264         private final char[] password;
265         private final String protectionAlgorithm;
266         private final AlgorithmParameterSpec protectionParameters;
267         private volatile boolean destroyed = false;
268 
269         /**
270          * Creates a password parameter.
271          *
272          * <p> The specified {@code password} is cloned before it is stored
273          * in the new {@code PasswordProtection} object.
274          *
275          * @param password the password, which may be {@code null}
276          */
PasswordProtection(char[] password)277         public PasswordProtection(char[] password) {
278             this.password = (password == null) ? null : password.clone();
279             this.protectionAlgorithm = null;
280             this.protectionParameters = null;
281         }
282 
283         /**
284          * Creates a password parameter and specifies the protection algorithm
285          * and associated parameters to use when encrypting a keystore entry.
286          * <p>
287          * The specified {@code password} is cloned before it is stored in the
288          * new {@code PasswordProtection} object.
289          *
290          * @param password the password, which may be {@code null}
291          * @param protectionAlgorithm the encryption algorithm name, for
292          *     example, {@code PBEWithHmacSHA256AndAES_256}.
293          *     See the Cipher section in the <a href=
294          * "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">
295          * Java Security Standard Algorithm Names Specification</a>
296          *     for information about standard encryption algorithm names.
297          * @param protectionParameters the encryption algorithm parameter
298          *     specification, which may be {@code null}
299          * @exception NullPointerException if {@code protectionAlgorithm} is
300          *     {@code null}
301          *
302          * @since 1.8
303          */
PasswordProtection(char[] password, String protectionAlgorithm, AlgorithmParameterSpec protectionParameters)304         public PasswordProtection(char[] password, String protectionAlgorithm,
305             AlgorithmParameterSpec protectionParameters) {
306             if (protectionAlgorithm == null) {
307                 throw new NullPointerException("invalid null input");
308             }
309             this.password = (password == null) ? null : password.clone();
310             this.protectionAlgorithm = protectionAlgorithm;
311             this.protectionParameters = protectionParameters;
312         }
313 
314         /**
315          * Gets the name of the protection algorithm.
316          * If none was set then the keystore provider will use its default
317          * protection algorithm. The name of the default protection algorithm
318          * for a given keystore type is set using the
319          * {@code 'keystore.<type>.keyProtectionAlgorithm'} security property.
320          * For example, the
321          * {@code keystore.PKCS12.keyProtectionAlgorithm} property stores the
322          * name of the default key protection algorithm used for PKCS12
323          * keystores. If the security property is not set, an
324          * implementation-specific algorithm will be used.
325          *
326          * @return the algorithm name, or {@code null} if none was set
327          *
328          * @since 1.8
329          */
getProtectionAlgorithm()330         public String getProtectionAlgorithm() {
331             return protectionAlgorithm;
332         }
333 
334         /**
335          * Gets the parameters supplied for the protection algorithm.
336          *
337          * @return the algorithm parameter specification, or {@code  null},
338          *     if none was set
339          *
340          * @since 1.8
341          */
getProtectionParameters()342         public AlgorithmParameterSpec getProtectionParameters() {
343             return protectionParameters;
344         }
345 
346         /**
347          * Gets the password.
348          *
349          * <p>Note that this method returns a reference to the password.
350          * If a clone of the array is created it is the caller's
351          * responsibility to zero out the password information
352          * after it is no longer needed.
353          *
354          * @see #destroy()
355          * @return the password, which may be {@code null}
356          * @exception IllegalStateException if the password has
357          *              been cleared (destroyed)
358          */
getPassword()359         public synchronized char[] getPassword() {
360             if (destroyed) {
361                 throw new IllegalStateException("password has been cleared");
362             }
363             return password;
364         }
365 
366         /**
367          * Clears the password.
368          *
369          * @exception DestroyFailedException if this method was unable
370          *      to clear the password
371          */
destroy()372         public synchronized void destroy() throws DestroyFailedException {
373             destroyed = true;
374             if (password != null) {
375                 Arrays.fill(password, ' ');
376             }
377         }
378 
379         /**
380          * Determines if password has been cleared.
381          *
382          * @return true if the password has been cleared, false otherwise
383          */
isDestroyed()384         public synchronized boolean isDestroyed() {
385             return destroyed;
386         }
387     }
388 
389     /**
390      * A ProtectionParameter encapsulating a CallbackHandler.
391      *
392      * @since 1.5
393      */
394     public static class CallbackHandlerProtection
395             implements ProtectionParameter {
396 
397         private final CallbackHandler handler;
398 
399         /**
400          * Constructs a new CallbackHandlerProtection from a
401          * CallbackHandler.
402          *
403          * @param handler the CallbackHandler
404          * @exception NullPointerException if handler is null
405          */
CallbackHandlerProtection(CallbackHandler handler)406         public CallbackHandlerProtection(CallbackHandler handler) {
407             if (handler == null) {
408                 throw new NullPointerException("handler must not be null");
409             }
410             this.handler = handler;
411         }
412 
413         /**
414          * Returns the CallbackHandler.
415          *
416          * @return the CallbackHandler.
417          */
getCallbackHandler()418         public CallbackHandler getCallbackHandler() {
419             return handler;
420         }
421 
422     }
423 
424     /**
425      * A marker interface for {@code KeyStore} entry types.
426      *
427      * @since 1.5
428      */
429     public static interface Entry {
430 
431         /**
432          * Retrieves the attributes associated with an entry.
433          *
434          * @implSpec
435          * The default implementation returns an empty {@code Set}.
436          *
437          * @return an unmodifiable {@code Set} of attributes, possibly empty
438          *
439          * @since 1.8
440          */
getAttributes()441         public default Set<Attribute> getAttributes() {
442             return Collections.<Attribute>emptySet();
443         }
444 
445         /**
446          * An attribute associated with a keystore entry.
447          * It comprises a name and one or more values.
448          *
449          * @since 1.8
450          */
451         public interface Attribute {
452             /**
453              * Returns the attribute's name.
454              *
455              * @return the attribute name
456              */
getName()457             public String getName();
458 
459             /**
460              * Returns the attribute's value.
461              * Multi-valued attributes encode their values as a single string.
462              *
463              * @return the attribute value
464              */
getValue()465             public String getValue();
466         }
467     }
468 
469     /**
470      * A {@code KeyStore} entry that holds a {@code PrivateKey}
471      * and corresponding certificate chain.
472      *
473      * @since 1.5
474      */
475     public static final class PrivateKeyEntry implements Entry {
476 
477         private final PrivateKey privKey;
478         private final Certificate[] chain;
479         private final Set<Attribute> attributes;
480 
481         /**
482          * Constructs a {@code PrivateKeyEntry} with a
483          * {@code PrivateKey} and corresponding certificate chain.
484          *
485          * <p> The specified {@code chain} is cloned before it is stored
486          * in the new {@code PrivateKeyEntry} object.
487          *
488          * @param privateKey the {@code PrivateKey}
489          * @param chain an array of {@code Certificate}s
490          *      representing the certificate chain.
491          *      The chain must be ordered and contain a
492          *      {@code Certificate} at index 0
493          *      corresponding to the private key.
494          *
495          * @exception NullPointerException if
496          *      {@code privateKey} or {@code chain}
497          *      is {@code null}
498          * @exception IllegalArgumentException if the specified chain has a
499          *      length of 0, if the specified chain does not contain
500          *      {@code Certificate}s of the same type,
501          *      or if the {@code PrivateKey} algorithm
502          *      does not match the algorithm of the {@code PublicKey}
503          *      in the end entity {@code Certificate} (at index 0)
504          */
PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain)505         public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
506             this(privateKey, chain, Collections.<Attribute>emptySet());
507         }
508 
509         /**
510          * Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and
511          * corresponding certificate chain and associated entry attributes.
512          *
513          * <p> The specified {@code chain} and {@code attributes} are cloned
514          * before they are stored in the new {@code PrivateKeyEntry} object.
515          *
516          * @param privateKey the {@code PrivateKey}
517          * @param chain an array of {@code Certificate}s
518          *      representing the certificate chain.
519          *      The chain must be ordered and contain a
520          *      {@code Certificate} at index 0
521          *      corresponding to the private key.
522          * @param attributes the attributes
523          *
524          * @exception NullPointerException if {@code privateKey}, {@code chain}
525          *      or {@code attributes} is {@code null}
526          * @exception IllegalArgumentException if the specified chain has a
527          *      length of 0, if the specified chain does not contain
528          *      {@code Certificate}s of the same type,
529          *      or if the {@code PrivateKey} algorithm
530          *      does not match the algorithm of the {@code PublicKey}
531          *      in the end entity {@code Certificate} (at index 0)
532          *
533          * @since 1.8
534          */
PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain, Set<Attribute> attributes)535         public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,
536            Set<Attribute> attributes) {
537 
538             if (privateKey == null || chain == null || attributes == null) {
539                 throw new NullPointerException("invalid null input");
540             }
541             if (chain.length == 0) {
542                 throw new IllegalArgumentException
543                                 ("invalid zero-length input chain");
544             }
545 
546             Certificate[] clonedChain = chain.clone();
547             String certType = clonedChain[0].getType();
548             for (int i = 1; i < clonedChain.length; i++) {
549                 if (!certType.equals(clonedChain[i].getType())) {
550                     throw new IllegalArgumentException
551                                 ("chain does not contain certificates " +
552                                 "of the same type");
553                 }
554             }
555             if (!privateKey.getAlgorithm().equals
556                         (clonedChain[0].getPublicKey().getAlgorithm())) {
557                 throw new IllegalArgumentException
558                                 ("private key algorithm does not match " +
559                                 "algorithm of public key in end entity " +
560                                 "certificate (at index 0)");
561             }
562             this.privKey = privateKey;
563 
564             if (clonedChain[0] instanceof X509Certificate &&
565                 !(clonedChain instanceof X509Certificate[])) {
566 
567                 this.chain = new X509Certificate[clonedChain.length];
568                 System.arraycopy(clonedChain, 0,
569                                 this.chain, 0, clonedChain.length);
570             } else {
571                 this.chain = clonedChain;
572             }
573 
574             this.attributes =
575                 Collections.unmodifiableSet(new HashSet<>(attributes));
576         }
577 
578         /**
579          * Gets the {@code PrivateKey} from this entry.
580          *
581          * @return the {@code PrivateKey} from this entry
582          */
getPrivateKey()583         public PrivateKey getPrivateKey() {
584             return privKey;
585         }
586 
587         /**
588          * Gets the {@code Certificate} chain from this entry.
589          *
590          * <p> The stored chain is cloned before being returned.
591          *
592          * @return an array of {@code Certificate}s corresponding
593          *      to the certificate chain for the public key.
594          *      If the certificates are of type X.509,
595          *      the runtime type of the returned array is
596          *      {@code X509Certificate[]}.
597          */
getCertificateChain()598         public Certificate[] getCertificateChain() {
599             return chain.clone();
600         }
601 
602         /**
603          * Gets the end entity {@code Certificate}
604          * from the certificate chain in this entry.
605          *
606          * @return the end entity {@code Certificate} (at index 0)
607          *      from the certificate chain in this entry.
608          *      If the certificate is of type X.509,
609          *      the runtime type of the returned certificate is
610          *      {@code X509Certificate}.
611          */
getCertificate()612         public Certificate getCertificate() {
613             return chain[0];
614         }
615 
616         /**
617          * Retrieves the attributes associated with an entry.
618          *
619          * @return an unmodifiable {@code Set} of attributes, possibly empty
620          *
621          * @since 1.8
622          */
623         @Override
getAttributes()624         public Set<Attribute> getAttributes() {
625             return attributes;
626         }
627 
628         /**
629          * Returns a string representation of this PrivateKeyEntry.
630          * @return a string representation of this PrivateKeyEntry.
631          */
toString()632         public String toString() {
633             StringBuilder sb = new StringBuilder();
634             sb.append("Private key entry and certificate chain with "
635                 + chain.length + " elements:\r\n");
636             for (Certificate cert : chain) {
637                 sb.append(cert);
638                 sb.append("\r\n");
639             }
640             return sb.toString();
641         }
642 
643     }
644 
645     /**
646      * A {@code KeyStore} entry that holds a {@code SecretKey}.
647      *
648      * @since 1.5
649      */
650     public static final class SecretKeyEntry implements Entry {
651 
652         private final SecretKey sKey;
653         private final Set<Attribute> attributes;
654 
655         /**
656          * Constructs a {@code SecretKeyEntry} with a
657          * {@code SecretKey}.
658          *
659          * @param secretKey the {@code SecretKey}
660          *
661          * @exception NullPointerException if {@code secretKey}
662          *      is {@code null}
663          */
SecretKeyEntry(SecretKey secretKey)664         public SecretKeyEntry(SecretKey secretKey) {
665             if (secretKey == null) {
666                 throw new NullPointerException("invalid null input");
667             }
668             this.sKey = secretKey;
669             this.attributes = Collections.<Attribute>emptySet();
670         }
671 
672         /**
673          * Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and
674          * associated entry attributes.
675          *
676          * <p> The specified {@code attributes} is cloned before it is stored
677          * in the new {@code SecretKeyEntry} object.
678          *
679          * @param secretKey the {@code SecretKey}
680          * @param attributes the attributes
681          *
682          * @exception NullPointerException if {@code secretKey} or
683          *     {@code attributes} is {@code null}
684          *
685          * @since 1.8
686          */
SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes)687         public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) {
688 
689             if (secretKey == null || attributes == null) {
690                 throw new NullPointerException("invalid null input");
691             }
692             this.sKey = secretKey;
693             this.attributes =
694                 Collections.unmodifiableSet(new HashSet<>(attributes));
695         }
696 
697         /**
698          * Gets the {@code SecretKey} from this entry.
699          *
700          * @return the {@code SecretKey} from this entry
701          */
getSecretKey()702         public SecretKey getSecretKey() {
703             return sKey;
704         }
705 
706         /**
707          * Retrieves the attributes associated with an entry.
708          *
709          * @return an unmodifiable {@code Set} of attributes, possibly empty
710          *
711          * @since 1.8
712          */
713         @Override
getAttributes()714         public Set<Attribute> getAttributes() {
715             return attributes;
716         }
717 
718         /**
719          * Returns a string representation of this SecretKeyEntry.
720          * @return a string representation of this SecretKeyEntry.
721          */
toString()722         public String toString() {
723             return "Secret key entry with algorithm " + sKey.getAlgorithm();
724         }
725     }
726 
727     /**
728      * A {@code KeyStore} entry that holds a trusted
729      * {@code Certificate}.
730      *
731      * @since 1.5
732      */
733     public static final class TrustedCertificateEntry implements Entry {
734 
735         private final Certificate cert;
736         private final Set<Attribute> attributes;
737 
738         /**
739          * Constructs a {@code TrustedCertificateEntry} with a
740          * trusted {@code Certificate}.
741          *
742          * @param trustedCert the trusted {@code Certificate}
743          *
744          * @exception NullPointerException if
745          *      {@code trustedCert} is {@code null}
746          */
TrustedCertificateEntry(Certificate trustedCert)747         public TrustedCertificateEntry(Certificate trustedCert) {
748             if (trustedCert == null) {
749                 throw new NullPointerException("invalid null input");
750             }
751             this.cert = trustedCert;
752             this.attributes = Collections.<Attribute>emptySet();
753         }
754 
755         /**
756          * Constructs a {@code TrustedCertificateEntry} with a
757          * trusted {@code Certificate} and associated entry attributes.
758          *
759          * <p> The specified {@code attributes} is cloned before it is stored
760          * in the new {@code TrustedCertificateEntry} object.
761          *
762          * @param trustedCert the trusted {@code Certificate}
763          * @param attributes the attributes
764          *
765          * @exception NullPointerException if {@code trustedCert} or
766          *     {@code attributes} is {@code null}
767          *
768          * @since 1.8
769          */
TrustedCertificateEntry(Certificate trustedCert, Set<Attribute> attributes)770         public TrustedCertificateEntry(Certificate trustedCert,
771            Set<Attribute> attributes) {
772             if (trustedCert == null || attributes == null) {
773                 throw new NullPointerException("invalid null input");
774             }
775             this.cert = trustedCert;
776             this.attributes =
777                 Collections.unmodifiableSet(new HashSet<>(attributes));
778         }
779 
780         /**
781          * Gets the trusted {@code Certficate} from this entry.
782          *
783          * @return the trusted {@code Certificate} from this entry
784          */
getTrustedCertificate()785         public Certificate getTrustedCertificate() {
786             return cert;
787         }
788 
789         /**
790          * Retrieves the attributes associated with an entry.
791          *
792          * @return an unmodifiable {@code Set} of attributes, possibly empty
793          *
794          * @since 1.8
795          */
796         @Override
getAttributes()797         public Set<Attribute> getAttributes() {
798             return attributes;
799         }
800 
801         /**
802          * Returns a string representation of this TrustedCertificateEntry.
803          * @return a string representation of this TrustedCertificateEntry.
804          */
toString()805         public String toString() {
806             return "Trusted certificate entry:\r\n" + cert.toString();
807         }
808     }
809 
810     /**
811      * Creates a KeyStore object of the given type, and encapsulates the given
812      * provider implementation (SPI object) in it.
813      *
814      * @param keyStoreSpi the provider implementation.
815      * @param provider the provider.
816      * @param type the keystore type.
817      */
KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)818     protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
819     {
820         this.keyStoreSpi = keyStoreSpi;
821         this.provider = provider;
822         this.type = type;
823 
824         if (!skipDebug && pdebug != null) {
825             pdebug.println("KeyStore." + type.toUpperCase() + " type from: " +
826                 getProviderName());
827         }
828     }
829 
getProviderName()830     private String getProviderName() {
831         return (provider == null) ? "(no provider)" : provider.getName();
832     }
833 
834     /**
835      * Returns a keystore object of the specified type.
836      *
837      * <p> This method traverses the list of registered security Providers,
838      * starting with the most preferred Provider.
839      * A new KeyStore object encapsulating the
840      * KeyStoreSpi implementation from the first
841      * Provider that supports the specified type is returned.
842      *
843      * <p> Note that the list of registered providers may be retrieved via
844      * the {@link Security#getProviders() Security.getProviders()} method.
845      *
846      * @implNote
847      * The JDK Reference Implementation additionally uses the
848      * {@code jdk.security.provider.preferred}
849      * {@link Security#getProperty(String) Security} property to determine
850      * the preferred provider order for the specified algorithm. This
851      * may be different than the order of providers returned by
852      * {@link Security#getProviders() Security.getProviders()}.
853      *
854      * @param type the type of keystore.
855      * See the KeyStore section in the <a href=
856      * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
857      * Java Security Standard Algorithm Names Specification</a>
858      * for information about standard keystore types.
859      *
860      * @return a keystore object of the specified type
861      *
862      * @throws KeyStoreException if no {@code Provider} supports a
863      *         {@code KeyStoreSpi} implementation for the
864      *         specified type
865      *
866      * @throws NullPointerException if {@code type} is {@code null}
867      *
868      * @see Provider
869      */
getInstance(String type)870     public static KeyStore getInstance(String type)
871         throws KeyStoreException
872     {
873         Objects.requireNonNull(type, "null type name");
874         try {
875             Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
876             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
877         } catch (NoSuchAlgorithmException nsae) {
878             throw new KeyStoreException(type + " not found", nsae);
879         } catch (NoSuchProviderException nspe) {
880             throw new KeyStoreException(type + " not found", nspe);
881         }
882     }
883 
884     /**
885      * Returns a keystore object of the specified type.
886      *
887      * <p> A new KeyStore object encapsulating the
888      * KeyStoreSpi implementation from the specified provider
889      * is returned.  The specified provider must be registered
890      * in the security provider list.
891      *
892      * <p> Note that the list of registered providers may be retrieved via
893      * the {@link Security#getProviders() Security.getProviders()} method.
894      *
895      * @param type the type of keystore.
896      * See the KeyStore section in the <a href=
897      * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
898      * Java Security Standard Algorithm Names Specification</a>
899      * for information about standard keystore types.
900      *
901      * @param provider the name of the provider.
902      *
903      * @return a keystore object of the specified type
904      *
905      * @throws IllegalArgumentException if the provider name is {@code null}
906      *         or empty
907      *
908      * @throws KeyStoreException if a {@code KeyStoreSpi}
909      *         implementation for the specified type is not
910      *         available from the specified provider
911      *
912      * @throws NoSuchProviderException if the specified provider is not
913      *         registered in the security provider list
914      *
915      * @throws NullPointerException if {@code type} is {@code null}
916      *
917      * @see Provider
918      */
getInstance(String type, String provider)919     public static KeyStore getInstance(String type, String provider)
920         throws KeyStoreException, NoSuchProviderException
921     {
922         Objects.requireNonNull(type, "null type name");
923         if (provider == null || provider.isEmpty())
924             throw new IllegalArgumentException("missing provider");
925         try {
926             Object[] objs = Security.getImpl(type, "KeyStore", provider);
927             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
928         } catch (NoSuchAlgorithmException nsae) {
929             throw new KeyStoreException(type + " not found", nsae);
930         }
931     }
932 
933     /**
934      * Returns a keystore object of the specified type.
935      *
936      * <p> A new KeyStore object encapsulating the
937      * KeyStoreSpi implementation from the specified Provider
938      * object is returned.  Note that the specified Provider object
939      * does not have to be registered in the provider list.
940      *
941      * @param type the type of keystore.
942      * See the KeyStore section in the <a href=
943      * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
944      * Java Security Standard Algorithm Names Specification</a>
945      * for information about standard keystore types.
946      *
947      * @param provider the provider.
948      *
949      * @return a keystore object of the specified type
950      *
951      * @throws IllegalArgumentException if the specified provider is
952      *         {@code null}
953      *
954      * @throws KeyStoreException if {@code KeyStoreSpi}
955      *         implementation for the specified type is not available
956      *         from the specified {@code Provider} object
957      *
958      * @throws NullPointerException if {@code type} is {@code null}
959      *
960      * @see Provider
961      *
962      * @since 1.4
963      */
getInstance(String type, Provider provider)964     public static KeyStore getInstance(String type, Provider provider)
965         throws KeyStoreException
966     {
967         Objects.requireNonNull(type, "null type name");
968         if (provider == null)
969             throw new IllegalArgumentException("missing provider");
970         try {
971             Object[] objs = Security.getImpl(type, "KeyStore", provider);
972             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
973         } catch (NoSuchAlgorithmException nsae) {
974             throw new KeyStoreException(type + " not found", nsae);
975         }
976     }
977 
978     /**
979      * Returns the default keystore type as specified by the
980      * {@code keystore.type} security property, or the string
981      * {@literal "jks"} (acronym for {@literal "Java keystore"})
982      * if no such property exists.
983      *
984      * <p>The default keystore type can be used by applications that do not
985      * want to use a hard-coded keystore type when calling one of the
986      * {@code getInstance} methods, and want to provide a default keystore
987      * type in case a user does not specify its own.
988      *
989      * <p>The default keystore type can be changed by setting the value of the
990      * {@code keystore.type} security property to the desired keystore type.
991      *
992      * @return the default keystore type as specified by the
993      * {@code keystore.type} security property, or the string {@literal "jks"}
994      * if no such property exists.
995      * @see java.security.Security security properties
996      */
getDefaultType()997     public static final String getDefaultType() {
998         String kstype;
999         kstype = AccessController.doPrivileged(new PrivilegedAction<>() {
1000             public String run() {
1001                 return Security.getProperty(KEYSTORE_TYPE);
1002             }
1003         });
1004         if (kstype == null) {
1005             kstype = "jks";
1006         }
1007         return kstype;
1008     }
1009 
1010     /**
1011      * Returns the provider of this keystore.
1012      *
1013      * @return the provider of this keystore.
1014      */
getProvider()1015     public final Provider getProvider()
1016     {
1017         return this.provider;
1018     }
1019 
1020     /**
1021      * Returns the type of this keystore.
1022      *
1023      * @return the type of this keystore.
1024      */
getType()1025     public final String getType()
1026     {
1027         return this.type;
1028     }
1029 
1030     /**
1031      * Returns the key associated with the given alias, using the given
1032      * password to recover it.  The key must have been associated with
1033      * the alias by a call to {@code setKeyEntry},
1034      * or by a call to {@code setEntry} with a
1035      * {@code PrivateKeyEntry} or {@code SecretKeyEntry}.
1036      *
1037      * @param alias the alias name
1038      * @param password the password for recovering the key
1039      *
1040      * @return the requested key, or null if the given alias does not exist
1041      * or does not identify a key-related entry.
1042      *
1043      * @exception KeyStoreException if the keystore has not been initialized
1044      * (loaded).
1045      * @exception NoSuchAlgorithmException if the algorithm for recovering the
1046      * key cannot be found
1047      * @exception UnrecoverableKeyException if the key cannot be recovered
1048      * (e.g., the given password is wrong).
1049      */
getKey(String alias, char[] password)1050     public final Key getKey(String alias, char[] password)
1051         throws KeyStoreException, NoSuchAlgorithmException,
1052             UnrecoverableKeyException
1053     {
1054         if (!initialized) {
1055             throw new KeyStoreException("Uninitialized keystore");
1056         }
1057         return keyStoreSpi.engineGetKey(alias, password);
1058     }
1059 
1060     /**
1061      * Returns the certificate chain associated with the given alias.
1062      * The certificate chain must have been associated with the alias
1063      * by a call to {@code setKeyEntry},
1064      * or by a call to {@code setEntry} with a
1065      * {@code PrivateKeyEntry}.
1066      *
1067      * @param alias the alias name
1068      *
1069      * @return the certificate chain (ordered with the user's certificate first
1070      * followed by zero or more certificate authorities), or null if the given alias
1071      * does not exist or does not contain a certificate chain
1072      *
1073      * @exception KeyStoreException if the keystore has not been initialized
1074      * (loaded).
1075      */
getCertificateChain(String alias)1076     public final Certificate[] getCertificateChain(String alias)
1077         throws KeyStoreException
1078     {
1079         if (!initialized) {
1080             throw new KeyStoreException("Uninitialized keystore");
1081         }
1082         return keyStoreSpi.engineGetCertificateChain(alias);
1083     }
1084 
1085     /**
1086      * Returns the certificate associated with the given alias.
1087      *
1088      * <p> If the given alias name identifies an entry
1089      * created by a call to {@code setCertificateEntry},
1090      * or created by a call to {@code setEntry} with a
1091      * {@code TrustedCertificateEntry},
1092      * then the trusted certificate contained in that entry is returned.
1093      *
1094      * <p> If the given alias name identifies an entry
1095      * created by a call to {@code setKeyEntry},
1096      * or created by a call to {@code setEntry} with a
1097      * {@code PrivateKeyEntry},
1098      * then the first element of the certificate chain in that entry
1099      * is returned.
1100      *
1101      * @param alias the alias name
1102      *
1103      * @return the certificate, or null if the given alias does not exist or
1104      * does not contain a certificate.
1105      *
1106      * @exception KeyStoreException if the keystore has not been initialized
1107      * (loaded).
1108      */
getCertificate(String alias)1109     public final Certificate getCertificate(String alias)
1110         throws KeyStoreException
1111     {
1112         if (!initialized) {
1113             throw new KeyStoreException("Uninitialized keystore");
1114         }
1115         return keyStoreSpi.engineGetCertificate(alias);
1116     }
1117 
1118     /**
1119      * Returns the creation date of the entry identified by the given alias.
1120      *
1121      * @param alias the alias name
1122      *
1123      * @return the creation date of this entry, or null if the given alias does
1124      * not exist
1125      *
1126      * @exception KeyStoreException if the keystore has not been initialized
1127      * (loaded).
1128      */
getCreationDate(String alias)1129     public final Date getCreationDate(String alias)
1130         throws KeyStoreException
1131     {
1132         if (!initialized) {
1133             throw new KeyStoreException("Uninitialized keystore");
1134         }
1135         return keyStoreSpi.engineGetCreationDate(alias);
1136     }
1137 
1138     /**
1139      * Assigns the given key to the given alias, protecting it with the given
1140      * password.
1141      *
1142      * <p>If the given key is of type {@code java.security.PrivateKey},
1143      * it must be accompanied by a certificate chain certifying the
1144      * corresponding public key.
1145      *
1146      * <p>If the given alias already exists, the keystore information
1147      * associated with it is overridden by the given key (and possibly
1148      * certificate chain).
1149      *
1150      * @param alias the alias name
1151      * @param key the key to be associated with the alias
1152      * @param password the password to protect the key
1153      * @param chain the certificate chain for the corresponding public
1154      * key (only required if the given key is of type
1155      * {@code java.security.PrivateKey}).
1156      *
1157      * @exception KeyStoreException if the keystore has not been initialized
1158      * (loaded), the given key cannot be protected, or this operation fails
1159      * for some other reason
1160      */
setKeyEntry(String alias, Key key, char[] password, Certificate[] chain)1161     public final void setKeyEntry(String alias, Key key, char[] password,
1162                                   Certificate[] chain)
1163         throws KeyStoreException
1164     {
1165         if (!initialized) {
1166             throw new KeyStoreException("Uninitialized keystore");
1167         }
1168         if ((key instanceof PrivateKey) &&
1169             (chain == null || chain.length == 0)) {
1170             throw new IllegalArgumentException("Private key must be "
1171                                                + "accompanied by certificate "
1172                                                + "chain");
1173         }
1174         keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
1175     }
1176 
1177     /**
1178      * Assigns the given key (that has already been protected) to the given
1179      * alias.
1180      *
1181      * <p>If the protected key is of type
1182      * {@code java.security.PrivateKey}, it must be accompanied by a
1183      * certificate chain certifying the corresponding public key. If the
1184      * underlying keystore implementation is of type {@code jks},
1185      * {@code key} must be encoded as an
1186      * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard.
1187      *
1188      * <p>If the given alias already exists, the keystore information
1189      * associated with it is overridden by the given key (and possibly
1190      * certificate chain).
1191      *
1192      * @param alias the alias name
1193      * @param key the key (in protected format) to be associated with the alias
1194      * @param chain the certificate chain for the corresponding public
1195      *          key (only useful if the protected key is of type
1196      *          {@code java.security.PrivateKey}).
1197      *
1198      * @exception KeyStoreException if the keystore has not been initialized
1199      * (loaded), or if this operation fails for some other reason.
1200      */
setKeyEntry(String alias, byte[] key, Certificate[] chain)1201     public final void setKeyEntry(String alias, byte[] key,
1202                                   Certificate[] chain)
1203         throws KeyStoreException
1204     {
1205         if (!initialized) {
1206             throw new KeyStoreException("Uninitialized keystore");
1207         }
1208         keyStoreSpi.engineSetKeyEntry(alias, key, chain);
1209     }
1210 
1211     /**
1212      * Assigns the given trusted certificate to the given alias.
1213      *
1214      * <p> If the given alias identifies an existing entry
1215      * created by a call to {@code setCertificateEntry},
1216      * or created by a call to {@code setEntry} with a
1217      * {@code TrustedCertificateEntry},
1218      * the trusted certificate in the existing entry
1219      * is overridden by the given certificate.
1220      *
1221      * @param alias the alias name
1222      * @param cert the certificate
1223      *
1224      * @exception KeyStoreException if the keystore has not been initialized,
1225      * or the given alias already exists and does not identify an
1226      * entry containing a trusted certificate,
1227      * or this operation fails for some other reason.
1228      */
setCertificateEntry(String alias, Certificate cert)1229     public final void setCertificateEntry(String alias, Certificate cert)
1230         throws KeyStoreException
1231     {
1232         if (!initialized) {
1233             throw new KeyStoreException("Uninitialized keystore");
1234         }
1235         keyStoreSpi.engineSetCertificateEntry(alias, cert);
1236     }
1237 
1238     /**
1239      * Deletes the entry identified by the given alias from this keystore.
1240      *
1241      * @param alias the alias name
1242      *
1243      * @exception KeyStoreException if the keystore has not been initialized,
1244      * or if the entry cannot be removed.
1245      */
deleteEntry(String alias)1246     public final void deleteEntry(String alias)
1247         throws KeyStoreException
1248     {
1249         if (!initialized) {
1250             throw new KeyStoreException("Uninitialized keystore");
1251         }
1252         keyStoreSpi.engineDeleteEntry(alias);
1253     }
1254 
1255     /**
1256      * Lists all the alias names of this keystore.
1257      *
1258      * @return enumeration of the alias names
1259      *
1260      * @exception KeyStoreException if the keystore has not been initialized
1261      * (loaded).
1262      */
aliases()1263     public final Enumeration<String> aliases()
1264         throws KeyStoreException
1265     {
1266         if (!initialized) {
1267             throw new KeyStoreException("Uninitialized keystore");
1268         }
1269         return keyStoreSpi.engineAliases();
1270     }
1271 
1272     /**
1273      * Checks if the given alias exists in this keystore.
1274      *
1275      * @param alias the alias name
1276      *
1277      * @return true if the alias exists, false otherwise
1278      *
1279      * @exception KeyStoreException if the keystore has not been initialized
1280      * (loaded).
1281      */
containsAlias(String alias)1282     public final boolean containsAlias(String alias)
1283         throws KeyStoreException
1284     {
1285         if (!initialized) {
1286             throw new KeyStoreException("Uninitialized keystore");
1287         }
1288         return keyStoreSpi.engineContainsAlias(alias);
1289     }
1290 
1291     /**
1292      * Retrieves the number of entries in this keystore.
1293      *
1294      * @return the number of entries in this keystore
1295      *
1296      * @exception KeyStoreException if the keystore has not been initialized
1297      * (loaded).
1298      */
size()1299     public final int size()
1300         throws KeyStoreException
1301     {
1302         if (!initialized) {
1303             throw new KeyStoreException("Uninitialized keystore");
1304         }
1305         return keyStoreSpi.engineSize();
1306     }
1307 
1308     /**
1309      * Returns true if the entry identified by the given alias
1310      * was created by a call to {@code setKeyEntry},
1311      * or created by a call to {@code setEntry} with a
1312      * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.
1313      *
1314      * @param alias the alias for the keystore entry to be checked
1315      *
1316      * @return true if the entry identified by the given alias is a
1317      * key-related entry, false otherwise.
1318      *
1319      * @exception KeyStoreException if the keystore has not been initialized
1320      * (loaded).
1321      */
isKeyEntry(String alias)1322     public final boolean isKeyEntry(String alias)
1323         throws KeyStoreException
1324     {
1325         if (!initialized) {
1326             throw new KeyStoreException("Uninitialized keystore");
1327         }
1328         return keyStoreSpi.engineIsKeyEntry(alias);
1329     }
1330 
1331     /**
1332      * Returns true if the entry identified by the given alias
1333      * was created by a call to {@code setCertificateEntry},
1334      * or created by a call to {@code setEntry} with a
1335      * {@code TrustedCertificateEntry}.
1336      *
1337      * @param alias the alias for the keystore entry to be checked
1338      *
1339      * @return true if the entry identified by the given alias contains a
1340      * trusted certificate, false otherwise.
1341      *
1342      * @exception KeyStoreException if the keystore has not been initialized
1343      * (loaded).
1344      */
isCertificateEntry(String alias)1345     public final boolean isCertificateEntry(String alias)
1346         throws KeyStoreException
1347     {
1348         if (!initialized) {
1349             throw new KeyStoreException("Uninitialized keystore");
1350         }
1351         return keyStoreSpi.engineIsCertificateEntry(alias);
1352     }
1353 
1354     /**
1355      * Returns the (alias) name of the first keystore entry whose certificate
1356      * matches the given certificate.
1357      *
1358      * <p> This method attempts to match the given certificate with each
1359      * keystore entry. If the entry being considered was
1360      * created by a call to {@code setCertificateEntry},
1361      * or created by a call to {@code setEntry} with a
1362      * {@code TrustedCertificateEntry},
1363      * then the given certificate is compared to that entry's certificate.
1364      *
1365      * <p> If the entry being considered was
1366      * created by a call to {@code setKeyEntry},
1367      * or created by a call to {@code setEntry} with a
1368      * {@code PrivateKeyEntry},
1369      * then the given certificate is compared to the first
1370      * element of that entry's certificate chain.
1371      *
1372      * @param cert the certificate to match with.
1373      *
1374      * @return the alias name of the first entry with a matching certificate,
1375      * or null if no such entry exists in this keystore.
1376      *
1377      * @exception KeyStoreException if the keystore has not been initialized
1378      * (loaded).
1379      */
getCertificateAlias(Certificate cert)1380     public final String getCertificateAlias(Certificate cert)
1381         throws KeyStoreException
1382     {
1383         if (!initialized) {
1384             throw new KeyStoreException("Uninitialized keystore");
1385         }
1386         return keyStoreSpi.engineGetCertificateAlias(cert);
1387     }
1388 
1389     /**
1390      * Stores this keystore to the given output stream, and protects its
1391      * integrity with the given password.
1392      *
1393      * @param stream the output stream to which this keystore is written.
1394      * @param password the password to generate the keystore integrity check
1395      *
1396      * @exception KeyStoreException if the keystore has not been initialized
1397      * (loaded).
1398      * @exception IOException if there was an I/O problem with data
1399      * @exception NoSuchAlgorithmException if the appropriate data integrity
1400      * algorithm could not be found
1401      * @exception CertificateException if any of the certificates included in
1402      * the keystore data could not be stored
1403      */
store(OutputStream stream, char[] password)1404     public final void store(OutputStream stream, char[] password)
1405         throws KeyStoreException, IOException, NoSuchAlgorithmException,
1406             CertificateException
1407     {
1408         if (!initialized) {
1409             throw new KeyStoreException("Uninitialized keystore");
1410         }
1411         keyStoreSpi.engineStore(stream, password);
1412     }
1413 
1414     /**
1415      * Stores this keystore using the given {@code LoadStoreParameter}.
1416      *
1417      * @param param the {@code LoadStoreParameter}
1418      *          that specifies how to store the keystore,
1419      *          which may be {@code null}
1420      *
1421      * @exception IllegalArgumentException if the given
1422      *          {@code LoadStoreParameter}
1423      *          input is not recognized
1424      * @exception KeyStoreException if the keystore has not been initialized
1425      *          (loaded)
1426      * @exception IOException if there was an I/O problem with data
1427      * @exception NoSuchAlgorithmException if the appropriate data integrity
1428      *          algorithm could not be found
1429      * @exception CertificateException if any of the certificates included in
1430      *          the keystore data could not be stored
1431      *
1432      * @since 1.5
1433      */
store(LoadStoreParameter param)1434     public final void store(LoadStoreParameter param)
1435                 throws KeyStoreException, IOException,
1436                 NoSuchAlgorithmException, CertificateException {
1437         if (!initialized) {
1438             throw new KeyStoreException("Uninitialized keystore");
1439         }
1440         keyStoreSpi.engineStore(param);
1441     }
1442 
1443     /**
1444      * Loads this KeyStore from the given input stream.
1445      *
1446      * <p>A password may be given to unlock the keystore
1447      * (e.g. the keystore resides on a hardware token device),
1448      * or to check the integrity of the keystore data.
1449      * If a password is not given for integrity checking,
1450      * then integrity checking is not performed.
1451      *
1452      * <p>In order to create an empty keystore, or if the keystore cannot
1453      * be initialized from a stream, pass {@code null}
1454      * as the {@code stream} argument.
1455      *
1456      * <p> Note that if this keystore has already been loaded, it is
1457      * reinitialized and loaded again from the given input stream.
1458      *
1459      * @param stream the input stream from which the keystore is loaded,
1460      * or {@code null}
1461      * @param password the password used to check the integrity of
1462      * the keystore, the password used to unlock the keystore,
1463      * or {@code null}
1464      *
1465      * @exception IOException if there is an I/O or format problem with the
1466      * keystore data, if a password is required but not given,
1467      * or if the given password was incorrect. If the error is due to a
1468      * wrong password, the {@link Throwable#getCause cause} of the
1469      * {@code IOException} should be an
1470      * {@code UnrecoverableKeyException}
1471      * @exception NoSuchAlgorithmException if the algorithm used to check
1472      * the integrity of the keystore cannot be found
1473      * @exception CertificateException if any of the certificates in the
1474      * keystore could not be loaded
1475      */
load(InputStream stream, char[] password)1476     public final void load(InputStream stream, char[] password)
1477         throws IOException, NoSuchAlgorithmException, CertificateException
1478     {
1479         keyStoreSpi.engineLoad(stream, password);
1480         initialized = true;
1481     }
1482 
1483     /**
1484      * Loads this keystore using the given {@code LoadStoreParameter}.
1485      *
1486      * <p> Note that if this KeyStore has already been loaded, it is
1487      * reinitialized and loaded again from the given parameter.
1488      *
1489      * @param param the {@code LoadStoreParameter}
1490      *          that specifies how to load the keystore,
1491      *          which may be {@code null}
1492      *
1493      * @exception IllegalArgumentException if the given
1494      *          {@code LoadStoreParameter}
1495      *          input is not recognized
1496      * @exception IOException if there is an I/O or format problem with the
1497      *          keystore data. If the error is due to an incorrect
1498      *         {@code ProtectionParameter} (e.g. wrong password)
1499      *         the {@link Throwable#getCause cause} of the
1500      *         {@code IOException} should be an
1501      *         {@code UnrecoverableKeyException}
1502      * @exception NoSuchAlgorithmException if the algorithm used to check
1503      *          the integrity of the keystore cannot be found
1504      * @exception CertificateException if any of the certificates in the
1505      *          keystore could not be loaded
1506      *
1507      * @since 1.5
1508      */
load(LoadStoreParameter param)1509     public final void load(LoadStoreParameter param)
1510                 throws IOException, NoSuchAlgorithmException,
1511                 CertificateException {
1512 
1513         keyStoreSpi.engineLoad(param);
1514         initialized = true;
1515     }
1516 
1517     /**
1518      * Gets a keystore {@code Entry} for the specified alias
1519      * with the specified protection parameter.
1520      *
1521      * @param alias get the keystore {@code Entry} for this alias
1522      * @param protParam the {@code ProtectionParameter}
1523      *          used to protect the {@code Entry},
1524      *          which may be {@code null}
1525      *
1526      * @return the keystore {@code Entry} for the specified alias,
1527      *          or {@code null} if there is no such entry
1528      *
1529      * @exception NullPointerException if
1530      *          {@code alias} is {@code null}
1531      * @exception NoSuchAlgorithmException if the algorithm for recovering the
1532      *          entry cannot be found
1533      * @exception UnrecoverableEntryException if the specified
1534      *          {@code protParam} were insufficient or invalid
1535      * @exception UnrecoverableKeyException if the entry is a
1536      *          {@code PrivateKeyEntry} or {@code SecretKeyEntry}
1537      *          and the specified {@code protParam} does not contain
1538      *          the information needed to recover the key (e.g. wrong password)
1539      * @exception KeyStoreException if the keystore has not been initialized
1540      *          (loaded).
1541      * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
1542      *
1543      * @since 1.5
1544      */
getEntry(String alias, ProtectionParameter protParam)1545     public final Entry getEntry(String alias, ProtectionParameter protParam)
1546                 throws NoSuchAlgorithmException, UnrecoverableEntryException,
1547                 KeyStoreException {
1548 
1549         if (alias == null) {
1550             throw new NullPointerException("invalid null input");
1551         }
1552         if (!initialized) {
1553             throw new KeyStoreException("Uninitialized keystore");
1554         }
1555         return keyStoreSpi.engineGetEntry(alias, protParam);
1556     }
1557 
1558     /**
1559      * Saves a keystore {@code Entry} under the specified alias.
1560      * The protection parameter is used to protect the
1561      * {@code Entry}.
1562      *
1563      * <p> If an entry already exists for the specified alias,
1564      * it is overridden.
1565      *
1566      * @param alias save the keystore {@code Entry} under this alias
1567      * @param entry the {@code Entry} to save
1568      * @param protParam the {@code ProtectionParameter}
1569      *          used to protect the {@code Entry},
1570      *          which may be {@code null}
1571      *
1572      * @exception NullPointerException if
1573      *          {@code alias} or {@code entry}
1574      *          is {@code null}
1575      * @exception KeyStoreException if the keystore has not been initialized
1576      *          (loaded), or if this operation fails for some other reason
1577      *
1578      * @see #getEntry(String, KeyStore.ProtectionParameter)
1579      *
1580      * @since 1.5
1581      */
setEntry(String alias, Entry entry, ProtectionParameter protParam)1582     public final void setEntry(String alias, Entry entry,
1583                         ProtectionParameter protParam)
1584                 throws KeyStoreException {
1585         if (alias == null || entry == null) {
1586             throw new NullPointerException("invalid null input");
1587         }
1588         if (!initialized) {
1589             throw new KeyStoreException("Uninitialized keystore");
1590         }
1591         keyStoreSpi.engineSetEntry(alias, entry, protParam);
1592     }
1593 
1594     /**
1595      * Determines if the keystore {@code Entry} for the specified
1596      * {@code alias} is an instance or subclass of the specified
1597      * {@code entryClass}.
1598      *
1599      * @param alias the alias name
1600      * @param entryClass the entry class
1601      *
1602      * @return true if the keystore {@code Entry} for the specified
1603      *          {@code alias} is an instance or subclass of the
1604      *          specified {@code entryClass}, false otherwise
1605      *
1606      * @exception NullPointerException if
1607      *          {@code alias} or {@code entryClass}
1608      *          is {@code null}
1609      * @exception KeyStoreException if the keystore has not been
1610      *          initialized (loaded)
1611      *
1612      * @since 1.5
1613      */
1614     public final boolean
entryInstanceOf(String alias, Class<? extends KeyStore.Entry> entryClass)1615         entryInstanceOf(String alias,
1616                         Class<? extends KeyStore.Entry> entryClass)
1617         throws KeyStoreException
1618     {
1619 
1620         if (alias == null || entryClass == null) {
1621             throw new NullPointerException("invalid null input");
1622         }
1623         if (!initialized) {
1624             throw new KeyStoreException("Uninitialized keystore");
1625         }
1626         return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
1627     }
1628 
1629     /**
1630      * Returns a loaded keystore object of the appropriate keystore type.
1631      * First the keystore type is determined by probing the specified file.
1632      * Then a keystore object is instantiated and loaded using the data from
1633      * that file.
1634      *
1635      * <p>
1636      * A password may be given to unlock the keystore
1637      * (e.g. the keystore resides on a hardware token device),
1638      * or to check the integrity of the keystore data.
1639      * If a password is not given for integrity checking,
1640      * then integrity checking is not performed.
1641      *
1642      * <p>
1643      * This method traverses the list of registered security
1644      * {@linkplain Provider providers}, starting with the most
1645      * preferred Provider.
1646      * For each {@link KeyStoreSpi} implementation supported by a
1647      * Provider, it invokes the {@link
1648      * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
1649      * determine if it supports the specified keystore.
1650      * A new KeyStore object is returned that encapsulates the KeyStoreSpi
1651      * implementation from the first Provider that supports the specified file.
1652      *
1653      * <p> Note that the list of registered providers may be retrieved via
1654      * the {@link Security#getProviders() Security.getProviders()} method.
1655      *
1656      * @param  file the keystore file
1657      * @param  password the keystore password, which may be {@code null}
1658      *
1659      * @return a keystore object loaded with keystore data
1660      *
1661      * @throws KeyStoreException if no Provider supports a KeyStoreSpi
1662      *             implementation for the specified keystore file.
1663      * @throws IOException if there is an I/O or format problem with the
1664      *             keystore data, if a password is required but not given,
1665      *             or if the given password was incorrect. If the error is
1666      *             due to a wrong password, the {@link Throwable#getCause cause}
1667      *             of the {@code IOException} should be an
1668      *             {@code UnrecoverableKeyException}.
1669      * @throws NoSuchAlgorithmException if the algorithm used to check the
1670      *             integrity of the keystore cannot be found.
1671      * @throws CertificateException if any of the certificates in the
1672      *             keystore could not be loaded.
1673      * @throws IllegalArgumentException if file does not exist or does not
1674      *             refer to a normal file.
1675      * @throws NullPointerException if file is {@code null}.
1676      * @throws SecurityException if a security manager exists and its
1677      *             {@link java.lang.SecurityManager#checkRead} method denies
1678      *             read access to the specified file.
1679      *
1680      * @see Provider
1681      *
1682      * @since 9
1683      */
getInstance(File file, char[] password)1684     public static final KeyStore getInstance(File file, char[] password)
1685         throws KeyStoreException, IOException, NoSuchAlgorithmException,
1686             CertificateException {
1687         return getInstance(file, password, null, true);
1688     }
1689 
1690     /**
1691      * Returns a loaded keystore object of the appropriate keystore type.
1692      * First the keystore type is determined by probing the specified file.
1693      * Then a keystore object is instantiated and loaded using the data from
1694      * that file.
1695      * A {@code LoadStoreParameter} may be supplied which specifies how to
1696      * unlock the keystore data or perform an integrity check.
1697      *
1698      * <p>
1699      * This method traverses the list of registered security {@linkplain
1700      * Provider providers}, starting with the most preferred Provider.
1701      * For each {@link KeyStoreSpi} implementation supported by a
1702      * Provider, it invokes the {@link
1703      * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
1704      * determine if it supports the specified keystore.
1705      * A new KeyStore object is returned that encapsulates the KeyStoreSpi
1706      * implementation from the first Provider that supports the specified file.
1707      *
1708      * <p> Note that the list of registered providers may be retrieved via
1709      * the {@link Security#getProviders() Security.getProviders()} method.
1710      *
1711      * @param  file the keystore file
1712      * @param  param the {@code LoadStoreParameter} that specifies how to load
1713      *             the keystore, which may be {@code null}
1714      *
1715      * @return a keystore object loaded with keystore data
1716      *
1717      * @throws KeyStoreException if no Provider supports a KeyStoreSpi
1718      *             implementation for the specified keystore file.
1719      * @throws IOException if there is an I/O or format problem with the
1720      *             keystore data. If the error is due to an incorrect
1721      *             {@code ProtectionParameter} (e.g. wrong password)
1722      *             the {@link Throwable#getCause cause} of the
1723      *             {@code IOException} should be an
1724      *             {@code UnrecoverableKeyException}.
1725      * @throws NoSuchAlgorithmException if the algorithm used to check the
1726      *             integrity of the keystore cannot be found.
1727      * @throws CertificateException if any of the certificates in the
1728      *             keystore could not be loaded.
1729      * @throws IllegalArgumentException if file does not exist or does not
1730      *             refer to a normal file, or if param is not recognized.
1731      * @throws NullPointerException if file is {@code null}.
1732      * @throws SecurityException if a security manager exists and its
1733      *             {@link java.lang.SecurityManager#checkRead} method denies
1734      *             read access to the specified file.
1735      *
1736      * @see Provider
1737      *
1738      * @since 9
1739      */
getInstance(File file, LoadStoreParameter param)1740     public static final KeyStore getInstance(File file,
1741         LoadStoreParameter param) throws KeyStoreException, IOException,
1742             NoSuchAlgorithmException, CertificateException {
1743         return getInstance(file, null, param, false);
1744     }
1745 
1746     // Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter)
getInstance(File file, char[] password, LoadStoreParameter param, boolean hasPassword)1747     private static final KeyStore getInstance(File file, char[] password,
1748         LoadStoreParameter param, boolean hasPassword)
1749             throws KeyStoreException, IOException, NoSuchAlgorithmException,
1750                 CertificateException {
1751 
1752         if (file == null) {
1753             throw new NullPointerException();
1754         }
1755 
1756         if (file.isFile() == false) {
1757             throw new IllegalArgumentException(
1758                 "File does not exist or it does not refer to a normal file: " +
1759                     file);
1760         }
1761 
1762         KeyStore keystore = null;
1763 
1764         try (DataInputStream dataStream =
1765             new DataInputStream(
1766                 new BufferedInputStream(
1767                     new FileInputStream(file)))) {
1768 
1769             dataStream.mark(Integer.MAX_VALUE);
1770 
1771             // Detect the keystore type
1772             for (String type : Security.getAlgorithms("KeyStore")) {
1773                 Object[] objs = null;
1774 
1775                 try {
1776                     objs = Security.getImpl(type, "KeyStore", (String)null);
1777 
1778                     KeyStoreSpi impl = (KeyStoreSpi)objs[0];
1779                     if (impl.engineProbe(dataStream)) {
1780 
1781                         if (kdebug != null) {
1782                             kdebug.println(type + " keystore detected: " +
1783                                 file);
1784                         }
1785 
1786                         keystore = new KeyStore(impl, (Provider)objs[1], type);
1787                         break;
1788                     }
1789                 } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
1790                     // ignore
1791                     if (kdebug != null) {
1792                         kdebug.println(type + " not found - " + e);
1793                     }
1794                 } catch (IOException e) {
1795                     // ignore
1796                     if (kdebug != null) {
1797                         kdebug.println("I/O error in " + file + " - " + e);
1798                     }
1799                 }
1800                 dataStream.reset(); // prepare the stream for the next probe
1801             }
1802 
1803             // Load the keystore data
1804             if (keystore != null) {
1805                 dataStream.reset(); // prepare the stream for loading
1806                 if (hasPassword) {
1807                     keystore.load(dataStream, password);
1808                 } else {
1809                     keystore.keyStoreSpi.engineLoad(dataStream, param);
1810                     keystore.initialized = true;
1811                 }
1812                 return keystore;
1813             }
1814         }
1815 
1816         throw new KeyStoreException("Unrecognized keystore format. "
1817                 + "Please load it with a specified type");
1818     }
1819 
1820     /**
1821      * A description of a to-be-instantiated KeyStore object.
1822      *
1823      * <p>An instance of this class encapsulates the information needed to
1824      * instantiate and initialize a KeyStore object. That process is
1825      * triggered when the {@linkplain #getKeyStore} method is called.
1826      *
1827      * <p>This makes it possible to decouple configuration from KeyStore
1828      * object creation and e.g. delay a password prompt until it is
1829      * needed.
1830      *
1831      * @see KeyStore
1832      * @see javax.net.ssl.KeyStoreBuilderParameters
1833      * @since 1.5
1834      */
1835     public abstract static class Builder {
1836 
1837         // maximum times to try the callbackhandler if the password is wrong
1838         static final int MAX_CALLBACK_TRIES = 3;
1839 
1840         /**
1841          * Construct a new Builder.
1842          */
Builder()1843         protected Builder() {
1844             // empty
1845         }
1846 
1847         /**
1848          * Returns the KeyStore described by this object.
1849          *
1850          * @return the {@code KeyStore} described by this object
1851          * @exception KeyStoreException if an error occurred during the
1852          *   operation, for example if the KeyStore could not be
1853          *   instantiated or loaded
1854          */
getKeyStore()1855         public abstract KeyStore getKeyStore() throws KeyStoreException;
1856 
1857         /**
1858          * Returns the ProtectionParameters that should be used to obtain
1859          * the {@link KeyStore.Entry Entry} with the given alias.
1860          * The {@code getKeyStore} method must be invoked before this
1861          * method may be called.
1862          *
1863          * @return the ProtectionParameters that should be used to obtain
1864          *   the {@link KeyStore.Entry Entry} with the given alias.
1865          * @param alias the alias of the KeyStore entry
1866          * @throws NullPointerException if alias is null
1867          * @throws KeyStoreException if an error occurred during the
1868          *   operation
1869          * @throws IllegalStateException if the getKeyStore method has
1870          *   not been invoked prior to calling this method
1871          */
getProtectionParameter(String alias)1872         public abstract ProtectionParameter getProtectionParameter(String alias)
1873             throws KeyStoreException;
1874 
1875         /**
1876          * Returns a new Builder that encapsulates the given KeyStore.
1877          * The {@linkplain #getKeyStore} method of the returned object
1878          * will return {@code keyStore}, the {@linkplain
1879          * #getProtectionParameter getProtectionParameter()} method will
1880          * return {@code protectionParameters}.
1881          *
1882          * <p> This is useful if an existing KeyStore object needs to be
1883          * used with Builder-based APIs.
1884          *
1885          * @return a new Builder object
1886          * @param keyStore the KeyStore to be encapsulated
1887          * @param protectionParameter the ProtectionParameter used to
1888          *   protect the KeyStore entries
1889          * @throws NullPointerException if keyStore or
1890          *   protectionParameters is null
1891          * @throws IllegalArgumentException if the keyStore has not been
1892          *   initialized
1893          */
newInstance(final KeyStore keyStore, final ProtectionParameter protectionParameter)1894         public static Builder newInstance(final KeyStore keyStore,
1895                 final ProtectionParameter protectionParameter) {
1896             if ((keyStore == null) || (protectionParameter == null)) {
1897                 throw new NullPointerException();
1898             }
1899             if (keyStore.initialized == false) {
1900                 throw new IllegalArgumentException("KeyStore not initialized");
1901             }
1902             return new Builder() {
1903                 private volatile boolean getCalled;
1904 
1905                 public KeyStore getKeyStore() {
1906                     getCalled = true;
1907                     return keyStore;
1908                 }
1909 
1910                 public ProtectionParameter getProtectionParameter(String alias)
1911                 {
1912                     if (alias == null) {
1913                         throw new NullPointerException();
1914                     }
1915                     if (getCalled == false) {
1916                         throw new IllegalStateException
1917                             ("getKeyStore() must be called first");
1918                     }
1919                     return protectionParameter;
1920                 }
1921             };
1922         }
1923 
1924         /**
1925          * Returns a new Builder object.
1926          *
1927          * <p>The first call to the {@link #getKeyStore} method on the returned
1928          * builder will create a KeyStore of type {@code type} and call
1929          * its {@link KeyStore#load load()} method.
1930          * The {@code inputStream} argument is constructed from
1931          * {@code file}.
1932          * If {@code protection} is a
1933          * {@code PasswordProtection}, the password is obtained by
1934          * calling the {@code getPassword} method.
1935          * Otherwise, if {@code protection} is a
1936          * {@code CallbackHandlerProtection}, the password is obtained
1937          * by invoking the CallbackHandler.
1938          *
1939          * <p>Subsequent calls to {@link #getKeyStore} return the same object
1940          * as the initial call. If the initial call failed with a
1941          * KeyStoreException, subsequent calls also throw a
1942          * KeyStoreException.
1943          *
1944          * <p>The KeyStore is instantiated from {@code provider} if
1945          * non-null. Otherwise, all installed providers are searched.
1946          *
1947          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1948          * will return a {@link KeyStore.PasswordProtection PasswordProtection}
1949          * object encapsulating the password that was used to invoke the
1950          * {@code load} method.
1951          *
1952          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1953          * within the {@link AccessControlContext} of the code invoking this
1954          * method.
1955          *
1956          * @return a new Builder object
1957          * @param type the type of KeyStore to be constructed
1958          * @param provider the provider from which the KeyStore is to
1959          *   be instantiated (or null)
1960          * @param file the File that contains the KeyStore data
1961          * @param protection the ProtectionParameter securing the KeyStore data
1962          * @throws NullPointerException if type, file or protection is null
1963          * @throws IllegalArgumentException if protection is not an instance
1964          *   of either PasswordProtection or CallbackHandlerProtection; or
1965          *   if file does not exist or does not refer to a normal file
1966          */
newInstance(String type, Provider provider, File file, ProtectionParameter protection)1967         public static Builder newInstance(String type, Provider provider,
1968                 File file, ProtectionParameter protection) {
1969             if ((type == null) || (file == null) || (protection == null)) {
1970                 throw new NullPointerException();
1971             }
1972             if ((protection instanceof PasswordProtection == false) &&
1973                 (protection instanceof CallbackHandlerProtection == false)) {
1974                 throw new IllegalArgumentException
1975                 ("Protection must be PasswordProtection or " +
1976                  "CallbackHandlerProtection");
1977             }
1978             if (file.isFile() == false) {
1979                 throw new IllegalArgumentException
1980                     ("File does not exist or it does not refer " +
1981                      "to a normal file: " + file);
1982             }
1983             return new FileBuilder(type, provider, file, protection,
1984                 AccessController.getContext());
1985         }
1986 
1987         /**
1988          * Returns a new Builder object.
1989          *
1990          * <p>The first call to the {@link #getKeyStore} method on the returned
1991          * builder will create a KeyStore using {@code file} to detect the
1992          * keystore type and then call its {@link KeyStore#load load()} method.
1993          * It uses the same algorithm to determine the keystore type as
1994          * described in {@link KeyStore#getInstance(File, LoadStoreParameter)}.
1995          * The {@code inputStream} argument is constructed from {@code file}.
1996          * If {@code protection} is a {@code PasswordProtection}, the password
1997          * is obtained by calling the {@code getPassword} method.
1998          * Otherwise, if {@code protection} is a
1999          * {@code CallbackHandlerProtection},
2000          * the password is obtained by invoking the CallbackHandler.
2001          *
2002          * <p>Subsequent calls to {@link #getKeyStore} return the same object
2003          * as the initial call. If the initial call failed with a
2004          * KeyStoreException, subsequent calls also throw a KeyStoreException.
2005          *
2006          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
2007          * will return a {@link KeyStore.PasswordProtection PasswordProtection}
2008          * object encapsulating the password that was used to invoke the
2009          * {@code load} method.
2010          *
2011          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
2012          * within the {@link AccessControlContext} of the code invoking this
2013          * method.
2014          *
2015          * @return a new Builder object
2016          * @param file the File that contains the KeyStore data
2017          * @param protection the ProtectionParameter securing the KeyStore data
2018          * @throws NullPointerException if file or protection is null
2019          * @throws IllegalArgumentException if protection is not an instance
2020          *   of either PasswordProtection or CallbackHandlerProtection; or
2021          *   if file does not exist or does not refer to a normal file
2022          *
2023          * @since 9
2024          */
newInstance(File file, ProtectionParameter protection)2025         public static Builder newInstance(File file,
2026             ProtectionParameter protection) {
2027 
2028             return newInstance("", null, file, protection);
2029         }
2030 
2031         private static final class FileBuilder extends Builder {
2032 
2033             private final String type;
2034             private final Provider provider;
2035             private final File file;
2036             private ProtectionParameter protection;
2037             private ProtectionParameter keyProtection;
2038             private final AccessControlContext context;
2039 
2040             private KeyStore keyStore;
2041 
2042             private Throwable oldException;
2043 
FileBuilder(String type, Provider provider, File file, ProtectionParameter protection, AccessControlContext context)2044             FileBuilder(String type, Provider provider, File file,
2045                     ProtectionParameter protection,
2046                     AccessControlContext context) {
2047                 this.type = type;
2048                 this.provider = provider;
2049                 this.file = file;
2050                 this.protection = protection;
2051                 this.context = context;
2052             }
2053 
getKeyStore()2054             public synchronized KeyStore getKeyStore() throws KeyStoreException
2055             {
2056                 if (keyStore != null) {
2057                     return keyStore;
2058                 }
2059                 if (oldException != null) {
2060                     throw new KeyStoreException
2061                         ("Previous KeyStore instantiation failed",
2062                          oldException);
2063                 }
2064                 PrivilegedExceptionAction<KeyStore> action =
2065                         new PrivilegedExceptionAction<KeyStore>() {
2066                     public KeyStore run() throws Exception {
2067                         if (protection instanceof CallbackHandlerProtection == false) {
2068                             return run0();
2069                         }
2070                         // when using a CallbackHandler,
2071                         // reprompt if the password is wrong
2072                         int tries = 0;
2073                         while (true) {
2074                             tries++;
2075                             try {
2076                                 return run0();
2077                             } catch (IOException e) {
2078                                 if ((tries < MAX_CALLBACK_TRIES)
2079                                         && (e.getCause() instanceof UnrecoverableKeyException)) {
2080                                     continue;
2081                                 }
2082                                 throw e;
2083                             }
2084                         }
2085                     }
2086                     public KeyStore run0() throws Exception {
2087                         KeyStore ks;
2088                         char[] password = null;
2089 
2090                         // Acquire keystore password
2091                         if (protection instanceof PasswordProtection) {
2092                             password =
2093                                 ((PasswordProtection)protection).getPassword();
2094                             keyProtection = protection;
2095                         } else {
2096                             CallbackHandler handler =
2097                                 ((CallbackHandlerProtection)protection)
2098                                     .getCallbackHandler();
2099                             PasswordCallback callback = new PasswordCallback
2100                                 ("Password for keystore " + file.getName(),
2101                                     false);
2102                             handler.handle(new Callback[] {callback});
2103                             password = callback.getPassword();
2104                             if (password == null) {
2105                                 throw new KeyStoreException("No password" +
2106                                                             " provided");
2107                             }
2108                             callback.clearPassword();
2109                             keyProtection = new PasswordProtection(password);
2110                         }
2111 
2112                         if (type.isEmpty()) {
2113                             // Instantiate keystore and load keystore data
2114                             ks = KeyStore.getInstance(file, password);
2115                         } else {
2116                             // Instantiate keystore
2117                             if (provider == null) {
2118                                 ks = KeyStore.getInstance(type);
2119                             } else {
2120                                 ks = KeyStore.getInstance(type, provider);
2121                             }
2122                             // Load keystore data
2123                             try (InputStream in = new FileInputStream(file)) {
2124                                 ks.load(in, password);
2125                             }
2126                         }
2127                         return ks;
2128                     }
2129                 };
2130                 try {
2131                     keyStore = AccessController.doPrivileged(action, context);
2132                     return keyStore;
2133                 } catch (PrivilegedActionException e) {
2134                     oldException = e.getCause();
2135                     throw new KeyStoreException
2136                         ("KeyStore instantiation failed", oldException);
2137                 }
2138             }
2139 
2140             public synchronized ProtectionParameter
getProtectionParameter(String alias)2141                         getProtectionParameter(String alias) {
2142                 if (alias == null) {
2143                     throw new NullPointerException();
2144                 }
2145                 if (keyStore == null) {
2146                     throw new IllegalStateException
2147                         ("getKeyStore() must be called first");
2148                 }
2149                 return keyProtection;
2150             }
2151         }
2152 
2153         /**
2154          * Returns a new Builder object.
2155          *
2156          * <p>Each call to the {@link #getKeyStore} method on the returned
2157          * builder will return a new KeyStore object of type {@code type}.
2158          * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
2159          * method is invoked using a
2160          * {@code LoadStoreParameter} that encapsulates
2161          * {@code protection}.
2162          *
2163          * <p>The KeyStore is instantiated from {@code provider} if
2164          * non-null. Otherwise, all installed providers are searched.
2165          *
2166          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
2167          * will return {@code protection}.
2168          *
2169          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
2170          * within the {@link AccessControlContext} of the code invoking this
2171          * method.
2172          *
2173          * @return a new Builder object
2174          * @param type the type of KeyStore to be constructed
2175          * @param provider the provider from which the KeyStore is to
2176          *   be instantiated (or null)
2177          * @param protection the ProtectionParameter securing the Keystore
2178          * @throws NullPointerException if type or protection is null
2179          */
newInstance(final String type, final Provider provider, final ProtectionParameter protection)2180         public static Builder newInstance(final String type,
2181                 final Provider provider, final ProtectionParameter protection) {
2182             if ((type == null) || (protection == null)) {
2183                 throw new NullPointerException();
2184             }
2185             final AccessControlContext context = AccessController.getContext();
2186             return new Builder() {
2187                 private volatile boolean getCalled;
2188                 private IOException oldException;
2189 
2190                 private final PrivilegedExceptionAction<KeyStore> action
2191                         = new PrivilegedExceptionAction<KeyStore>() {
2192 
2193                     public KeyStore run() throws Exception {
2194                         KeyStore ks;
2195                         if (provider == null) {
2196                             ks = KeyStore.getInstance(type);
2197                         } else {
2198                             ks = KeyStore.getInstance(type, provider);
2199                         }
2200                         LoadStoreParameter param = new SimpleLoadStoreParameter(protection);
2201                         if (protection instanceof CallbackHandlerProtection == false) {
2202                             ks.load(param);
2203                         } else {
2204                             // when using a CallbackHandler,
2205                             // reprompt if the password is wrong
2206                             int tries = 0;
2207                             while (true) {
2208                                 tries++;
2209                                 try {
2210                                     ks.load(param);
2211                                     break;
2212                                 } catch (IOException e) {
2213                                     if (e.getCause() instanceof UnrecoverableKeyException) {
2214                                         if (tries < MAX_CALLBACK_TRIES) {
2215                                             continue;
2216                                         } else {
2217                                             oldException = e;
2218                                         }
2219                                     }
2220                                     throw e;
2221                                 }
2222                             }
2223                         }
2224                         getCalled = true;
2225                         return ks;
2226                     }
2227                 };
2228 
2229                 public synchronized KeyStore getKeyStore()
2230                         throws KeyStoreException {
2231                     if (oldException != null) {
2232                         throw new KeyStoreException
2233                             ("Previous KeyStore instantiation failed",
2234                              oldException);
2235                     }
2236                     try {
2237                         return AccessController.doPrivileged(action, context);
2238                     } catch (PrivilegedActionException e) {
2239                         Throwable cause = e.getCause();
2240                         throw new KeyStoreException
2241                             ("KeyStore instantiation failed", cause);
2242                     }
2243                 }
2244 
2245                 public ProtectionParameter getProtectionParameter(String alias)
2246                 {
2247                     if (alias == null) {
2248                         throw new NullPointerException();
2249                     }
2250                     if (getCalled == false) {
2251                         throw new IllegalStateException
2252                             ("getKeyStore() must be called first");
2253                     }
2254                     return protection;
2255                 }
2256             };
2257         }
2258 
2259     }
2260 
2261     static class SimpleLoadStoreParameter implements LoadStoreParameter {
2262 
2263         private final ProtectionParameter protection;
2264 
2265         SimpleLoadStoreParameter(ProtectionParameter protection) {
2266             this.protection = protection;
2267         }
2268 
2269         public ProtectionParameter getProtectionParameter() {
2270             return protection;
2271         }
2272     }
2273 }
2274