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