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