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