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