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