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