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