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