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