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