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