1 /*
   2  * Copyright (c) 1997, 2015, 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      * @param type the type of keystore.
 845      * See the KeyStore section in the <a href=
 846      * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
 847      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 848      * for information about standard keystore types.
 849      *
 850      * @return a keystore object of the specified type.
 851      *
 852      * @exception KeyStoreException if no Provider supports a
 853      *          KeyStoreSpi implementation for the
 854      *          specified type.
 855      *
 856      * @see Provider
 857      */
 858     public static KeyStore getInstance(String type)
 859         throws KeyStoreException
 860     {
 861         try {
 862             Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
 863             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
 864         } catch (NoSuchAlgorithmException nsae) {
 865             throw new KeyStoreException(type + " not found", nsae);
 866         } catch (NoSuchProviderException nspe) {
 867             throw new KeyStoreException(type + " not found", nspe);
 868         }
 869     }
 870 
 871     /**
 872      * Returns a keystore object of the specified type.
 873      *
 874      * <p> A new KeyStore object encapsulating the
 875      * KeyStoreSpi implementation from the specified provider
 876      * is returned.  The specified provider must be registered
 877      * in the security provider list.
 878      *
 879      * <p> Note that the list of registered providers may be retrieved via
 880      * the {@link Security#getProviders() Security.getProviders()} method.
 881      *
 882      * @param type the type of keystore.
 883      * See the KeyStore section in the <a href=
 884      * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
 885      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 886      * for information about standard keystore types.
 887      *
 888      * @param provider the name of the provider.
 889      *
 890      * @return a keystore object of the specified type.
 891      *
 892      * @exception KeyStoreException if a KeyStoreSpi
 893      *          implementation for the specified type is not
 894      *          available from the specified provider.
 895      *
 896      * @exception NoSuchProviderException if the specified provider is not
 897      *          registered in the security provider list.
 898      *
 899      * @exception IllegalArgumentException if the provider name is null
 900      *          or empty.
 901      *
 902      * @see Provider
 903      */
 904     public static KeyStore getInstance(String type, String provider)
 905         throws KeyStoreException, NoSuchProviderException
 906     {
 907         if (provider == null || provider.length() == 0)
 908             throw new IllegalArgumentException("missing provider");
 909         try {
 910             Object[] objs = Security.getImpl(type, "KeyStore", provider);
 911             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
 912         } catch (NoSuchAlgorithmException nsae) {
 913             throw new KeyStoreException(type + " not found", nsae);
 914         }
 915     }
 916 
 917     /**
 918      * Returns a keystore object of the specified type.
 919      *
 920      * <p> A new KeyStore object encapsulating the
 921      * KeyStoreSpi implementation from the specified Provider
 922      * object is returned.  Note that the specified Provider object
 923      * does not have to be registered in the provider list.
 924      *
 925      * @param type the type of keystore.
 926      * See the KeyStore section in the <a href=
 927      * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
 928      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 929      * for information about standard keystore types.
 930      *
 931      * @param provider the provider.
 932      *
 933      * @return a keystore object of the specified type.
 934      *
 935      * @exception KeyStoreException if KeyStoreSpi
 936      *          implementation for the specified type is not available
 937      *          from the specified Provider object.
 938      *
 939      * @exception IllegalArgumentException if the specified provider is null.
 940      *
 941      * @see Provider
 942      *
 943      * @since 1.4
 944      */
 945     public static KeyStore getInstance(String type, Provider provider)
 946         throws KeyStoreException
 947     {
 948         if (provider == null)
 949             throw new IllegalArgumentException("missing provider");
 950         try {
 951             Object[] objs = Security.getImpl(type, "KeyStore", provider);
 952             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
 953         } catch (NoSuchAlgorithmException nsae) {
 954             throw new KeyStoreException(type + " not found", nsae);
 955         }
 956     }
 957 
 958     /**
 959      * Returns the default keystore type as specified by the
 960      * {@code keystore.type} security property, or the string
 961      * {@literal "jks"} (acronym for {@literal "Java keystore"})
 962      * if no such property exists.
 963      *
 964      * <p>The default keystore type can be used by applications that do not
 965      * want to use a hard-coded keystore type when calling one of the
 966      * {@code getInstance} methods, and want to provide a default keystore
 967      * type in case a user does not specify its own.
 968      *
 969      * <p>The default keystore type can be changed by setting the value of the
 970      * {@code keystore.type} security property to the desired keystore type.
 971      *
 972      * @return the default keystore type as specified by the
 973      * {@code keystore.type} security property, or the string {@literal "jks"}
 974      * if no such property exists.
 975      * @see java.security.Security security properties
 976      */
 977     public final static String getDefaultType() {
 978         String kstype;
 979         kstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
 980             public String run() {
 981                 return Security.getProperty(KEYSTORE_TYPE);
 982             }
 983         });
 984         if (kstype == null) {
 985             kstype = "jks";
 986         }
 987         return kstype;
 988     }
 989 
 990     /**
 991      * Returns the provider of this keystore.
 992      *
 993      * @return the provider of this keystore.
 994      */
 995     public final Provider getProvider()
 996     {
 997         return this.provider;
 998     }
 999 
1000     /**
1001      * Returns the type of this keystore.
1002      *
1003      * @return the type of this keystore.
1004      */
1005     public final String getType()
1006     {
1007         return this.type;
1008     }
1009 
1010     /**
1011      * Returns the key associated with the given alias, using the given
1012      * password to recover it.  The key must have been associated with
1013      * the alias by a call to {@code setKeyEntry},
1014      * or by a call to {@code setEntry} with a
1015      * {@code PrivateKeyEntry} or {@code SecretKeyEntry}.
1016      *
1017      * @param alias the alias name
1018      * @param password the password for recovering the key
1019      *
1020      * @return the requested key, or null if the given alias does not exist
1021      * or does not identify a key-related entry.
1022      *
1023      * @exception KeyStoreException if the keystore has not been initialized
1024      * (loaded).
1025      * @exception NoSuchAlgorithmException if the algorithm for recovering the
1026      * key cannot be found
1027      * @exception UnrecoverableKeyException if the key cannot be recovered
1028      * (e.g., the given password is wrong).
1029      */
1030     public final Key getKey(String alias, char[] password)
1031         throws KeyStoreException, NoSuchAlgorithmException,
1032             UnrecoverableKeyException
1033     {
1034         if (!initialized) {
1035             throw new KeyStoreException("Uninitialized keystore");
1036         }
1037         return keyStoreSpi.engineGetKey(alias, password);
1038     }
1039 
1040     /**
1041      * Returns the certificate chain associated with the given alias.
1042      * The certificate chain must have been associated with the alias
1043      * by a call to {@code setKeyEntry},
1044      * or by a call to {@code setEntry} with a
1045      * {@code PrivateKeyEntry}.
1046      *
1047      * @param alias the alias name
1048      *
1049      * @return the certificate chain (ordered with the user's certificate first
1050      * followed by zero or more certificate authorities), or null if the given alias
1051      * does not exist or does not contain a certificate chain
1052      *
1053      * @exception KeyStoreException if the keystore has not been initialized
1054      * (loaded).
1055      */
1056     public final Certificate[] getCertificateChain(String alias)
1057         throws KeyStoreException
1058     {
1059         if (!initialized) {
1060             throw new KeyStoreException("Uninitialized keystore");
1061         }
1062         return keyStoreSpi.engineGetCertificateChain(alias);
1063     }
1064 
1065     /**
1066      * Returns the certificate associated with the given alias.
1067      *
1068      * <p> If the given alias name identifies an entry
1069      * created by a call to {@code setCertificateEntry},
1070      * or created by a call to {@code setEntry} with a
1071      * {@code TrustedCertificateEntry},
1072      * then the trusted certificate contained in that entry is returned.
1073      *
1074      * <p> If the given alias name identifies an entry
1075      * created by a call to {@code setKeyEntry},
1076      * or created by a call to {@code setEntry} with a
1077      * {@code PrivateKeyEntry},
1078      * then the first element of the certificate chain in that entry
1079      * is returned.
1080      *
1081      * @param alias the alias name
1082      *
1083      * @return the certificate, or null if the given alias does not exist or
1084      * does not contain a certificate.
1085      *
1086      * @exception KeyStoreException if the keystore has not been initialized
1087      * (loaded).
1088      */
1089     public final Certificate getCertificate(String alias)
1090         throws KeyStoreException
1091     {
1092         if (!initialized) {
1093             throw new KeyStoreException("Uninitialized keystore");
1094         }
1095         return keyStoreSpi.engineGetCertificate(alias);
1096     }
1097 
1098     /**
1099      * Returns the creation date of the entry identified by the given alias.
1100      *
1101      * @param alias the alias name
1102      *
1103      * @return the creation date of this entry, or null if the given alias does
1104      * not exist
1105      *
1106      * @exception KeyStoreException if the keystore has not been initialized
1107      * (loaded).
1108      */
1109     public final Date getCreationDate(String alias)
1110         throws KeyStoreException
1111     {
1112         if (!initialized) {
1113             throw new KeyStoreException("Uninitialized keystore");
1114         }
1115         return keyStoreSpi.engineGetCreationDate(alias);
1116     }
1117 
1118     /**
1119      * Assigns the given key to the given alias, protecting it with the given
1120      * password.
1121      *
1122      * <p>If the given key is of type {@code java.security.PrivateKey},
1123      * it must be accompanied by a certificate chain certifying the
1124      * corresponding public key.
1125      *
1126      * <p>If the given alias already exists, the keystore information
1127      * associated with it is overridden by the given key (and possibly
1128      * certificate chain).
1129      *
1130      * @param alias the alias name
1131      * @param key the key to be associated with the alias
1132      * @param password the password to protect the key
1133      * @param chain the certificate chain for the corresponding public
1134      * key (only required if the given key is of type
1135      * {@code java.security.PrivateKey}).
1136      *
1137      * @exception KeyStoreException if the keystore has not been initialized
1138      * (loaded), the given key cannot be protected, or this operation fails
1139      * for some other reason
1140      */
1141     public final void setKeyEntry(String alias, Key key, char[] password,
1142                                   Certificate[] chain)
1143         throws KeyStoreException
1144     {
1145         if (!initialized) {
1146             throw new KeyStoreException("Uninitialized keystore");
1147         }
1148         if ((key instanceof PrivateKey) &&
1149             (chain == null || chain.length == 0)) {
1150             throw new IllegalArgumentException("Private key must be "
1151                                                + "accompanied by certificate "
1152                                                + "chain");
1153         }
1154         keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
1155     }
1156 
1157     /**
1158      * Assigns the given key (that has already been protected) to the given
1159      * alias.
1160      *
1161      * <p>If the protected key is of type
1162      * {@code java.security.PrivateKey}, it must be accompanied by a
1163      * certificate chain certifying the corresponding public key. If the
1164      * underlying keystore implementation is of type {@code jks},
1165      * {@code key} must be encoded as an
1166      * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard.
1167      *
1168      * <p>If the given alias already exists, the keystore information
1169      * associated with it is overridden by the given key (and possibly
1170      * certificate chain).
1171      *
1172      * @param alias the alias name
1173      * @param key the key (in protected format) to be associated with the alias
1174      * @param chain the certificate chain for the corresponding public
1175      *          key (only useful if the protected key is of type
1176      *          {@code java.security.PrivateKey}).
1177      *
1178      * @exception KeyStoreException if the keystore has not been initialized
1179      * (loaded), or if this operation fails for some other reason.
1180      */
1181     public final void setKeyEntry(String alias, byte[] key,
1182                                   Certificate[] chain)
1183         throws KeyStoreException
1184     {
1185         if (!initialized) {
1186             throw new KeyStoreException("Uninitialized keystore");
1187         }
1188         keyStoreSpi.engineSetKeyEntry(alias, key, chain);
1189     }
1190 
1191     /**
1192      * Assigns the given trusted certificate to the given alias.
1193      *
1194      * <p> If the given alias identifies an existing entry
1195      * created by a call to {@code setCertificateEntry},
1196      * or created by a call to {@code setEntry} with a
1197      * {@code TrustedCertificateEntry},
1198      * the trusted certificate in the existing entry
1199      * is overridden by the given certificate.
1200      *
1201      * @param alias the alias name
1202      * @param cert the certificate
1203      *
1204      * @exception KeyStoreException if the keystore has not been initialized,
1205      * or the given alias already exists and does not identify an
1206      * entry containing a trusted certificate,
1207      * or this operation fails for some other reason.
1208      */
1209     public final void setCertificateEntry(String alias, Certificate cert)
1210         throws KeyStoreException
1211     {
1212         if (!initialized) {
1213             throw new KeyStoreException("Uninitialized keystore");
1214         }
1215         keyStoreSpi.engineSetCertificateEntry(alias, cert);
1216     }
1217 
1218     /**
1219      * Deletes the entry identified by the given alias from this keystore.
1220      *
1221      * @param alias the alias name
1222      *
1223      * @exception KeyStoreException if the keystore has not been initialized,
1224      * or if the entry cannot be removed.
1225      */
1226     public final void deleteEntry(String alias)
1227         throws KeyStoreException
1228     {
1229         if (!initialized) {
1230             throw new KeyStoreException("Uninitialized keystore");
1231         }
1232         keyStoreSpi.engineDeleteEntry(alias);
1233     }
1234 
1235     /**
1236      * Lists all the alias names of this keystore.
1237      *
1238      * @return enumeration of the alias names
1239      *
1240      * @exception KeyStoreException if the keystore has not been initialized
1241      * (loaded).
1242      */
1243     public final Enumeration<String> aliases()
1244         throws KeyStoreException
1245     {
1246         if (!initialized) {
1247             throw new KeyStoreException("Uninitialized keystore");
1248         }
1249         return keyStoreSpi.engineAliases();
1250     }
1251 
1252     /**
1253      * Checks if the given alias exists in this keystore.
1254      *
1255      * @param alias the alias name
1256      *
1257      * @return true if the alias exists, false otherwise
1258      *
1259      * @exception KeyStoreException if the keystore has not been initialized
1260      * (loaded).
1261      */
1262     public final boolean containsAlias(String alias)
1263         throws KeyStoreException
1264     {
1265         if (!initialized) {
1266             throw new KeyStoreException("Uninitialized keystore");
1267         }
1268         return keyStoreSpi.engineContainsAlias(alias);
1269     }
1270 
1271     /**
1272      * Retrieves the number of entries in this keystore.
1273      *
1274      * @return the number of entries in this keystore
1275      *
1276      * @exception KeyStoreException if the keystore has not been initialized
1277      * (loaded).
1278      */
1279     public final int size()
1280         throws KeyStoreException
1281     {
1282         if (!initialized) {
1283             throw new KeyStoreException("Uninitialized keystore");
1284         }
1285         return keyStoreSpi.engineSize();
1286     }
1287 
1288     /**
1289      * Returns true if the entry identified by the given alias
1290      * was created by a call to {@code setKeyEntry},
1291      * or created by a call to {@code setEntry} with a
1292      * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.
1293      *
1294      * @param alias the alias for the keystore entry to be checked
1295      *
1296      * @return true if the entry identified by the given alias is a
1297      * key-related entry, false otherwise.
1298      *
1299      * @exception KeyStoreException if the keystore has not been initialized
1300      * (loaded).
1301      */
1302     public final boolean isKeyEntry(String alias)
1303         throws KeyStoreException
1304     {
1305         if (!initialized) {
1306             throw new KeyStoreException("Uninitialized keystore");
1307         }
1308         return keyStoreSpi.engineIsKeyEntry(alias);
1309     }
1310 
1311     /**
1312      * Returns true if the entry identified by the given alias
1313      * was created by a call to {@code setCertificateEntry},
1314      * or created by a call to {@code setEntry} with a
1315      * {@code TrustedCertificateEntry}.
1316      *
1317      * @param alias the alias for the keystore entry to be checked
1318      *
1319      * @return true if the entry identified by the given alias contains a
1320      * trusted certificate, false otherwise.
1321      *
1322      * @exception KeyStoreException if the keystore has not been initialized
1323      * (loaded).
1324      */
1325     public final boolean isCertificateEntry(String alias)
1326         throws KeyStoreException
1327     {
1328         if (!initialized) {
1329             throw new KeyStoreException("Uninitialized keystore");
1330         }
1331         return keyStoreSpi.engineIsCertificateEntry(alias);
1332     }
1333 
1334     /**
1335      * Returns the (alias) name of the first keystore entry whose certificate
1336      * matches the given certificate.
1337      *
1338      * <p> This method attempts to match the given certificate with each
1339      * keystore entry. If the entry being considered was
1340      * created by a call to {@code setCertificateEntry},
1341      * or created by a call to {@code setEntry} with a
1342      * {@code TrustedCertificateEntry},
1343      * then the given certificate is compared to that entry's certificate.
1344      *
1345      * <p> If the entry being considered was
1346      * created by a call to {@code setKeyEntry},
1347      * or created by a call to {@code setEntry} with a
1348      * {@code PrivateKeyEntry},
1349      * then the given certificate is compared to the first
1350      * element of that entry's certificate chain.
1351      *
1352      * @param cert the certificate to match with.
1353      *
1354      * @return the alias name of the first entry with a matching certificate,
1355      * or null if no such entry exists in this keystore.
1356      *
1357      * @exception KeyStoreException if the keystore has not been initialized
1358      * (loaded).
1359      */
1360     public final String getCertificateAlias(Certificate cert)
1361         throws KeyStoreException
1362     {
1363         if (!initialized) {
1364             throw new KeyStoreException("Uninitialized keystore");
1365         }
1366         return keyStoreSpi.engineGetCertificateAlias(cert);
1367     }
1368 
1369     /**
1370      * Stores this keystore to the given output stream, and protects its
1371      * integrity with the given password.
1372      *
1373      * @param stream the output stream to which this keystore is written.
1374      * @param password the password to generate the keystore integrity check
1375      *
1376      * @exception KeyStoreException if the keystore has not been initialized
1377      * (loaded).
1378      * @exception IOException if there was an I/O problem with data
1379      * @exception NoSuchAlgorithmException if the appropriate data integrity
1380      * algorithm could not be found
1381      * @exception CertificateException if any of the certificates included in
1382      * the keystore data could not be stored
1383      */
1384     public final void store(OutputStream stream, char[] password)
1385         throws KeyStoreException, IOException, NoSuchAlgorithmException,
1386             CertificateException
1387     {
1388         if (!initialized) {
1389             throw new KeyStoreException("Uninitialized keystore");
1390         }
1391         keyStoreSpi.engineStore(stream, password);
1392     }
1393 
1394     /**
1395      * Stores this keystore using the given {@code LoadStoreParameter}.
1396      *
1397      * @param param the {@code LoadStoreParameter}
1398      *          that specifies how to store the keystore,
1399      *          which may be {@code null}
1400      *
1401      * @exception IllegalArgumentException if the given
1402      *          {@code LoadStoreParameter}
1403      *          input is not recognized
1404      * @exception KeyStoreException if the keystore has not been initialized
1405      *          (loaded)
1406      * @exception IOException if there was an I/O problem with data
1407      * @exception NoSuchAlgorithmException if the appropriate data integrity
1408      *          algorithm could not be found
1409      * @exception CertificateException if any of the certificates included in
1410      *          the keystore data could not be stored
1411      *
1412      * @since 1.5
1413      */
1414     public final void store(LoadStoreParameter param)
1415                 throws KeyStoreException, IOException,
1416                 NoSuchAlgorithmException, CertificateException {
1417         if (!initialized) {
1418             throw new KeyStoreException("Uninitialized keystore");
1419         }
1420         keyStoreSpi.engineStore(param);
1421     }
1422 
1423     /**
1424      * Loads this KeyStore from the given input stream.
1425      *
1426      * <p>A password may be given to unlock the keystore
1427      * (e.g. the keystore resides on a hardware token device),
1428      * or to check the integrity of the keystore data.
1429      * If a password is not given for integrity checking,
1430      * then integrity checking is not performed.
1431      *
1432      * <p>In order to create an empty keystore, or if the keystore cannot
1433      * be initialized from a stream, pass {@code null}
1434      * as the {@code stream} argument.
1435      *
1436      * <p> Note that if this keystore has already been loaded, it is
1437      * reinitialized and loaded again from the given input stream.
1438      *
1439      * @param stream the input stream from which the keystore is loaded,
1440      * or {@code null}
1441      * @param password the password used to check the integrity of
1442      * the keystore, the password used to unlock the keystore,
1443      * or {@code null}
1444      *
1445      * @exception IOException if there is an I/O or format problem with the
1446      * keystore data, if a password is required but not given,
1447      * or if the given password was incorrect. If the error is due to a
1448      * wrong password, the {@link Throwable#getCause cause} of the
1449      * {@code IOException} should be an
1450      * {@code UnrecoverableKeyException}
1451      * @exception NoSuchAlgorithmException if the algorithm used to check
1452      * the integrity of the keystore cannot be found
1453      * @exception CertificateException if any of the certificates in the
1454      * keystore could not be loaded
1455      */
1456     public final void load(InputStream stream, char[] password)
1457         throws IOException, NoSuchAlgorithmException, CertificateException
1458     {
1459         keyStoreSpi.engineLoad(stream, password);
1460         initialized = true;
1461     }
1462 
1463     /**
1464      * Loads this keystore using the given {@code LoadStoreParameter}.
1465      *
1466      * <p> Note that if this KeyStore has already been loaded, it is
1467      * reinitialized and loaded again from the given parameter.
1468      *
1469      * @param param the {@code LoadStoreParameter}
1470      *          that specifies how to load the keystore,
1471      *          which may be {@code null}
1472      *
1473      * @exception IllegalArgumentException if the given
1474      *          {@code LoadStoreParameter}
1475      *          input is not recognized
1476      * @exception IOException if there is an I/O or format problem with the
1477      *          keystore data. If the error is due to an incorrect
1478      *         {@code ProtectionParameter} (e.g. wrong password)
1479      *         the {@link Throwable#getCause cause} of the
1480      *         {@code IOException} should be an
1481      *         {@code UnrecoverableKeyException}
1482      * @exception NoSuchAlgorithmException if the algorithm used to check
1483      *          the integrity of the keystore cannot be found
1484      * @exception CertificateException if any of the certificates in the
1485      *          keystore could not be loaded
1486      *
1487      * @since 1.5
1488      */
1489     public final void load(LoadStoreParameter param)
1490                 throws IOException, NoSuchAlgorithmException,
1491                 CertificateException {
1492 
1493         keyStoreSpi.engineLoad(param);
1494         initialized = true;
1495     }
1496 
1497     /**
1498      * Gets a keystore {@code Entry} for the specified alias
1499      * with the specified protection parameter.
1500      *
1501      * @param alias get the keystore {@code Entry} for this alias
1502      * @param protParam the {@code ProtectionParameter}
1503      *          used to protect the {@code Entry},
1504      *          which may be {@code null}
1505      *
1506      * @return the keystore {@code Entry} for the specified alias,
1507      *          or {@code null} if there is no such entry
1508      *
1509      * @exception NullPointerException if
1510      *          {@code alias} is {@code null}
1511      * @exception NoSuchAlgorithmException if the algorithm for recovering the
1512      *          entry cannot be found
1513      * @exception UnrecoverableEntryException if the specified
1514      *          {@code protParam} were insufficient or invalid
1515      * @exception UnrecoverableKeyException if the entry is a
1516      *          {@code PrivateKeyEntry} or {@code SecretKeyEntry}
1517      *          and the specified {@code protParam} does not contain
1518      *          the information needed to recover the key (e.g. wrong password)
1519      * @exception KeyStoreException if the keystore has not been initialized
1520      *          (loaded).
1521      * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
1522      *
1523      * @since 1.5
1524      */
1525     public final Entry getEntry(String alias, ProtectionParameter protParam)
1526                 throws NoSuchAlgorithmException, UnrecoverableEntryException,
1527                 KeyStoreException {
1528 
1529         if (alias == null) {
1530             throw new NullPointerException("invalid null input");
1531         }
1532         if (!initialized) {
1533             throw new KeyStoreException("Uninitialized keystore");
1534         }
1535         return keyStoreSpi.engineGetEntry(alias, protParam);
1536     }
1537 
1538     /**
1539      * Saves a keystore {@code Entry} under the specified alias.
1540      * The protection parameter is used to protect the
1541      * {@code Entry}.
1542      *
1543      * <p> If an entry already exists for the specified alias,
1544      * it is overridden.
1545      *
1546      * @param alias save the keystore {@code Entry} under this alias
1547      * @param entry the {@code Entry} to save
1548      * @param protParam the {@code ProtectionParameter}
1549      *          used to protect the {@code Entry},
1550      *          which may be {@code null}
1551      *
1552      * @exception NullPointerException if
1553      *          {@code alias} or {@code entry}
1554      *          is {@code null}
1555      * @exception KeyStoreException if the keystore has not been initialized
1556      *          (loaded), or if this operation fails for some other reason
1557      *
1558      * @see #getEntry(String, KeyStore.ProtectionParameter)
1559      *
1560      * @since 1.5
1561      */
1562     public final void setEntry(String alias, Entry entry,
1563                         ProtectionParameter protParam)
1564                 throws KeyStoreException {
1565         if (alias == null || entry == null) {
1566             throw new NullPointerException("invalid null input");
1567         }
1568         if (!initialized) {
1569             throw new KeyStoreException("Uninitialized keystore");
1570         }
1571         keyStoreSpi.engineSetEntry(alias, entry, protParam);
1572     }
1573 
1574     /**
1575      * Determines if the keystore {@code Entry} for the specified
1576      * {@code alias} is an instance or subclass of the specified
1577      * {@code entryClass}.
1578      *
1579      * @param alias the alias name
1580      * @param entryClass the entry class
1581      *
1582      * @return true if the keystore {@code Entry} for the specified
1583      *          {@code alias} is an instance or subclass of the
1584      *          specified {@code entryClass}, false otherwise
1585      *
1586      * @exception NullPointerException if
1587      *          {@code alias} or {@code entryClass}
1588      *          is {@code null}
1589      * @exception KeyStoreException if the keystore has not been
1590      *          initialized (loaded)
1591      *
1592      * @since 1.5
1593      */
1594     public final boolean
1595         entryInstanceOf(String alias,
1596                         Class<? extends KeyStore.Entry> entryClass)
1597         throws KeyStoreException
1598     {
1599 
1600         if (alias == null || entryClass == null) {
1601             throw new NullPointerException("invalid null input");
1602         }
1603         if (!initialized) {
1604             throw new KeyStoreException("Uninitialized keystore");
1605         }
1606         return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
1607     }
1608 
1609     /**
1610      * Returns a loaded keystore object of the appropriate keystore type.
1611      * First the keystore type is determined by probing the specified file.
1612      * Then a keystore object is instantiated and loaded using the data from
1613      * that file.
1614      * A password may be supplied to unlock the keystore data or perform an
1615      * integrity check.
1616      *
1617      * <p>
1618      * This method traverses the list of registered security
1619      * {@linkplain Provider providers}, starting with the most
1620      * preferred Provider.
1621      * For each {@link KeyStoreSpi} implementation supported by a
1622      * Provider, it invokes the {@link
1623      * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
1624      * determine if it supports the specified keystore.
1625      * A new KeyStore object is returned that encapsulates the KeyStoreSpi
1626      * implementation from the first Provider that supports the specified file.
1627      *
1628      * <p> Note that the list of registered providers may be retrieved via
1629      * the {@link Security#getProviders() Security.getProviders()} method.
1630      *
1631      * @param  file the keystore file
1632      * @param  password the keystore password, which may be {@code null}
1633      *
1634      * @return a keystore object loaded with keystore data
1635      *
1636      * @throws KeyStoreException if no Provider supports a KeyStoreSpi
1637      *             implementation for the specified keystore file.
1638      * @throws IOException if there is an I/O or format problem with the
1639      *             keystore data, if a password is required but not given,
1640      *             or if the given password was incorrect. If the error is
1641      *             due to a wrong password, the {@link Throwable#getCause cause}
1642      *             of the {@code IOException} should be an
1643      *             {@code UnrecoverableKeyException}.
1644      * @throws NoSuchAlgorithmException if the algorithm used to check the
1645      *             integrity of the keystore cannot be found.
1646      * @throws CertificateException if any of the certificates in the
1647      *             keystore could not be loaded.
1648      * @throws IllegalArgumentException if file does not exist or does not
1649      *             refer to a normal file.
1650      * @throws NullPointerException if file is {@code null}.
1651      * @throws SecurityException if a security manager exists and its
1652      *             {@link java.lang.SecurityManager#checkRead} method denies
1653      *             read access to the specified file.
1654      *
1655      * @see Provider
1656      *
1657      * @since 1.9
1658      */
1659     public static final KeyStore getInstance(File file, char[] password)
1660         throws KeyStoreException, IOException, NoSuchAlgorithmException,
1661             CertificateException {
1662         return getInstance(file, password, null, true);
1663     }
1664 
1665     /**
1666      * Returns a loaded keystore object of the appropriate keystore type.
1667      * First the keystore type is determined by probing the specified file.
1668      * Then a keystore object is instantiated and loaded using the data from
1669      * that file.
1670      * A {@code LoadStoreParameter} may be supplied which specifies how to
1671      * unlock the keystore data or perform an integrity check.
1672      *
1673      * <p>
1674      * This method traverses the list of registered security {@linkplain
1675      * Provider providers}, starting with the most preferred Provider.
1676      * For each {@link KeyStoreSpi} implementation supported by a
1677      * Provider, it invokes the {@link
1678      * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
1679      * determine if it supports the specified keystore.
1680      * A new KeyStore object is returned that encapsulates the KeyStoreSpi
1681      * implementation from the first Provider that supports the specified file.
1682      *
1683      * <p> Note that the list of registered providers may be retrieved via
1684      * the {@link Security#getProviders() Security.getProviders()} method.
1685      *
1686      * @param  file the keystore file
1687      * @param  param the {@code LoadStoreParameter} that specifies how to load
1688      *             the keystore, which may be {@code null}
1689      *
1690      * @return a keystore object loaded with keystore data
1691      *
1692      * @throws KeyStoreException if no Provider supports a KeyStoreSpi
1693      *             implementation for the specified keystore file.
1694      * @throws IOException if there is an I/O or format problem with the
1695      *             keystore data. If the error is due to an incorrect
1696      *             {@code ProtectionParameter} (e.g. wrong password)
1697      *             the {@link Throwable#getCause cause} of the
1698      *             {@code IOException} should be an
1699      *             {@code UnrecoverableKeyException}.
1700      * @throws NoSuchAlgorithmException if the algorithm used to check the
1701      *             integrity of the keystore cannot be found.
1702      * @throws CertificateException if any of the certificates in the
1703      *             keystore could not be loaded.
1704      * @throws IllegalArgumentException if file does not exist or does not
1705      *             refer to a normal file, or if param is not recognized.
1706      * @throws NullPointerException if file is {@code null}.
1707      * @throws SecurityException if a security manager exists and its
1708      *             {@link java.lang.SecurityManager#checkRead} method denies
1709      *             read access to the specified file.
1710      *
1711      * @see Provider
1712      *
1713      * @since 1.9
1714      */
1715     public static final KeyStore getInstance(File file,
1716         LoadStoreParameter param) throws KeyStoreException, IOException,
1717             NoSuchAlgorithmException, CertificateException {
1718         return getInstance(file, null, param, false);
1719     }
1720 
1721     // Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter)
1722     private static final KeyStore getInstance(File file, char[] password,
1723         LoadStoreParameter param, boolean hasPassword)
1724             throws KeyStoreException, IOException, NoSuchAlgorithmException,
1725                 CertificateException {
1726 
1727         if (file == null) {
1728             throw new NullPointerException();
1729         }
1730 
1731         if (file.isFile() == false) {
1732             throw new IllegalArgumentException(
1733                 "File does not exist or it does not refer to a normal file: " +
1734                     file);
1735         }
1736 
1737         KeyStore keystore = null;
1738 
1739         try (DataInputStream dataStream =
1740             new DataInputStream(
1741                 new BufferedInputStream(
1742                     new FileInputStream(file)))) {
1743 
1744             dataStream.mark(Integer.MAX_VALUE);
1745 
1746             // Detect the keystore type
1747             for (String type : Security.getAlgorithms("KeyStore")) {
1748                 Object[] objs = null;
1749 
1750                 try {
1751                     objs = Security.getImpl(type, "KeyStore", (String)null);
1752 
1753                     KeyStoreSpi impl = (KeyStoreSpi)objs[0];
1754                     if (impl.engineProbe(dataStream)) {
1755 
1756                         if (kdebug != null) {
1757                             kdebug.println(type + " keystore detected: " +
1758                                 file);
1759                         }
1760 
1761                         keystore = new KeyStore(impl, (Provider)objs[1], type);
1762                         break;
1763                     }
1764                 } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
1765                     // ignore
1766                     if (kdebug != null) {
1767                         kdebug.println(type + " not found - " + e);
1768                     }
1769                 } catch (IOException e) {
1770                     // ignore
1771                     if (kdebug != null) {
1772                         kdebug.println("I/O error in " + file + " - " + e);
1773                     }
1774                 }
1775                 dataStream.reset(); // prepare the stream for the next probe
1776             }
1777 
1778             // Load the keystore data
1779             if (keystore != null) {
1780                 if (hasPassword) {
1781                     dataStream.reset(); // prepare the stream for loading
1782                     keystore.load(dataStream, password);
1783                 } else {
1784                     keystore.load(param);
1785                 }
1786                 return keystore;
1787             }
1788         }
1789 
1790         throw new KeyStoreException("Unrecognized keystore format: " +
1791             keystore);
1792     }
1793 
1794     /**
1795      * A description of a to-be-instantiated KeyStore object.
1796      *
1797      * <p>An instance of this class encapsulates the information needed to
1798      * instantiate and initialize a KeyStore object. That process is
1799      * triggered when the {@linkplain #getKeyStore} method is called.
1800      *
1801      * <p>This makes it possible to decouple configuration from KeyStore
1802      * object creation and e.g. delay a password prompt until it is
1803      * needed.
1804      *
1805      * @see KeyStore
1806      * @see javax.net.ssl.KeyStoreBuilderParameters
1807      * @since 1.5
1808      */
1809     public static abstract class Builder {
1810 
1811         // maximum times to try the callbackhandler if the password is wrong
1812         static final int MAX_CALLBACK_TRIES = 3;
1813 
1814         /**
1815          * Construct a new Builder.
1816          */
1817         protected Builder() {
1818             // empty
1819         }
1820 
1821         /**
1822          * Returns the KeyStore described by this object.
1823          *
1824          * @return the {@code KeyStore} described by this object
1825          * @exception KeyStoreException if an error occurred during the
1826          *   operation, for example if the KeyStore could not be
1827          *   instantiated or loaded
1828          */
1829         public abstract KeyStore getKeyStore() throws KeyStoreException;
1830 
1831         /**
1832          * Returns the ProtectionParameters that should be used to obtain
1833          * the {@link KeyStore.Entry Entry} with the given alias.
1834          * The {@code getKeyStore} method must be invoked before this
1835          * method may be called.
1836          *
1837          * @return the ProtectionParameters that should be used to obtain
1838          *   the {@link KeyStore.Entry Entry} with the given alias.
1839          * @param alias the alias of the KeyStore entry
1840          * @throws NullPointerException if alias is null
1841          * @throws KeyStoreException if an error occurred during the
1842          *   operation
1843          * @throws IllegalStateException if the getKeyStore method has
1844          *   not been invoked prior to calling this method
1845          */
1846         public abstract ProtectionParameter getProtectionParameter(String alias)
1847             throws KeyStoreException;
1848 
1849         /**
1850          * Returns a new Builder that encapsulates the given KeyStore.
1851          * The {@linkplain #getKeyStore} method of the returned object
1852          * will return {@code keyStore}, the {@linkplain
1853          * #getProtectionParameter getProtectionParameter()} method will
1854          * return {@code protectionParameters}.
1855          *
1856          * <p> This is useful if an existing KeyStore object needs to be
1857          * used with Builder-based APIs.
1858          *
1859          * @return a new Builder object
1860          * @param keyStore the KeyStore to be encapsulated
1861          * @param protectionParameter the ProtectionParameter used to
1862          *   protect the KeyStore entries
1863          * @throws NullPointerException if keyStore or
1864          *   protectionParameters is null
1865          * @throws IllegalArgumentException if the keyStore has not been
1866          *   initialized
1867          */
1868         public static Builder newInstance(final KeyStore keyStore,
1869                 final ProtectionParameter protectionParameter) {
1870             if ((keyStore == null) || (protectionParameter == null)) {
1871                 throw new NullPointerException();
1872             }
1873             if (keyStore.initialized == false) {
1874                 throw new IllegalArgumentException("KeyStore not initialized");
1875             }
1876             return new Builder() {
1877                 private volatile boolean getCalled;
1878 
1879                 public KeyStore getKeyStore() {
1880                     getCalled = true;
1881                     return keyStore;
1882                 }
1883 
1884                 public ProtectionParameter getProtectionParameter(String alias)
1885                 {
1886                     if (alias == null) {
1887                         throw new NullPointerException();
1888                     }
1889                     if (getCalled == false) {
1890                         throw new IllegalStateException
1891                             ("getKeyStore() must be called first");
1892                     }
1893                     return protectionParameter;
1894                 }
1895             };
1896         }
1897 
1898         /**
1899          * Returns a new Builder object.
1900          *
1901          * <p>The first call to the {@link #getKeyStore} method on the returned
1902          * builder will create a KeyStore of type {@code type} and call
1903          * its {@link KeyStore#load load()} method.
1904          * The {@code inputStream} argument is constructed from
1905          * {@code file}.
1906          * If {@code protection} is a
1907          * {@code PasswordProtection}, the password is obtained by
1908          * calling the {@code getPassword} method.
1909          * Otherwise, if {@code protection} is a
1910          * {@code CallbackHandlerProtection}, the password is obtained
1911          * by invoking the CallbackHandler.
1912          *
1913          * <p>Subsequent calls to {@link #getKeyStore} return the same object
1914          * as the initial call. If the initial call failed with a
1915          * KeyStoreException, subsequent calls also throw a
1916          * KeyStoreException.
1917          *
1918          * <p>The KeyStore is instantiated from {@code provider} if
1919          * non-null. Otherwise, all installed providers are searched.
1920          *
1921          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1922          * will return a {@link KeyStore.PasswordProtection PasswordProtection}
1923          * object encapsulating the password that was used to invoke the
1924          * {@code load} method.
1925          *
1926          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1927          * within the {@link AccessControlContext} of the code invoking this
1928          * method.
1929          *
1930          * @return a new Builder object
1931          * @param type the type of KeyStore to be constructed
1932          * @param provider the provider from which the KeyStore is to
1933          *   be instantiated (or null)
1934          * @param file the File that contains the KeyStore data
1935          * @param protection the ProtectionParameter securing the KeyStore data
1936          * @throws NullPointerException if type, file or protection is null
1937          * @throws IllegalArgumentException if protection is not an instance
1938          *   of either PasswordProtection or CallbackHandlerProtection; or
1939          *   if file does not exist or does not refer to a normal file
1940          */
1941         public static Builder newInstance(String type, Provider provider,
1942                 File file, ProtectionParameter protection) {
1943             if ((type == null) || (file == null) || (protection == null)) {
1944                 throw new NullPointerException();
1945             }
1946             if ((protection instanceof PasswordProtection == false) &&
1947                 (protection instanceof CallbackHandlerProtection == false)) {
1948                 throw new IllegalArgumentException
1949                 ("Protection must be PasswordProtection or " +
1950                  "CallbackHandlerProtection");
1951             }
1952             if (file.isFile() == false) {
1953                 throw new IllegalArgumentException
1954                     ("File does not exist or it does not refer " +
1955                      "to a normal file: " + file);
1956             }
1957             return new FileBuilder(type, provider, file, protection,
1958                 AccessController.getContext());
1959         }
1960 
1961         /**
1962          * Returns a new Builder object.
1963          *
1964          * <p>The first call to the {@link #getKeyStore} method on the returned
1965          * builder will create a KeyStore using {@code file} to detect the
1966          * keystore type and then call its {@link KeyStore#load load()} method.
1967          * It uses the same algorithm to determine the keystore type as
1968          * described in {@link KeyStore#getInstance(File, LoadStoreParameter)}.
1969          * The {@code inputStream} argument is constructed from {@code file}.
1970          * If {@code protection} is a {@code PasswordProtection}, the password
1971          * is obtained by calling the {@code getPassword} method.
1972          * Otherwise, if {@code protection} is a
1973          * {@code CallbackHandlerProtection},
1974          * the password is obtained by invoking the CallbackHandler.
1975          *
1976          * <p>Subsequent calls to {@link #getKeyStore} return the same object
1977          * as the initial call. If the initial call failed with a
1978          * KeyStoreException, subsequent calls also throw a KeyStoreException.
1979          *
1980          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1981          * will return a {@link KeyStore.PasswordProtection PasswordProtection}
1982          * object encapsulating the password that was used to invoke the
1983          * {@code load} method.
1984          *
1985          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1986          * within the {@link AccessControlContext} of the code invoking this
1987          * method.
1988          *
1989          * @return a new Builder object
1990          * @param file the File that contains the KeyStore data
1991          * @param protection the ProtectionParameter securing the KeyStore data
1992          * @throws NullPointerException if file or protection is null
1993          * @throws IllegalArgumentException if protection is not an instance
1994          *   of either PasswordProtection or CallbackHandlerProtection; or
1995          *   if file does not exist or does not refer to a normal file
1996          *
1997          * @since 1.9
1998          */
1999         public static Builder newInstance(File file,
2000             ProtectionParameter protection) {
2001 
2002             return newInstance("", null, file, protection);
2003         }
2004 
2005         private static final class FileBuilder extends Builder {
2006 
2007             private final String type;
2008             private final Provider provider;
2009             private final File file;
2010             private ProtectionParameter protection;
2011             private ProtectionParameter keyProtection;
2012             private final AccessControlContext context;
2013 
2014             private KeyStore keyStore;
2015 
2016             private Throwable oldException;
2017 
2018             FileBuilder(String type, Provider provider, File file,
2019                     ProtectionParameter protection,
2020                     AccessControlContext context) {
2021                 this.type = type;
2022                 this.provider = provider;
2023                 this.file = file;
2024                 this.protection = protection;
2025                 this.context = context;
2026             }
2027 
2028             public synchronized KeyStore getKeyStore() throws KeyStoreException
2029             {
2030                 if (keyStore != null) {
2031                     return keyStore;
2032                 }
2033                 if (oldException != null) {
2034                     throw new KeyStoreException
2035                         ("Previous KeyStore instantiation failed",
2036                          oldException);
2037                 }
2038                 PrivilegedExceptionAction<KeyStore> action =
2039                         new PrivilegedExceptionAction<KeyStore>() {
2040                     public KeyStore run() throws Exception {
2041                         if (protection instanceof CallbackHandlerProtection == false) {
2042                             return run0();
2043                         }
2044                         // when using a CallbackHandler,
2045                         // reprompt if the password is wrong
2046                         int tries = 0;
2047                         while (true) {
2048                             tries++;
2049                             try {
2050                                 return run0();
2051                             } catch (IOException e) {
2052                                 if ((tries < MAX_CALLBACK_TRIES)
2053                                         && (e.getCause() instanceof UnrecoverableKeyException)) {
2054                                     continue;
2055                                 }
2056                                 throw e;
2057                             }
2058                         }
2059                     }
2060                     public KeyStore run0() throws Exception {
2061                         KeyStore ks;
2062                         char[] password = null;
2063 
2064                         // Acquire keystore password
2065                         if (protection instanceof PasswordProtection) {
2066                             password =
2067                                 ((PasswordProtection)protection).getPassword();
2068                             keyProtection = protection;
2069                         } else {
2070                             CallbackHandler handler =
2071                                 ((CallbackHandlerProtection)protection)
2072                                     .getCallbackHandler();
2073                             PasswordCallback callback = new PasswordCallback
2074                                 ("Password for keystore " + file.getName(),
2075                                     false);
2076                             handler.handle(new Callback[] {callback});
2077                             password = callback.getPassword();
2078                             if (password == null) {
2079                                 throw new KeyStoreException("No password" +
2080                                                             " provided");
2081                             }
2082                             callback.clearPassword();
2083                             keyProtection = new PasswordProtection(password);
2084                         }
2085 
2086                         if (type.isEmpty()) {
2087                             // Instantiate keystore and load keystore data
2088                             ks = KeyStore.getInstance(file, password);
2089                         } else {
2090                             // Instantiate keystore
2091                             if (provider == null) {
2092                                 ks = KeyStore.getInstance(type);
2093                             } else {
2094                                 ks = KeyStore.getInstance(type, provider);
2095                             }
2096                             // Load keystore data
2097                             try (InputStream in = new FileInputStream(file)) {
2098                                 ks.load(in, password);
2099                             }
2100                         }
2101                         return ks;
2102                     }
2103                 };
2104                 try {
2105                     keyStore = AccessController.doPrivileged(action, context);
2106                     return keyStore;
2107                 } catch (PrivilegedActionException e) {
2108                     oldException = e.getCause();
2109                     throw new KeyStoreException
2110                         ("KeyStore instantiation failed", oldException);
2111                 }
2112             }
2113 
2114             public synchronized ProtectionParameter
2115                         getProtectionParameter(String alias) {
2116                 if (alias == null) {
2117                     throw new NullPointerException();
2118                 }
2119                 if (keyStore == null) {
2120                     throw new IllegalStateException
2121                         ("getKeyStore() must be called first");
2122                 }
2123                 return keyProtection;
2124             }
2125         }
2126 
2127         /**
2128          * Returns a new Builder object.
2129          *
2130          * <p>Each call to the {@link #getKeyStore} method on the returned
2131          * builder will return a new KeyStore object of type {@code type}.
2132          * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
2133          * method is invoked using a
2134          * {@code LoadStoreParameter} that encapsulates
2135          * {@code protection}.
2136          *
2137          * <p>The KeyStore is instantiated from {@code provider} if
2138          * non-null. Otherwise, all installed providers are searched.
2139          *
2140          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
2141          * will return {@code protection}.
2142          *
2143          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
2144          * within the {@link AccessControlContext} of the code invoking this
2145          * method.
2146          *
2147          * @return a new Builder object
2148          * @param type the type of KeyStore to be constructed
2149          * @param provider the provider from which the KeyStore is to
2150          *   be instantiated (or null)
2151          * @param protection the ProtectionParameter securing the Keystore
2152          * @throws NullPointerException if type or protection is null
2153          */
2154         public static Builder newInstance(final String type,
2155                 final Provider provider, final ProtectionParameter protection) {
2156             if ((type == null) || (protection == null)) {
2157                 throw new NullPointerException();
2158             }
2159             final AccessControlContext context = AccessController.getContext();
2160             return new Builder() {
2161                 private volatile boolean getCalled;
2162                 private IOException oldException;
2163 
2164                 private final PrivilegedExceptionAction<KeyStore> action
2165                         = new PrivilegedExceptionAction<KeyStore>() {
2166 
2167                     public KeyStore run() throws Exception {
2168                         KeyStore ks;
2169                         if (provider == null) {
2170                             ks = KeyStore.getInstance(type);
2171                         } else {
2172                             ks = KeyStore.getInstance(type, provider);
2173                         }
2174                         LoadStoreParameter param = new SimpleLoadStoreParameter(protection);
2175                         if (protection instanceof CallbackHandlerProtection == false) {
2176                             ks.load(param);
2177                         } else {
2178                             // when using a CallbackHandler,
2179                             // reprompt if the password is wrong
2180                             int tries = 0;
2181                             while (true) {
2182                                 tries++;
2183                                 try {
2184                                     ks.load(param);
2185                                     break;
2186                                 } catch (IOException e) {
2187                                     if (e.getCause() instanceof UnrecoverableKeyException) {
2188                                         if (tries < MAX_CALLBACK_TRIES) {
2189                                             continue;
2190                                         } else {
2191                                             oldException = e;
2192                                         }
2193                                     }
2194                                     throw e;
2195                                 }
2196                             }
2197                         }
2198                         getCalled = true;
2199                         return ks;
2200                     }
2201                 };
2202 
2203                 public synchronized KeyStore getKeyStore()
2204                         throws KeyStoreException {
2205                     if (oldException != null) {
2206                         throw new KeyStoreException
2207                             ("Previous KeyStore instantiation failed",
2208                              oldException);
2209                     }
2210                     try {
2211                         return AccessController.doPrivileged(action, context);
2212                     } catch (PrivilegedActionException e) {
2213                         Throwable cause = e.getCause();
2214                         throw new KeyStoreException
2215                             ("KeyStore instantiation failed", cause);
2216                     }
2217                 }
2218 
2219                 public ProtectionParameter getProtectionParameter(String alias)
2220                 {
2221                     if (alias == null) {
2222                         throw new NullPointerException();
2223                     }
2224                     if (getCalled == false) {
2225                         throw new IllegalStateException
2226                             ("getKeyStore() must be called first");
2227                     }
2228                     return protection;
2229                 }
2230             };
2231         }
2232 
2233     }
2234 
2235     static class SimpleLoadStoreParameter implements LoadStoreParameter {
2236 
2237         private final ProtectionParameter protection;
2238 
2239         SimpleLoadStoreParameter(ProtectionParameter protection) {
2240             this.protection = protection;
2241         }
2242 
2243         public ProtectionParameter getProtectionParameter() {
2244             return protection;
2245         }
2246     }
2247 }