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