OSDN Git Service

Fix PKCS12 and BKS KeyStore as well as SSL renegotiation
authorBrian Carlstrom <bdc@google.com>
Wed, 14 Jul 2010 05:54:39 +0000 (22:54 -0700)
committerBrian Carlstrom <bdc@google.com>
Fri, 16 Jul 2010 18:33:07 +0000 (11:33 -0700)
Summary:
- Added KeyStoreTest and fixed PKCS and BKS keystores to be fully functional
- KeyStore and KeyStoreImpl improvements in libcore and bouncycastle for more RI-like behavior
- SSL Renegotiation fix for new implementation

Details:

external/bouncycastle

   TwoFish added back for BKS KeyStore. Like RC2, it not supported as
   a general cipher, but instead used internally for KeyStore
   implementation.

src/main/java/org/bouncycastle/crypto/engines/TwofishEngine.java
bouncycastle.config

    Added back PBEWITHSHAANDTWOFISH, PBEWITHSHAANDTWOFISH-CBC,
    PBEWITHSHA1ANDRC2-CBC, PBEWITHHMACSHA, PBEWITHHMACSHA1 to support
    PKCS12 and BKS KeyStore implementations (as determined by new
    KeyStoreTest)

src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
src/main/java/org/bouncycastle/jce/provider/JCEBlockCipher.java
src/main/java/org/bouncycastle/jce/provider/JCEMac.java
src/main/java/org/bouncycastle/jce/provider/JCESecretKeyFactory.java

    Don't throw an error when deleting a non-existing KeyStore entry. The
    RI documentation (and behavior) says it throws an error when it fails
    to remove an entry, not when the entry does not exist.

src/main/java/org/bouncycastle/jce/provider/JDKKeyStore.java
src/main/java/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java

    Try to make BC's PKCS KeyStore have a more RI-like getCreationDate behavior

src/main/java/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java

    Make BC's PKCS KeyStore failfast on setting non-supported key,
    instead of failing later on get.

src/main/java/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java

    Make BC's PKCS KeyStore handle setting a PrivateKey with an emtpy chain.

src/main/java/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java

    Add more general avoidance of NullPointerExceptions on null aliases

src/main/java/org/bouncycastle/jce/provider/JDKPKCS12KeyStore.java

    Added notes about changes improvements

patches/README

    Regenerated patch with above changes

patches/android.patch

libcore

    KeyStore improvements based on KeyStoreTest

    - Fix UnrecoverableKeyException to be a subclass of
      UnrecoverableEntryException, which was keeping the new
      KeyStoreTest from compiling.

luni/src/main/java/java/security/UnrecoverableKeyException.java

    - Fix to not convert UnrecoverableKeyException to KeyStoreException,
      which was only being done because of the UnrecoverableKeyException
      superclass bug.

luni/src/main/java/java/security/KeyStoreSpi.java

    - Harmony KeyStore was being overly aggresive about throwing on null
      alias arguments in cases where the RI was happy to pass them to the
      KeyStoreSpi.

luni/src/main/java/java/security/KeyStore.java

    - New test after PKCS12 regresion. It enumerates and excercises
      all methods on all available KeyStore
      implementations. Unfortunately, the main varieties of KeyStores
      made this a lot more complicated than I was originally
      expecting. It does clarifiy the differences between the RI and
      BC KeyStore implementations, especially for PKCS12, where in
      some ways the RI is more feature complete (setting key via
      byte[]), but in other ways BC goes beyond some RI limitations
      (allowing storage of certificates).

luni/src/test/java/java/security/KeyStoreTest.java

   TestKeyStore improvements while writing KeyStoreTest
   - Renamed "keyStorePassword" working usages to clarify if it really
     means the "storePassword" on the whole KeyStore, or if it is a
     "keyPassword" on individual keys.
   - Moved TestKeyStore from javax.net.ssl to java.security

luni/src/test/java/javax/net/ssl/SSLContextTest.java
luni/src/test/java/javax/net/ssl/SSLEngineTest.java
luni/src/test/java/javax/net/ssl/SSLSessionTest.java
luni/src/test/java/javax/net/ssl/SSLSocketTest.java
support/src/test/java/java/security/StandardNames.java
support/src/test/java/java/security/TestKeyStore.java
support/src/test/java/javax/net/ssl/TestKeyStore.java
support/src/test/java/javax/net/ssl/TestSSLContext.java

    Fixing up SSL renegotiation support. Now that we are not trying to
    prevent renegotiation, make sure it is working correctly.

    - Remove SSL_VERIFY_CLIENT_ONCE to take the default behavior of
      re-requesting client certificate on renegotiation.

luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java

    - Updated comments to reflect renegotiation. Bug fix to not clear
      out callback reference on handshake complete, since we need it for
      renegotiation.

luni/src/main/native/NativeCrypto.cpp

   Updated for PKCS12 KeyStore support

support/src/test/java/java/security/StandardNames.java

   Added javadoc when writint KeyStoreTest

luni/src/test/java/java/security/ProviderTest.java

frameworks/base

    Tracking changes to UnrecoverableKeyException superclass

api/8.xml
api/current.xml

Change-Id: I6349dbfc02896417595b52e364ade8000b567615

15 files changed:
luni/src/main/java/java/security/KeyStore.java
luni/src/main/java/java/security/KeyStoreSpi.java
luni/src/main/java/java/security/UnrecoverableKeyException.java
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
luni/src/main/native/NativeCrypto.cpp
luni/src/test/java/java/security/KeyStoreTest.java [new file with mode: 0644]
luni/src/test/java/java/security/ProviderTest.java
luni/src/test/java/javax/net/ssl/SSLContextTest.java
luni/src/test/java/javax/net/ssl/SSLEngineTest.java
luni/src/test/java/javax/net/ssl/SSLSessionTest.java
luni/src/test/java/javax/net/ssl/SSLSocketTest.java
support/src/test/java/java/security/StandardNames.java
support/src/test/java/java/security/TestKeyStore.java [moved from support/src/test/java/javax/net/ssl/TestKeyStore.java with 87% similarity]
support/src/test/java/javax/net/ssl/TestSSLContext.java

index 8a5ddcf..38c2af5 100644 (file)
@@ -430,8 +430,6 @@ public class KeyStore {
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized, or if the entry
      *             can not be deleted.
-     * @throws NullPointerException
-     *             if {@code alias} is {@code null}.
      */
     public final void deleteEntry(String alias) throws KeyStoreException {
         if (!isInit) {
@@ -439,9 +437,6 @@ public class KeyStore {
             throwNotInitialized();
             // END android-changed
         }
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
         implSpi.engineDeleteEntry(alias);
     }
 
@@ -471,8 +466,6 @@ public class KeyStore {
      * @return {@code true} if the alias exists, {@code false} otherwise.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @throws NullPointerException
-     *             if {@code alias} is {@code null}.
      */
     public final boolean containsAlias(String alias) throws KeyStoreException {
         if (!isInit) {
@@ -480,9 +473,6 @@ public class KeyStore {
             throwNotInitialized();
             // END android-changed
         }
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
         return implSpi.engineContainsAlias(alias);
     }
 
@@ -511,8 +501,6 @@ public class KeyStore {
      * @return {@code true} if the given alias is associated with a key entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @throws NullPointerException
-     *             if {@code alias} is {@code null}.
      */
     public final boolean isKeyEntry(String alias) throws KeyStoreException {
         if (!isInit) {
@@ -520,9 +508,6 @@ public class KeyStore {
             throwNotInitialized();
             // END android-changed
         }
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
         return implSpi.engineIsKeyEntry(alias);
     }
 
@@ -536,8 +521,6 @@ public class KeyStore {
      *         entry.
      * @throws KeyStoreException
      *             if this {@code KeyStore} is not initialized.
-     * @throws NullPointerException
-     *             if {@code alias} is {@code null}.
      */
     public final boolean isCertificateEntry(String alias)
             throws KeyStoreException {
@@ -546,9 +529,6 @@ public class KeyStore {
             throwNotInitialized();
             // END android-changed
         }
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
         return implSpi.engineIsCertificateEntry(alias);
     }
 
@@ -1329,8 +1309,7 @@ public class KeyStore {
 
             if(isAllX509Certificates){
                 this.chain = new X509Certificate[chain.length];
-            }
-            else{
+            } else {
                 this.chain = new Certificate[chain.length];
             }
             System.arraycopy(chain, 0, this.chain, 0, chain.length);
index 8f2234c..01565f5 100644 (file)
@@ -320,7 +320,8 @@ public abstract class KeyStoreSpi {
                 throw new IllegalArgumentException(e);
             }
         }
-        throw new UnsupportedOperationException("protectionParameter is neither PasswordProtection nor CallbackHandlerProtection instance");
+        throw new UnsupportedOperationException("protectionParameter is neither PasswordProtection "
+                                                + "nor CallbackHandlerProtection instance");
     }
 
     /**
@@ -363,22 +364,18 @@ public abstract class KeyStoreSpi {
             } else if (protParam instanceof KeyStore.CallbackHandlerProtection) {
                 passW = getPasswordFromCallBack(protParam);
             } else {
-                throw new UnrecoverableEntryException("ProtectionParameter object is not " +
-                        "PasswordProtection: " + protParam);
+                throw new UnrecoverableEntryException("ProtectionParameter object is not "
+                                                      + "PasswordProtection: " + protParam);
             }
         }
         if (engineIsKeyEntry(alias)) {
-            try {
-                Key key = engineGetKey(alias, passW);
-                if (key instanceof PrivateKey) {
-                    return new KeyStore.PrivateKeyEntry((PrivateKey) key,
-                            engineGetCertificateChain(alias));
-                }
-                if (key instanceof SecretKey) {
-                    return new KeyStore.SecretKeyEntry((SecretKey) key);
-                }
-            } catch (UnrecoverableKeyException e) {
-                throw new KeyStoreException(e);
+            Key key = engineGetKey(alias, passW);
+            if (key instanceof PrivateKey) {
+                return new KeyStore.PrivateKeyEntry((PrivateKey) key,
+                                                    engineGetCertificateChain(alias));
+            }
+            if (key instanceof SecretKey) {
+                return new KeyStore.SecretKeyEntry((SecretKey) key);
             }
         }
         throw new NoSuchAlgorithmException("Unknown KeyStore.Entry object");
@@ -431,7 +428,8 @@ public abstract class KeyStoreSpi {
                     throw new KeyStoreException(e);
                 }
             } else {
-                throw new KeyStoreException("protParam should be PasswordProtection or CallbackHandlerProtection");
+                throw new KeyStoreException("protParam should be PasswordProtection or "
+                                            + "CallbackHandlerProtection");
             }
         }
 
@@ -449,8 +447,8 @@ public abstract class KeyStoreSpi {
             return;
         }
 
-        throw new KeyStoreException("Entry object is neither PrivateKeyObject nor SecretKeyEntry " +
-                "nor TrustedCertificateEntry: " + entry);
+        throw new KeyStoreException("Entry object is neither PrivateKeyObject nor SecretKeyEntry "
+                                    + "nor TrustedCertificateEntry: " + entry);
     }
 
     /**
index 59e3708..67273c1 100644 (file)
@@ -23,7 +23,7 @@ package java.security;
  *
  * @see KeyStore
  */
-public class UnrecoverableKeyException extends GeneralSecurityException {
+public class UnrecoverableKeyException extends UnrecoverableEntryException {
 
     private static final long serialVersionUID = 7275063078190151277L;
 
index 5de1e8e..7b5b611 100644 (file)
@@ -392,7 +392,6 @@ public final class NativeCrypto {
     public static final int SSL_VERIFY_NONE =                 0x00;
     public static final int SSL_VERIFY_PEER =                 0x01;
     public static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 0x02;
-    public static final int SSL_VERIFY_CLIENT_ONCE =          0x04;
 
     public static native void SSL_set_verify(int sslNativePointer, int mode) throws IOException;
 
index 3349926..2e496db 100644 (file)
@@ -346,13 +346,11 @@ public class OpenSSLSocketImpl
             if (sslParameters.getNeedClientAuth()) {
                 NativeCrypto.SSL_set_verify(sslNativePointer,
                                             NativeCrypto.SSL_VERIFY_PEER|
-                                            NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
-                                            NativeCrypto.SSL_VERIFY_CLIENT_ONCE);
+                                            NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
             // ... over just wanting it...
             } else if (sslParameters.getWantClientAuth()) {
                 NativeCrypto.SSL_set_verify(sslNativePointer,
-                                            NativeCrypto.SSL_VERIFY_PEER|
-                                            NativeCrypto.SSL_VERIFY_CLIENT_ONCE);
+                                            NativeCrypto.SSL_VERIFY_PEER);
             }
             // ... and it defaults properly so we don't need call SSL_set_verify in the common case.
 
index 52c7bc5..a39105b 100644 (file)
@@ -1152,20 +1152,19 @@ static jobjectArray getPrincipalBytes(JNIEnv* env, const STACK_OF(X509_NAME)* na
  * currently this seems a bit like overkill. Marking volatile at the very least.
  *
  * During handshaking, two additional fields are used to up-call into
- * Java to perform certificate verification and handshake completion.
+ * Java to perform certificate verification and handshake
+ * completion. These are also used in any renegotiation.
  *
  * (5) the JNIEnv so we can invoke the Java callback
  *
  * (6) a NativeCrypto.SSLHandshakeCallbacks instance for callbacks from native to Java
  *
- * These fields are cleared by the info_callback the handshake has
- * completed. SSL_VERIFY_CLIENT_ONCE is currently used to disable
- * renegotiation but if that changes, care would need to be taken to
- * maintain an appropriate JNIEnv on any downcall to openssl that
- * could result in an upcall to Java. The current code does try to
- * cover these cases by conditionally setting the JNIenv on calls that
- * can read and write to the SSL such as SSL_do_handshake, SSL_read,
- * SSL_write, and SSL_shutdown if handshaking is not complete.
+ * Because renegotiation can be requested by the peer at any time,
+ * care should be taken to maintain an appropriate JNIEnv on any
+ * downcall to openssl since it could result in an upcall to Java. The
+ * current code does try to cover these cases by conditionally setting
+ * the JNIenv on calls that can read and write to the SSL such as
+ * SSL_do_handshake, SSL_read, SSL_write, and SSL_shutdown.
  *
  * Finally, we have one other piece of state setup by OpenSSL callbacks:
  *
@@ -1262,10 +1261,6 @@ class AppData {
     void clearEnv() {
         env = NULL;
     }
-
-    void handshakeCompleted(JNIEnv* e) {
-        cleanupGlobalRef(e);
-    }
 };
 
 /**
@@ -1508,8 +1503,6 @@ static void info_callback(const SSL *ssl, int where, int ret __attribute__ ((unu
     if (env->ExceptionCheck()) {
         JNI_TRACE("ssl=%p info_callback exception", ssl);
     }
-
-    appData->handshakeCompleted(env);
     JNI_TRACE("ssl=%p info_callback completed", ssl);
 }
 
diff --git a/luni/src/test/java/java/security/KeyStoreTest.java b/luni/src/test/java/java/security/KeyStoreTest.java
new file mode 100644 (file)
index 0000000..8510801
--- /dev/null
@@ -0,0 +1,1843 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.security;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.security.KeyStore.Builder;
+import java.security.KeyStore.CallbackHandlerProtection;
+import java.security.KeyStore.Entry;
+import java.security.KeyStore.LoadStoreParameter;
+import java.security.KeyStore.PasswordProtection;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore.ProtectionParameter;
+import java.security.KeyStore.SecretKeyEntry;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import junit.framework.TestCase;
+
+public class KeyStoreTest extends TestCase {
+
+    private static final PrivateKeyEntry PRIVATE_KEY
+            = TestKeyStore.privateKey(TestKeyStore.getServer().keyStore,
+                                      TestKeyStore.getServer().keyPassword,
+                                      "RSA");
+    private static final PrivateKeyEntry PRIVATE_KEY_2
+            = TestKeyStore.privateKey(TestKeyStore.getClientCertificate().keyStore,
+                                      TestKeyStore.getClientCertificate().keyPassword,
+                                      "RSA");
+    private static final SecretKey SECRET_KEY = generateSecretKey();
+    private static final SecretKey SECRET_KEY_2 = generateSecretKey();
+
+    private static SecretKey generateSecretKey() {
+        try {
+            KeyGenerator kg = KeyGenerator.getInstance("DES");
+            return kg.generateKey();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static final String ALIAS_PRIVATE = "private";
+    private static final String ALIAS_CERTIFICATE = "certificate";
+    private static final String ALIAS_SECRET = "secret";
+
+    private static final String ALIAS_ALT_CASE_PRIVATE = "pRiVaTe";
+    private static final String ALIAS_ALT_CASE_CERTIFICATE = "cErTiFiCaTe";
+    private static final String ALIAS_ALT_CASE_SECRET = "sEcRet";
+
+    private static final String ALIAS_NO_PASSWORD_PRIVATE = "private-no-password";
+    private static final String ALIAS_NO_PASSWORD_SECRET = "secret-no-password";
+
+    private static final char[] PASSWORD_STORE = "store password".toCharArray();
+    private static final char[] PASSWORD_KEY = "key password".toCharArray();
+    private static final char[] PASSWORD_BAD = "dummy".toCharArray();
+
+    private static final ProtectionParameter PARAM_STORE = new PasswordProtection(PASSWORD_STORE);
+    private static final ProtectionParameter PARAM_KEY = new PasswordProtection(PASSWORD_KEY);
+    private static final ProtectionParameter PARAM_BAD = new PasswordProtection(PASSWORD_BAD);
+
+    public static List<KeyStore> keyStores () throws Exception {
+        List<KeyStore> keyStores = new ArrayList<KeyStore>();
+        Provider[] providers = Security.getProviders();
+        for (Provider provider : providers) {
+            Set<Provider.Service> services = provider.getServices();
+            for (Provider.Service service : services) {
+                String type = service.getType();
+                if (!type.equals("KeyStore")) {
+                    continue;
+                }
+                String algorithm = service.getAlgorithm();
+                KeyStore ks = KeyStore.getInstance(algorithm, provider);
+                assertEquals(provider, ks.getProvider());
+                assertEquals(algorithm, ks.getType());
+                if (!isUnsupported(ks)) {
+                    keyStores.add(ks);
+                }
+            }
+        }
+        return keyStores;
+    }
+
+    private static boolean isSecretKeyEnabled(KeyStore ks) {
+        // JKS key stores cannot store secret keys, neither can the RI's PKCS12
+        return (!(ks.getType().equals("JKS")
+                  || ks.getType().equals("CaseExactJKS")
+                  || (ks.getType().equals("PKCS12"))));
+    }
+
+    private static boolean isCertificateEnabled(KeyStore ks) {
+        // RI can't handle certificate in PKCS12, but BC can
+        return (!(ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("SunJSSE")));
+    }
+
+    private static boolean isCaseSensitive(KeyStore ks) {
+        return (ks.getType().equals("CaseExactJKS")
+                || ks.getType().equals("BKS")
+                || ks.getType().equals("BouncyCastle"));
+
+    }
+
+    private static boolean isUnsupported(KeyStore ks) {
+        // Don't bother testing BC on RI
+        return (StandardNames.IS_RI && ks.getProvider().getName().equals("BC"));
+    }
+
+    private static boolean isNullPasswordAllowed(KeyStore ks) {
+        return (!(ks.getType().equals("JKS")
+                  || ks.getType().equals("CaseExactJKS")
+                  || ks.getType().equals("JCEKS")
+                  || ks.getType().equals("PKCS12")));
+    }
+
+    private static boolean isKeyPasswordIgnored(KeyStore ks) {
+        // BouncyCastle's PKCS12 ignores the key password unlike the RI which requires it
+        return (ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("BC"));
+    }
+
+    private static boolean isSetKeyByteArrayUnimplemented(KeyStore ks) {
+        // All of BouncyCastle's
+        // KeyStore.setKeyEntry(String,byte[],char[]) implementations
+        // throw RuntimeException
+        return (ks.getProvider().getName().equals("BC"));
+    }
+
+    public static void populate(KeyStore ks) throws Exception {
+        ks.load(null, null);
+        setPrivateKey(ks);
+        if (isNullPasswordAllowed(ks)) {
+            ks.setKeyEntry(ALIAS_NO_PASSWORD_PRIVATE,
+                           PRIVATE_KEY.getPrivateKey(),
+                           null,
+                           PRIVATE_KEY.getCertificateChain());
+        }
+        if (isCertificateEnabled(ks)) {
+            ks.setCertificateEntry(ALIAS_CERTIFICATE,
+                                   PRIVATE_KEY.getCertificate());
+        }
+        if (isSecretKeyEnabled(ks)) {
+            setSecretKey(ks);
+            if (isNullPasswordAllowed(ks)) {
+                ks.setKeyEntry(ALIAS_NO_PASSWORD_SECRET,
+                               SECRET_KEY,
+                               null,
+                               null);
+            }
+        }
+    }
+
+    public static void setPrivateKey(KeyStore ks) throws Exception {
+        setPrivateKey(ks, ALIAS_PRIVATE);
+    }
+    public static void setPrivateKey(KeyStore ks, String alias) throws Exception {
+        setPrivateKey(ks, alias, PRIVATE_KEY);
+    }
+    public static void setPrivateKey(KeyStore ks,
+                                     String alias,
+                                     PrivateKeyEntry privateKey)
+            throws Exception {
+        ks.setKeyEntry(alias,
+                       privateKey.getPrivateKey(),
+                       PASSWORD_KEY,
+                       privateKey.getCertificateChain());
+    }
+
+    public static void setPrivateKeyBytes(KeyStore ks) throws Exception {
+        setPrivateKeyBytes(ks, ALIAS_PRIVATE);
+    }
+    public static void setPrivateKeyBytes(KeyStore ks, String alias) throws Exception {
+        setPrivateKeyBytes(ks, alias, PRIVATE_KEY);
+    }
+    public static void setPrivateKeyBytes(KeyStore ks,
+                                     String alias,
+                                     PrivateKeyEntry privateKey)
+            throws Exception {
+        ks.setKeyEntry(alias,
+                       privateKey.getPrivateKey().getEncoded(),
+                       privateKey.getCertificateChain());
+    }
+
+    public static void setSecretKey(KeyStore ks) throws Exception {
+        setSecretKey(ks, ALIAS_SECRET);
+    }
+    public static void setSecretKey(KeyStore ks, String alias) throws Exception {
+        setSecretKey(ks, alias, SECRET_KEY);
+    }
+    public static void setSecretKey(KeyStore ks, String alias, SecretKey key) throws Exception {
+        ks.setKeyEntry(alias,
+                       key,
+                       PASSWORD_KEY,
+                       null);
+    }
+
+    public static void setSecretKeyBytes(KeyStore ks) throws Exception {
+        setSecretKeyBytes(ks, ALIAS_SECRET);
+    }
+    public static void setSecretKeyBytes(KeyStore ks, String alias) throws Exception {
+        setSecretKeyBytes(ks, alias, SECRET_KEY);
+    }
+    public static void setSecretKeyBytes(KeyStore ks, String alias, SecretKey key)
+            throws Exception {
+        ks.setKeyEntry(alias,
+                       key.getEncoded(),
+                       null);
+    }
+
+    public static void setCertificate(KeyStore ks) throws Exception {
+        setCertificate(ks, ALIAS_CERTIFICATE);
+    }
+    public static void setCertificate(KeyStore ks, String alias) throws Exception {
+        setCertificate(ks, alias, PRIVATE_KEY.getCertificate());
+    }
+    public static void setCertificate(KeyStore ks, String alias, Certificate certificate)
+            throws Exception {
+        ks.setCertificateEntry(alias, certificate);
+    }
+
+    public static void assertPrivateKey(Key actual)
+            throws Exception {
+        assertEquals(PRIVATE_KEY.getPrivateKey(), actual);
+    }
+    public static void assertPrivateKey2(Key actual)
+            throws Exception {
+        assertEquals(PRIVATE_KEY_2.getPrivateKey(), actual);
+    }
+    public static void assertPrivateKey(Entry actual)
+            throws Exception {
+        assertSame(PrivateKeyEntry.class, actual.getClass());
+        PrivateKeyEntry privateKey = (PrivateKeyEntry) actual;
+        assertEquals(PRIVATE_KEY.getPrivateKey(), privateKey.getPrivateKey());
+        assertEquals(PRIVATE_KEY.getCertificate(), privateKey.getCertificate());
+        assertEquals(Arrays.asList(PRIVATE_KEY.getCertificateChain()),
+                     Arrays.asList(privateKey.getCertificateChain()));
+    }
+
+    public static void assertSecretKey(Key actual)
+            throws Exception {
+        assertEquals(SECRET_KEY, actual);
+    }
+    public static void assertSecretKey2(Key actual)
+            throws Exception {
+        assertEquals(SECRET_KEY_2, actual);
+    }
+    public static void assertSecretKey(Entry actual)
+            throws Exception {
+        assertSame(SecretKeyEntry.class, actual.getClass());
+        assertEquals(SECRET_KEY, ((SecretKeyEntry) actual).getSecretKey());
+    }
+
+    public static void assertCertificate(Certificate actual)
+            throws Exception {
+        assertEquals(PRIVATE_KEY.getCertificate(), actual);
+    }
+    public static void assertCertificate2(Certificate actual)
+            throws Exception {
+        assertEquals(PRIVATE_KEY_2.getCertificate(), actual);
+    }
+    public static void assertCertificate(Entry actual)
+            throws Exception {
+        assertSame(TrustedCertificateEntry.class, actual.getClass());
+        assertEquals(PRIVATE_KEY.getCertificate(),
+                     ((TrustedCertificateEntry) actual).getTrustedCertificate());
+    }
+
+    public static void assertCertificateChain(Certificate[] actual)
+            throws Exception {
+        assertEquals(Arrays.asList(PRIVATE_KEY.getCertificateChain()),
+                     Arrays.asList(actual));
+    }
+
+    public void test_KeyStore_create() throws Exception {
+        Provider[] providers = Security.getProviders();
+        for (Provider provider : providers) {
+            Set<Provider.Service> services = provider.getServices();
+            for (Provider.Service service : services) {
+                String type = service.getType();
+                if (!type.equals("KeyStore")) {
+                    continue;
+                }
+                String algorithm = service.getAlgorithm();
+                KeyStore ks = KeyStore.getInstance(algorithm, provider);
+                assertEquals(provider, ks.getProvider());
+                assertEquals(algorithm, ks.getType());
+            }
+        }
+    }
+
+    public void test_KeyStore_getInstance() throws Exception {
+        String type = KeyStore.getDefaultType();
+        try {
+            KeyStore.getInstance(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        assertNotNull(KeyStore.getInstance(type));
+
+        String providerName = StandardNames.SECURITY_PROVIDER_NAME;
+        try {
+            KeyStore.getInstance(null, (String)null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            KeyStore.getInstance(null, providerName);
+            fail();
+        } catch (Exception e) {
+            if (e.getClass() != NullPointerException.class
+                && e.getClass() != KeyStoreException.class) {
+                throw e;
+            }
+        }
+        try {
+            KeyStore.getInstance(type, (String)null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        assertNotNull(KeyStore.getInstance(type, providerName));
+
+        Provider provider = Security.getProvider(providerName);
+        try {
+            KeyStore.getInstance(null, (Provider)null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            KeyStore.getInstance(null, provider);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            KeyStore.getInstance(type, (Provider)null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        assertNotNull(KeyStore.getInstance(type, provider));
+    }
+
+    public void test_KeyStore_getDefaultType() throws Exception {
+        String type = KeyStore.getDefaultType();
+        assertNotNull(type);
+        KeyStore ks = KeyStore.getInstance(type);
+        assertNotNull(ks);
+        assertEquals(type, ks.getType());
+    }
+
+    public void test_KeyStore_getProvider() throws Exception {
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        assertNotNull(ks.getProvider());
+        assertNotNull(StandardNames.SECURITY_PROVIDER_NAME, ks.getProvider().getName());
+
+        for (KeyStore keyStore : keyStores()) {
+            assertNotNull(keyStore.getProvider());
+        }
+    }
+
+    public void test_KeyStore_getType() throws Exception {
+        String type = KeyStore.getDefaultType();
+        KeyStore ks = KeyStore.getInstance(type);
+        assertNotNull(ks.getType());
+        assertNotNull(type, ks.getType());
+
+        for (KeyStore keyStore : keyStores()) {
+            assertNotNull(keyStore.getType());
+        }
+    }
+
+    public void test_KeyStore_getKey() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getKey(null, null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getKey(null, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.getKey(null, PASSWORD_KEY);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            assertNull(keyStore.getKey("", null));
+            assertNull(keyStore.getKey("", PASSWORD_KEY));
+
+            // test case sensitive
+            assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            if (isSecretKeyEnabled(keyStore)) {
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            }
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+            } else {
+                assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            }
+
+            // test with null passwords
+            if (isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else {
+                try {
+                    keyStore.getKey(ALIAS_PRIVATE, null);
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getKey(ALIAS_SECRET, null);
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+
+            // test with bad passwords
+            if (isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else {
+                try {
+                    keyStore.getKey(ALIAS_PRIVATE, PASSWORD_BAD);
+                    fail();
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getKey(ALIAS_SECRET, PASSWORD_BAD);
+                    fail();
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_getCertificateChain() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCertificateChain(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getCertificateChain(null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class) {
+                    throw e;
+                }
+            }
+            assertNull(keyStore.getCertificateChain(""));
+
+            // test case sensitive
+            assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getCertificateChain(ALIAS_ALT_CASE_PRIVATE));
+            } else {
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_ALT_CASE_PRIVATE));
+            }
+        }
+    }
+
+    public void test_KeyStore_getCertificate() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCertificate(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getCertificate(null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class) {
+                    throw e;
+                }
+            }
+            assertNull(keyStore.getCertificate(""));
+
+            // test case sensitive
+            if (isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            } else {
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            }
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else {
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_getCreationDate() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                assertNotNull(keyStore.getCreationDate(null));
+            } catch (KeyStoreException expected) {
+            }
+        }
+        long before = System.currentTimeMillis();
+        for (KeyStore keyStore : keyStores()) {
+            // add 1000 since some key stores round of time to nearest second
+            long after = System.currentTimeMillis() + 1000;
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getCreationDate(null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            assertNull(keyStore.getCreationDate(""));
+
+            // test case sensitive
+            if (isCertificateEnabled(keyStore)) {
+                Date date = keyStore.getCreationDate(ALIAS_CERTIFICATE);
+                assertNotNull(date);
+                assertTrue(before <= date.getTime());
+                assertTrue(date.getTime() <= after);
+            } else {
+                assertNull(keyStore.getCreationDate(ALIAS_CERTIFICATE));
+            }
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getCreationDate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else {
+                if (isCertificateEnabled(keyStore)) {
+                    Date date = keyStore.getCreationDate(ALIAS_ALT_CASE_CERTIFICATE);
+                    assertTrue(before <= date.getTime());
+                    assertTrue(date.getTime() <= after);
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setKeyEntry_Key() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.setKeyEntry(null, null, null, null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test odd inputs
+            try {
+                keyStore.setKeyEntry(null, null, null, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setKeyEntry(null, null, PASSWORD_KEY, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                     PRIVATE_KEY.getPrivateKey(),
+                                     PASSWORD_KEY,
+                                     null);
+                fail();
+            } catch (IllegalArgumentException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test case sensitive
+            assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            setPrivateKey(keyStore);
+            assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                setSecretKey(keyStore);
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, SECRET_KEY, PASSWORD_KEY, null);
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != KeyStoreException.class
+                        && e.getClass() != NullPointerException.class) {
+                        throw e;
+                    }
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            // test case insensitive
+
+            if (isCaseSensitive(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, PRIVATE_KEY_2);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKey(keyStore, ALIAS_ALT_CASE_SECRET, SECRET_KEY_2);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            } else {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, PRIVATE_KEY_2);
+                assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKey(keyStore, ALIAS_ALT_CASE_PRIVATE, SECRET_KEY_2);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test with null passwords
+            if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                     PRIVATE_KEY.getPrivateKey(),
+                                     null,
+                                     PRIVATE_KEY.getCertificateChain());
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                         PRIVATE_KEY.getPrivateKey(),
+                                         null,
+                                         PRIVATE_KEY.getCertificateChain());
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != KeyStoreException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                    keyStore.setKeyEntry(ALIAS_SECRET, SECRET_KEY, null, null);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, null));
+                } else {
+                    try {
+                        keyStore.setKeyEntry(ALIAS_SECRET, SECRET_KEY, null, null);
+                        fail();
+                    } catch (Exception e) {
+                        if (e.getClass() != UnrecoverableKeyException.class
+                            && e.getClass() != IllegalArgumentException.class
+                            && e.getClass() != KeyStoreException.class) {
+                            throw e;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setKeyEntry_array() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.setKeyEntry(null, null, null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test odd inputs
+            try {
+                keyStore.setKeyEntry(null, null, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class
+                    && e.getClass() != KeyStoreException.class
+                    && e.getClass() != RuntimeException.class) {
+                    throw e;
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isNullPasswordAllowed(keyStore)) {
+                // TODO Use EncryptedPrivateKeyInfo to protect keys if
+                // password is required.
+                continue;
+            }
+            if (isSetKeyByteArrayUnimplemented(keyStore)) {
+                continue;
+            }
+
+            keyStore.load(null, null);
+
+            // test case sensitive
+            assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            setPrivateKeyBytes(keyStore);
+            assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                setSecretKeyBytes(keyStore);
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, SECRET_KEY.getEncoded(), null);
+                    fail();
+                } catch (KeyStoreException expected) {
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isNullPasswordAllowed(keyStore)) {
+                // TODO Use EncryptedPrivateKeyInfo to protect keys if
+                // password is required.
+                continue;
+            }
+            if (isSetKeyByteArrayUnimplemented(keyStore)) {
+                continue;
+            }
+
+            populate(keyStore);
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, PRIVATE_KEY_2);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, SECRET_KEY_2);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            } else {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, PRIVATE_KEY_2);
+                assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, SECRET_KEY_2);
+                    assertSecretKey2(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setCertificateEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.setCertificateEntry(null, null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            // test odd inputs
+            try {
+                keyStore.setCertificateEntry(null, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+
+            // Sort of delete by setting null.  Note that even though
+            // certificiate is null, size doesn't change,
+            // isCertificateEntry returns true, and it is still listed in aliases.
+            if (isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                try {
+                    int size = keyStore.size();
+                    keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null);
+                    assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertEquals(size, keyStore.size());
+                    assertTrue(keyStore.isCertificateEntry(ALIAS_CERTIFICATE));
+                    assertTrue(Collections.list(keyStore.aliases()).contains(ALIAS_CERTIFICATE));
+                } catch (NullPointerException expectedSometimes) {
+                    assertEquals("PKCS12", keyStore.getType());
+                    assertEquals("BC", keyStore.getProvider().getName());
+                }
+            } else {
+                try {
+                    keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null);
+                } catch (KeyStoreException expected) {
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isCertificateEnabled(keyStore)) {
+                continue;
+            }
+
+            keyStore.load(null, null);
+
+            // test case sensitive
+            assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            setCertificate(keyStore);
+            assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isCertificateEnabled(keyStore)) {
+                continue;
+            }
+
+            populate(keyStore);
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                setCertificate(keyStore,
+                               ALIAS_ALT_CASE_CERTIFICATE,
+                               PRIVATE_KEY_2.getCertificate());
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertCertificate(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                setCertificate(keyStore,
+                               ALIAS_ALT_CASE_CERTIFICATE,
+                               PRIVATE_KEY_2.getCertificate());
+                assertCertificate2(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            }
+        }
+    }
+    public void test_KeyStore_deleteEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.deleteEntry(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test odd inputs
+            try {
+                keyStore.deleteEntry(null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            keyStore.deleteEntry("");
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test case sensitive
+            assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            keyStore.deleteEntry(ALIAS_PRIVATE);
+            assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+
+            if (isSecretKeyEnabled(keyStore)) {
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                keyStore.deleteEntry(ALIAS_SECRET);
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                keyStore.deleteEntry(ALIAS_SECRET);
+            }
+
+            if (isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                keyStore.deleteEntry(ALIAS_CERTIFICATE);
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            } else {
+                keyStore.deleteEntry(ALIAS_CERTIFICATE);
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            // test case insensitive
+
+            if (isCaseSensitive(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                keyStore.deleteEntry(ALIAS_ALT_CASE_PRIVATE);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    keyStore.deleteEntry(ALIAS_ALT_CASE_SECRET);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                } else {
+                    keyStore.deleteEntry(ALIAS_SECRET);
+                }
+
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    keyStore.deleteEntry(ALIAS_ALT_CASE_CERTIFICATE);
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                } else {
+                    keyStore.deleteEntry(ALIAS_CERTIFICATE);
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_aliases() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.aliases();
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            assertEquals(Collections.EMPTY_SET, new HashSet(Collections.list(keyStore.aliases())));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            Set<String> expected = new HashSet<String>();
+            expected.add(ALIAS_PRIVATE);
+            if (isNullPasswordAllowed(keyStore)) {
+                expected.add(ALIAS_NO_PASSWORD_PRIVATE);
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                expected.add(ALIAS_SECRET);
+                if (isNullPasswordAllowed(keyStore)) {
+                    expected.add(ALIAS_NO_PASSWORD_SECRET);
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                expected.add(ALIAS_CERTIFICATE);
+            }
+            assertEquals(expected, new HashSet<String>(Collections.list(keyStore.aliases())));
+        }
+    }
+
+    public void test_KeyStore_containsAlias() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.containsAlias(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.containsAlias(null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+
+            assertFalse(keyStore.containsAlias(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            assertFalse(keyStore.containsAlias(""));
+
+            assertTrue(keyStore.containsAlias(ALIAS_PRIVATE));
+            assertEquals(isSecretKeyEnabled(keyStore), keyStore.containsAlias(ALIAS_SECRET));
+            assertEquals(isCertificateEnabled(keyStore), keyStore.containsAlias(ALIAS_CERTIFICATE));
+
+            assertEquals(!isCaseSensitive(keyStore),
+                         keyStore.containsAlias(ALIAS_ALT_CASE_PRIVATE));
+            assertEquals(!isCaseSensitive(keyStore) && isSecretKeyEnabled(keyStore),
+                         keyStore.containsAlias(ALIAS_ALT_CASE_SECRET));
+            assertEquals(!isCaseSensitive(keyStore) && isCertificateEnabled(keyStore),
+                         keyStore.containsAlias(ALIAS_ALT_CASE_CERTIFICATE));
+        }
+    }
+
+    public void test_KeyStore_size() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.aliases();
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            assertEquals(0, keyStore.size());
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            int expected = 1;
+            if (isNullPasswordAllowed(keyStore)) {
+                expected++;
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                expected++;
+                if (isNullPasswordAllowed(keyStore)) {
+                    expected++;
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                expected++;
+            }
+            assertEquals(expected, keyStore.size());
+        }
+    }
+
+    public void test_KeyStore_isKeyEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.isKeyEntry(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.isKeyEntry(null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+
+            assertFalse(keyStore.isKeyEntry(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            assertFalse(keyStore.isKeyEntry(""));
+
+            assertTrue(keyStore.isKeyEntry(ALIAS_PRIVATE));
+            assertEquals(isSecretKeyEnabled(keyStore), keyStore.isKeyEntry(ALIAS_SECRET));
+            assertFalse(keyStore.isKeyEntry(ALIAS_CERTIFICATE));
+
+            assertEquals(!isCaseSensitive(keyStore),
+                         keyStore.isKeyEntry(ALIAS_ALT_CASE_PRIVATE));
+            assertEquals(!isCaseSensitive(keyStore) && isSecretKeyEnabled(keyStore),
+                         keyStore.isKeyEntry(ALIAS_ALT_CASE_SECRET));
+            assertFalse(keyStore.isKeyEntry(ALIAS_ALT_CASE_CERTIFICATE));
+        }
+    }
+
+    public void test_KeyStore_isCertificateEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.isCertificateEntry(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            if (isCertificateEnabled(keyStore)) {
+                try {
+                    keyStore.isCertificateEntry(null);
+                    fail();
+                } catch (NullPointerException expected) {
+                }
+            } else {
+                assertFalse(keyStore.isCertificateEntry(null));
+            }
+
+            assertFalse(keyStore.isCertificateEntry(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            assertFalse(keyStore.isCertificateEntry(""));
+
+            assertFalse(keyStore.isCertificateEntry(ALIAS_PRIVATE));
+            assertFalse(keyStore.isCertificateEntry(ALIAS_SECRET));
+            assertEquals(isCertificateEnabled(keyStore),
+                         keyStore.isCertificateEntry(ALIAS_CERTIFICATE));
+
+            assertFalse(keyStore.isCertificateEntry(ALIAS_ALT_CASE_PRIVATE));
+            assertFalse(keyStore.isCertificateEntry(ALIAS_ALT_CASE_SECRET));
+            assertEquals(!isCaseSensitive(keyStore) && isCertificateEnabled(keyStore),
+                         keyStore.isCertificateEntry(ALIAS_ALT_CASE_CERTIFICATE));
+        }
+    }
+
+    public void test_KeyStore_getCertificateAlias() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCertificateAlias(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            assertNull(keyStore.getCertificateAlias(null));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            Set<String> expected = new HashSet<String>();
+            expected.add(ALIAS_PRIVATE);
+            if (isNullPasswordAllowed(keyStore)) {
+                expected.add(ALIAS_NO_PASSWORD_PRIVATE);
+            }
+            if (isCertificateEnabled(keyStore)) {
+                expected.add(ALIAS_CERTIFICATE);
+            }
+            String actual = keyStore.getCertificateAlias(PRIVATE_KEY.getCertificate());
+            assertTrue(expected.contains(actual));
+            assertNull(keyStore.getCertificateAlias(PRIVATE_KEY_2.getCertificate()));
+        }
+    }
+
+    public void assertEqualsKeyStores(File expected, char[] storePassword, KeyStore actual)
+            throws Exception{
+        KeyStore ks = KeyStore.getInstance(actual.getType(), actual.getProvider());
+        ks.load(new FileInputStream(expected), storePassword);
+        assertEqualsKeyStores(ks, actual);
+    }
+
+    public void assertEqualsKeyStores(KeyStore expected,
+                                      ByteArrayOutputStream actual, char[] storePassword)
+            throws Exception{
+        KeyStore ks = KeyStore.getInstance(expected.getType(), expected.getProvider());
+        ks.load(new ByteArrayInputStream(actual.toByteArray()), storePassword);
+        assertEqualsKeyStores(expected, ks);
+    }
+
+    public void assertEqualsKeyStores(KeyStore expected, KeyStore actual)
+            throws Exception{
+        assertEquals(expected.size(), actual.size());
+        for (String alias : Collections.list(actual.aliases())) {
+            if (alias.equals(ALIAS_NO_PASSWORD_PRIVATE)
+                    || alias.equals(ALIAS_NO_PASSWORD_SECRET)) {
+                assertEquals(expected.getKey(alias, null),
+                             actual.getKey(alias, null));
+            } else {
+                assertEquals(expected.getKey(alias, PASSWORD_KEY),
+                             actual.getKey(alias, PASSWORD_KEY));
+            }
+            assertEquals(expected.getCertificate(alias), actual.getCertificate(alias));
+        }
+    }
+
+    public void test_KeyStore_store_OutputStream() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.store(null, null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            if (isNullPasswordAllowed(keyStore)) {
+                keyStore.store(out, null);
+                assertEqualsKeyStores(keyStore, out, null);
+            } else {
+                try {
+                    keyStore.store(out, null);
+                } catch (Exception e) {
+                    if (e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != NullPointerException.class) {
+                        throw e;
+                    }
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            if (isNullPasswordAllowed(keyStore)) {
+                keyStore.store(out, null);
+                assertEqualsKeyStores(keyStore, out, null);
+            } else {
+                try {
+                    keyStore.store(out, null);
+                } catch (Exception e) {
+                    if (e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != NullPointerException.class) {
+                        throw e;
+                    }
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            keyStore.store(out, PASSWORD_STORE);
+            assertEqualsKeyStores(keyStore, out, PASSWORD_STORE);
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            keyStore.store(out, PASSWORD_STORE);
+            assertEqualsKeyStores(keyStore, out, PASSWORD_STORE);
+        }
+    }
+
+    public void test_KeyStore_store_LoadStoreParameter() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.store(null);
+                fail();
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            try {
+                keyStore.store(null);
+                fail();
+            } catch (UnsupportedOperationException expected) {
+            }
+        }
+    }
+
+    public void test_KeyStore_load_InputStream() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            assertEquals(0, keyStore.size());
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, PASSWORD_STORE);
+            assertEquals(0, keyStore.size());
+        }
+
+        // test_KeyStore_store_OutputStream effectively tests load as well as store
+    }
+
+    public void test_KeyStore_load_LoadStoreParameter() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null);
+            assertEquals(0, keyStore.size());
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.load(new LoadStoreParameter() {
+                        public ProtectionParameter getProtectionParameter() {
+                            return null;
+                        }
+                    });
+                assertEquals(0, keyStore.size());
+            } catch (UnsupportedOperationException expected) {
+            }
+        }
+    }
+
+    public void test_KeyStore_getEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getEntry(null, null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getEntry(null, null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            try {
+                keyStore.getEntry(null, PARAM_KEY);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            assertNull(keyStore.getEntry("", null));
+            assertNull(keyStore.getEntry("", PARAM_KEY));
+
+            // test case sensitive
+            assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_KEY));
+            if (isSecretKeyEnabled(keyStore)) {
+                assertSecretKey(keyStore.getEntry(ALIAS_SECRET, PARAM_KEY));
+            } else {
+                assertNull(keyStore.getEntry(ALIAS_SECRET, PARAM_KEY));
+            }
+            if (isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getEntry(ALIAS_CERTIFICATE, null));
+            } else {
+                assertNull(keyStore.getEntry(ALIAS_CERTIFICATE, null));
+            }
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_ALT_CASE_PRIVATE, PARAM_KEY));
+                assertNull(keyStore.getEntry(ALIAS_ALT_CASE_SECRET, PARAM_KEY));
+            } else {
+                assertPrivateKey(keyStore.getEntry(ALIAS_ALT_CASE_PRIVATE, PARAM_KEY));
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getEntry(ALIAS_ALT_CASE_SECRET, PARAM_KEY));
+                }
+            }
+            if (isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_ALT_CASE_CERTIFICATE, null));
+            } else {
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getEntry(ALIAS_ALT_CASE_CERTIFICATE, null));
+                }
+            }
+
+            // test with null passwords
+            if (isNullPasswordAllowed(keyStore)) {
+                assertPrivateKey(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null));
+            } else if (isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, null));
+            } else {
+                try {
+                    keyStore.getEntry(ALIAS_PRIVATE, null);
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getEntry(ALIAS_SECRET, null);
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+
+            // test with bad passwords
+            if (isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD));
+            } else {
+                try {
+                    keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD);
+                    fail();
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getEntry(ALIAS_SECRET, PARAM_BAD);
+                    fail();
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            try {
+                keyStore.setEntry(null, null, null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test odd inputs
+            try {
+                keyStore.setEntry(null, null, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setEntry(null, null, PARAM_KEY);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setEntry("", null, PARAM_KEY);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test case sensitive
+            assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            keyStore.setEntry(ALIAS_PRIVATE, PRIVATE_KEY, PARAM_KEY);
+            assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(SECRET_KEY), PARAM_KEY);
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, SECRET_KEY, PASSWORD_KEY, null);
+                    fail();
+                } catch (KeyStoreException expected) {
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                keyStore.setEntry(ALIAS_CERTIFICATE,
+                                  new TrustedCertificateEntry(PRIVATE_KEY.getCertificate()),
+                                  null);
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            } else {
+                try {
+                    keyStore.setEntry(ALIAS_CERTIFICATE,
+                                      new TrustedCertificateEntry(PRIVATE_KEY.getCertificate()),
+                                      null);
+                    fail();
+                } catch (KeyStoreException expected) {
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            // test case insensitive
+
+            if (isCaseSensitive(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                keyStore.setEntry(ALIAS_ALT_CASE_PRIVATE, PRIVATE_KEY_2, PARAM_KEY);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    keyStore.setEntry(ALIAS_ALT_CASE_SECRET,
+                                      new SecretKeyEntry(SECRET_KEY_2),
+                                      PARAM_KEY);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                    keyStore.setEntry(ALIAS_ALT_CASE_CERTIFICATE,
+                                      new TrustedCertificateEntry(PRIVATE_KEY_2.getCertificate()),
+                                      null);
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                }
+            } else {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                keyStore.setEntry(ALIAS_ALT_CASE_PRIVATE, PRIVATE_KEY_2, PARAM_KEY);
+                assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    keyStore.setEntry(ALIAS_ALT_CASE_SECRET,
+                                      new SecretKeyEntry(SECRET_KEY_2),
+                                      PARAM_KEY);
+                    assertSecretKey2(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertCertificate(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                    keyStore.setEntry(ALIAS_ALT_CASE_CERTIFICATE,
+                                      new TrustedCertificateEntry(PRIVATE_KEY_2.getCertificate()),
+                                      null);
+                    assertCertificate2(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test with null/non-null passwords
+            try {
+                keyStore.setEntry(ALIAS_PRIVATE, PRIVATE_KEY, null);
+                fail();
+            } catch (Exception e) {
+                if (e.getClass() != UnrecoverableKeyException.class
+                    && e.getClass() != IllegalArgumentException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(SECRET_KEY), null);
+                    fail();
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != KeyStoreException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                    keyStore.setEntry(ALIAS_CERTIFICATE,
+                                      new TrustedCertificateEntry(PRIVATE_KEY.getCertificate()),
+                                      PARAM_KEY);
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                } else {
+                    try {
+                        keyStore.setEntry(ALIAS_CERTIFICATE,
+                                          new TrustedCertificateEntry(PRIVATE_KEY.getCertificate()),
+                                          PARAM_KEY);
+                        fail();
+                    } catch (KeyStoreException expected) {
+                    }
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_entryInstanceOf() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.entryInstanceOf(null, null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.entryInstanceOf(null, null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            try {
+                keyStore.entryInstanceOf(null, Entry.class);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            try {
+                keyStore.entryInstanceOf("", null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+
+            assertFalse(keyStore.entryInstanceOf("", Entry.class));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            assertFalse(keyStore.entryInstanceOf("", Entry.class));
+            assertFalse(keyStore.entryInstanceOf("", PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf("", SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf("", TrustedCertificateEntry.class));
+
+            // test case sensitive
+            assertTrue(keyStore.entryInstanceOf(ALIAS_PRIVATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, TrustedCertificateEntry.class));
+
+            assertEquals(isSecretKeyEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_SECRET, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, TrustedCertificateEntry.class));
+
+            assertEquals(isCertificateEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_CERTIFICATE,
+                                                  TrustedCertificateEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE, SecretKeyEntry.class));
+
+            // test case insensitive
+            assertEquals(!isCaseSensitive(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_ALT_CASE_PRIVATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_PRIVATE, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_PRIVATE,
+                                                 TrustedCertificateEntry.class));
+
+            assertEquals(!isCaseSensitive(keyStore) && isSecretKeyEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_ALT_CASE_SECRET, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_SECRET, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_SECRET,
+                                                 TrustedCertificateEntry.class));
+
+            assertEquals(!isCaseSensitive(keyStore) && isCertificateEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_ALT_CASE_CERTIFICATE,
+                                                  TrustedCertificateEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_CERTIFICATE,
+                                                 PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_CERTIFICATE, SecretKeyEntry.class));
+        }
+    }
+
+    public void test_KeyStore_Builder() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            try {
+                Builder.newInstance(keyStore, null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                Builder.newInstance(keyStore.getType(),
+                                    keyStore.getProvider(),
+                                    null);
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                Builder.newInstance(null,
+                                    null,
+                                    null,
+                                    null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            try {
+                Builder.newInstance(keyStore.getType(),
+                                    keyStore.getProvider(),
+                                    null,
+                                    null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            Builder builder = Builder.newInstance(keyStore, PARAM_STORE);
+            try {
+                builder.getProtectionParameter(null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            assertEquals(keyStore, builder.getKeyStore());
+            try {
+                builder.getProtectionParameter(null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
+            assertEquals(PARAM_STORE, builder.getProtectionParameter(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            File file = File.createTempFile("keystore", keyStore.getProvider().getName());
+            try {
+                keyStore.store(new FileOutputStream(file), PASSWORD_STORE);
+                Builder builder = Builder.newInstance(keyStore.getType(),
+                                                      keyStore.getProvider(),
+                                                      file,
+                                                      PARAM_STORE);
+                assertEquals(keyStore.getType(), builder.getKeyStore().getType());
+                assertEquals(keyStore.getProvider(), builder.getKeyStore().getProvider());
+                assertEquals(PARAM_STORE, builder.getProtectionParameter(""));
+                assertEqualsKeyStores(file, PASSWORD_STORE, keyStore);
+            } finally {
+                file.delete();
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            Builder builder = Builder.newInstance(keyStore.getType(),
+                                                  keyStore.getProvider(),
+                                                  PARAM_STORE);
+            assertEquals(keyStore.getType(), builder.getKeyStore().getType());
+            assertEquals(keyStore.getProvider(), builder.getKeyStore().getProvider());
+            assertEquals(PARAM_STORE, builder.getProtectionParameter(""));
+        }
+    }
+
+    public void test_KeyStore_cacerts_bks() throws Exception {
+        if (StandardNames.IS_RI) {
+            return;
+        }
+        KeyStore ks = KeyStore.getInstance("BKS");
+        ks.load(new FileInputStream("/etc/security/cacerts.bks"), null);
+        for (String alias : Collections.list(ks.aliases())) {
+            assert(ks.isCertificateEntry(alias));
+            Certificate c = ks.getCertificate(alias);
+            assertTrue(c instanceof X509Certificate);
+            X509Certificate cert = (X509Certificate) c;
+            assertEquals(cert.getSubjectUniqueID(), cert.getIssuerUniqueID());
+        }
+    }
+}
index a0753dd..f4d9b0b 100644 (file)
@@ -31,6 +31,11 @@ import junit.framework.TestCase;
 
 public class ProviderTest extends TestCase {
 
+    /**
+     * Makes sure all all expected implementations (but not aliases)
+     * and that there are no extras, according to what we expect from
+     * StandardNames
+     */
     public void test_Provider_getServices() throws Exception {
 
         // build set of expected algorithms
@@ -107,6 +112,10 @@ public class ProviderTest extends TestCase {
 
     private static final Pattern alias = Pattern.compile("Alg\\.Alias\\.([^.]*)\\.(.*)");
 
+    /**
+     * Makes sure all provider properties either point to a class
+     * implementation that exists or are aliases to known algorithms.
+     */
     public void test_Provider_Properties() throws Exception {
         /*
          * A useful reference on Provider properties
index 104ceee..44d5f70 100644 (file)
@@ -287,9 +287,9 @@ public class SSLContextTest extends TestCase {
         TestSSLContext testContext = TestSSLContext.create();
         assertNotNull(testContext);
         assertNotNull(testContext.clientKeyStore);
-        assertNull(testContext.clientKeyStorePassword);
+        assertNull(testContext.clientStorePassword);
         assertNotNull(testContext.serverKeyStore);
-        assertNull(testContext.serverKeyStorePassword);
+        assertNull(testContext.serverStorePassword);
         assertNotNull(testContext.clientKeyManager);
         assertNotNull(testContext.serverKeyManager);
         assertNotNull(testContext.clientTrustManager);
index e731345..ae5c328 100644 (file)
@@ -18,6 +18,7 @@ package javax.net.ssl;
 
 import dalvik.annotation.KnownFailure;
 import java.security.StandardNames;
+import java.security.TestKeyStore;
 import java.util.Arrays;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import junit.framework.TestCase;
@@ -65,6 +66,7 @@ public class SSLEngineTest extends TestCase {
         // note the rare usage of DSA keys here in addition to RSA
         TestKeyStore testKeyStore = TestKeyStore.create(new String[] { "RSA", "DSA" },
                                                         null,
+                                                        null,
                                                         "rsa-dsa",
                                                         TestKeyStore.localhost(),
                                                         true,
index f05b04c..8c46039 100644 (file)
@@ -17,6 +17,7 @@
 package javax.net.ssl;
 
 import java.security.StandardNames;
+import java.security.TestKeyStore;
 import java.util.Arrays;
 import junit.framework.TestCase;
 
index 225358d..7634fa3 100644 (file)
@@ -20,6 +20,7 @@ import java.net.Socket;
 import java.net.SocketTimeoutException;
 import java.security.Principal;
 import java.security.StandardNames;
+import java.security.TestKeyStore;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
@@ -39,6 +40,7 @@ public class SSLSocketTest extends TestCase {
         // note the rare usage of DSA keys here in addition to RSA
         TestKeyStore testKeyStore = TestKeyStore.create(new String[] { "RSA", "DSA" },
                                                         null,
+                                                        null,
                                                         "rsa-dsa",
                                                         TestKeyStore.localhost(),
                                                         true,
index 1e4355e..9e36daf 100644 (file)
@@ -50,6 +50,7 @@ public final class StandardNames extends Assert {
     public static final boolean IS_RI
             = !"Dalvik Core Library".equals(System.getProperty("java.specification.name"));
     public static final String JSSE_PROVIDER_NAME = (IS_RI) ? "SunJSSE" : "AndroidOpenSSL";
+    public static final String SECURITY_PROVIDER_NAME = (IS_RI) ? "SUN" : "BC";
 
     /**
      * A map from algorithm type (e.g. Cipher) to a set of algorithms (e.g. AES, DES, ...)
@@ -283,6 +284,15 @@ public final class StandardNames extends Assert {
             unprovide("KeyStore", "JCEKS");
             provide("KeyStore", "BouncyCastle");
 
+            // Noise to support KeyStore.PKCS12
+            provide("Cipher", "PBEWITHSHAAND40BITRC2-CBC");
+            provide("Cipher", "PBEWITHSHAANDTWOFISH-CBC");
+            provide("Mac", "PBEWITHHMACSHA");
+            provide("Mac", "PBEWITHHMACSHA1");
+            provide("SecretKeyFactory", "PBEWITHHMACSHA1");
+            provide("SecretKeyFactory", "PBEWITHSHAAND40BITRC2-CBC");
+            provide("SecretKeyFactory", "PBEWITHSHAANDTWOFISH-CBC");
+
             // removed Blowfish
             unprovide("AlgorithmParameters", "Blowfish");
             unprovide("Cipher", "Blowfish");
  * limitations under the License.
  */
 
-package javax.net.ssl;
+package java.security;
 
 import java.io.PrintStream;
 import java.math.BigInteger;
 import java.net.InetAddress;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
 import java.security.KeyStore.PasswordProtection;
 import java.security.KeyStore.PrivateKeyEntry;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.StandardNames;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
@@ -57,17 +49,21 @@ public final class TestKeyStore extends Assert {
         }
     }
     public final KeyStore keyStore;
-    public final char[] keyStorePassword;
+    public final char[] storePassword;
+    public final char[] keyPassword;
 
     private TestKeyStore(KeyStore keyStore,
-                         char[] keyStorePassword) {
+                         char[] storePassword,
+                         char[] keyPassword) {
         this.keyStore = keyStore;
-        this.keyStorePassword = keyStorePassword;
+        this.storePassword = storePassword;
+        this.keyPassword = keyPassword;
     }
 
     private static final TestKeyStore ROOT_CA
             = create(new String[] { "RSA" },
                      null,
+                     null,
                      "RootCA",
                      x509Principal("Test Root Certificate Authority"),
                      true,
@@ -75,6 +71,7 @@ public final class TestKeyStore extends Assert {
     private static final TestKeyStore INTERMEDIATE_CA
             = create(new String[] { "RSA" },
                      null,
+                     null,
                      "IntermediateCA",
                      x509Principal("Test Intermediate Certificate Authority"),
                      true,
@@ -82,15 +79,17 @@ public final class TestKeyStore extends Assert {
     private static final TestKeyStore SERVER
             = create(new String[] { "RSA" },
                      null,
+                     null,
                      "server",
                      localhost(),
                      false,
                      INTERMEDIATE_CA);
     private static final TestKeyStore CLIENT
-            = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null);
+            = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null);
     private static final TestKeyStore CLIENT_CERTIFICATE
             = create(new String[] { "RSA" },
                      null,
+                     null,
                      "client",
                      x509Principal("test@user"),
                      false,
@@ -131,7 +130,8 @@ public final class TestKeyStore extends Assert {
      * @param signer If non-null, key store used for signing key, otherwise self-signed
      */
     public static TestKeyStore create(String[] keyAlgorithms,
-                                      char[] keyStorePassword,
+                                      char[] storePassword,
+                                      char[] keyPassword,
                                       String aliasPrefix,
                                       X509Principal subject,
                                       boolean ca,
@@ -141,7 +141,7 @@ public final class TestKeyStore extends Assert {
             for (String keyAlgorithm : keyAlgorithms) {
                 String publicAlias  = aliasPrefix + "-public-"  + keyAlgorithm;
                 String privateAlias = aliasPrefix + "-private-" + keyAlgorithm;
-                createKeys(keyStore, keyStorePassword,
+                createKeys(keyStore, keyPassword,
                            keyAlgorithm,
                            publicAlias, privateAlias,
                            subject,
@@ -151,7 +151,7 @@ public final class TestKeyStore extends Assert {
             if (signer != null) {
                 copySelfSignedCertificates(keyStore, signer.keyStore);
             }
-            return new TestKeyStore(keyStore, keyStorePassword);
+            return new TestKeyStore(keyStore, storePassword, keyPassword);
         } catch (RuntimeException e) {
             throw e;
         } catch (Exception e) {
@@ -189,7 +189,7 @@ public final class TestKeyStore extends Assert {
      * org.bouncycastle.jce.provider.test.CertTest
      */
     public static KeyStore createKeys(KeyStore keyStore,
-                                      char[] keyStorePassword,
+                                      char[] keyPassword,
                                       String keyAlgorithm,
                                       String publicAlias,
                                       String privateAlias,
@@ -205,7 +205,7 @@ public final class TestKeyStore extends Assert {
             caCertChain = null;
         } else {
             PrivateKeyEntry privateKeyEntry
-                    = privateKey(signer.keyStore, signer.keyStorePassword, keyAlgorithm);
+                    = privateKey(signer.keyStore, signer.keyPassword, keyAlgorithm);
             caKey = privateKeyEntry.getPrivateKey();
             caCert = (X509Certificate)privateKeyEntry.getCertificate();
             caCertChain = (X509Certificate[])privateKeyEntry.getCertificateChain();
@@ -276,7 +276,7 @@ public final class TestKeyStore extends Assert {
 
         // 3.) put certificate and private key into the key store
         if (privateAlias != null) {
-            keyStore.setKeyEntry(privateAlias, privateKey, keyStorePassword, x509cc);
+            keyStore.setKeyEntry(privateAlias, privateKey, keyPassword, x509cc);
         }
         if (publicAlias != null) {
             keyStore.setCertificateEntry(publicAlias, x509c);
@@ -310,11 +310,11 @@ public final class TestKeyStore extends Assert {
      * or less than one.
      */
     public static PrivateKeyEntry privateKey(KeyStore keyStore,
-                                             char[] keyStorePassword,
+                                             char[] keyPassword,
                                              String algorithm) {
         try {
             PrivateKeyEntry found = null;
-            PasswordProtection password = new PasswordProtection(keyStorePassword);
+            PasswordProtection password = new PasswordProtection(keyPassword);
             for (String alias: Collections.list(keyStore.aliases())) {
                 if (!keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
                     continue;
@@ -374,15 +374,19 @@ public final class TestKeyStore extends Assert {
      */
     public static void dump(String context,
                             KeyStore keyStore,
-                            char[] keyStorePassword) {
+                            char[] keyPassword) {
         try {
             PrintStream out = System.out;
             out.println("context=" + context);
             out.println("\tkeyStore=" + keyStore);
-            out.println("\tpassword="
-                        + ((keyStorePassword == null) ? null : new String(keyStorePassword)));
+            out.println("\tkeyStore.type=" + keyStore.getType());
+            out.println("\tkeyStore.provider=" + keyStore.getProvider());
+            out.println("\tkeyPassword="
+                        + ((keyPassword == null) ? null : new String(keyPassword)));
+            out.println("\tsize=" + keyStore.size());
             for (String alias: Collections.list(keyStore.aliases())) {
-                out.println("\talias=" + alias);
+                out.println("alias=" + alias);
+                out.println("\tcreationDate=" + keyStore.getCreationDate(alias));
                 if (keyStore.isCertificateEntry(alias)) {
                     out.println("\tcertificate:");
                     out.println("==========================================");
@@ -393,7 +397,19 @@ public final class TestKeyStore extends Assert {
                 if (keyStore.isKeyEntry(alias)) {
                     out.println("\tkey:");
                     out.println("==========================================");
-                    out.println(keyStore.getKey(alias, keyStorePassword));
+                    String key;
+                    try {
+                        key = ("Key retreived using password\n"
+                               + keyStore.getKey(alias, keyPassword).toString());
+                    } catch (UnrecoverableKeyException e1) {
+                        try {
+                            key = ("Key retreived without password\n"
+                                   + keyStore.getKey(alias, null).toString());
+                        } catch (UnrecoverableKeyException e2) {
+                            key = "Key could not be retreived";
+                        }
+                    }
+                    out.println(key);
                     out.println("==========================================");
                     continue;
                 }
index 5174b15..b183633 100644 (file)
@@ -22,6 +22,7 @@ import java.security.KeyStore;
 import java.security.Principal;
 import java.security.SecureRandom;
 import java.security.StandardNames;
+import java.security.TestKeyStore;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
@@ -67,9 +68,9 @@ public final class TestSSLContext extends Assert {
     }
 
     public final KeyStore clientKeyStore;
-    public final char[] clientKeyStorePassword;
+    public final char[] clientStorePassword;
     public final KeyStore serverKeyStore;
-    public final char[] serverKeyStorePassword;
+    public final char[] serverStorePassword;
     public final X509ExtendedKeyManager clientKeyManager;
     public final X509ExtendedKeyManager serverKeyManager;
     public final X509TrustManager clientTrustManager;
@@ -81,9 +82,9 @@ public final class TestSSLContext extends Assert {
     public final int port;
 
     private TestSSLContext(KeyStore clientKeyStore,
-                           char[] clientKeyStorePassword,
+                           char[] clientStorePassword,
                            KeyStore serverKeyStore,
-                           char[] serverKeyStorePassword,
+                           char[] serverStorePassword,
                            X509ExtendedKeyManager clientKeyManager,
                            X509ExtendedKeyManager serverKeyManager,
                            X509TrustManager clientTrustManager,
@@ -94,9 +95,9 @@ public final class TestSSLContext extends Assert {
                            InetAddress host,
                            int port) {
         this.clientKeyStore = clientKeyStore;
-        this.clientKeyStorePassword = clientKeyStorePassword;
+        this.clientStorePassword = clientStorePassword;
         this.serverKeyStore = serverKeyStore;
-        this.serverKeyStorePassword = serverKeyStorePassword;
+        this.serverStorePassword = serverStorePassword;
         this.clientKeyManager = clientKeyManager;
         this.serverKeyManager = serverKeyManager;
         this.clientTrustManager = clientTrustManager;
@@ -122,25 +123,23 @@ public final class TestSSLContext extends Assert {
      * TestSSLContext creation method that allows separate creation of server key store
      */
     public static TestSSLContext create(TestKeyStore client, TestKeyStore server) {
-        return create(client.keyStore, client.keyStorePassword,
-                      server.keyStore, server.keyStorePassword);
+        return create(client.keyStore, client.storePassword,
+                      server.keyStore, server.storePassword);
     }
 
     /**
      * TestSSLContext creation method that allows separate creation of client and server key store
      */
-    public static TestSSLContext create(KeyStore clientKeyStore, char[] clientKeyStorePassword,
-                                        KeyStore serverKeyStore, char[] serverKeyStorePassword) {
+    public static TestSSLContext create(KeyStore clientKeyStore, char[] clientStorePassword,
+                                        KeyStore serverKeyStore, char[] serverStorePassword) {
         try {
             KeyManager[] clientKeyManagers = createKeyManagers(clientKeyStore,
-                                                               clientKeyStorePassword);
+                                                               clientStorePassword);
             KeyManager[] serverKeyManagers = createKeyManagers(serverKeyStore,
-                                                               serverKeyStorePassword);
+                                                               serverStorePassword);
 
-            TrustManager[] clientTrustManagers = createTrustManagers(clientKeyStore,
-                                                                     clientKeyStorePassword);
-            TrustManager[] serverTrustManagers = createTrustManagers(serverKeyStore,
-                                                                     serverKeyStorePassword);
+            TrustManager[] clientTrustManagers = createTrustManagers(clientKeyStore);
+            TrustManager[] serverTrustManagers = createTrustManagers(serverKeyStore);
 
             SSLContext clientContext = createSSLContext(clientKeyManagers, clientTrustManagers);
             SSLContext serverContext = createSSLContext(serverKeyManagers, serverTrustManagers);
@@ -151,8 +150,8 @@ public final class TestSSLContext extends Assert {
             InetAddress host = sa.getAddress();
             int port = sa.getPort();
 
-            return new TestSSLContext(clientKeyStore, clientKeyStorePassword,
-                                      serverKeyStore, serverKeyStorePassword,
+            return new TestSSLContext(clientKeyStore, clientStorePassword,
+                                      serverKeyStore, serverStorePassword,
                                       (X509ExtendedKeyManager) clientKeyManagers[0],
                                       (X509ExtendedKeyManager) serverKeyManagers[0],
                                       (X509TrustManager) clientTrustManagers[0],
@@ -180,15 +179,14 @@ public final class TestSSLContext extends Assert {
     }
 
     public static KeyManager[] createKeyManagers(final KeyStore keyStore,
-                                                 final char[] keyStorePassword) throws Exception {
+                                                 final char[] storePassword) throws Exception {
         String kmfa = KeyManagerFactory.getDefaultAlgorithm();
         KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa);
-        kmf.init(keyStore, keyStorePassword);
+        kmf.init(keyStore, storePassword);
         return kmf.getKeyManagers();
     }
 
-    public static TrustManager[] createTrustManagers(final KeyStore keyStore,
-                                                   final char[] keyStorePassword) throws Exception {
+    public static TrustManager[] createTrustManagers(final KeyStore keyStore) throws Exception {
         String tmfa = TrustManagerFactory.getDefaultAlgorithm();
         TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa);
         tmf.init(keyStore);