Git at Google

commit9acacc36bafda869c6e9cc63786cdddd995ca96a[log][tgz]
authorBrian Carlstrom <bdc@google.com>Fri May 14 11:14:18 2010 -0700
committerBrian Carlstrom <bdc@google.com>Fri May 14 15:06:32 2010 -0700
tree1997531d039b0509811f7c249c017ba36f5df2cb
parent7cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7[diff]
Use JSSE cipher suite names and restore JSSE SSLSessionContext semantics

Summary:
- Switch to using JSSE cipher suite names
- SSLSessionContext implementation cleanup
- Updated tests

Details:

Switch to using JSSE cipher suite names
- We maintain backward compatability for enabling cipher suites using
  OpenSSL names for old code that did so without checking for the
  presence of the names in the supported list.
- We now have a well defined list of the supported cipher suites which
  are sorted in priority order as specified in JSSE documentation so
  that callers doing:
     s.setEnabledCipherSuites(s.getSupportedCipherSuites())
  will get something reasonable.
- We now have a default cipher suite list that is chose to match RI
  behavior and priority, not based on OpenSSLs default and priorities.

    Details:
    - Added NativeCrypto OPENSSL_TO_STANDARD and STANDARD_TO_OPENSSL
      mapping between naming conventions. STANDARD_TO_OPENSSL is a
      LinkedHashMap so enumerating it gives the proper order for
      SUPPORTED_CIPHER_SUITES.
    - SSL_get_ciphers and SSL_set_cipher_list are removed, we now use
      our own SSL_set_cipher_lists (defined seperately in
      external/openssl/patches/jsse.patch) to set the set and order of
      cipher suites. SSL_CTX_get_ciphers is also removed because we no
      longer rely on the OpenSSL for the default cipher suites
      behavior.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
	luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp

    Add cipherSuite and protocol field caches for native values,
    mapping the cipherSuite to a JSSE name from the OpenSSL name
    returned by SSL_SESSION_cipher.

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

    Fixed a long standing bug where we reused sessions found in the
    client host/port cache even if the old protocol and cipher suite
    where no longer compatible with what was specified by
    setEnabledCipherSuites and setProtocols.  Also fixed a recently
    introduced bug where lastAccessedTime was being set on a cached
    session even if it was not reused, found by fixed the above.

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

Move most of SSLSessionContext implementation from subclasses to
AbstractSessionContext. This was primarily to align the
implementations of how different sessions id for the same host and
port were handled for RI compatability. client subclasses now focuses
on handling its host/port based cache and both deal with their own
persistent cache details.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java

Tests

   Added some variants of assertSSLSessionContextSize to simplify tests code.
   Broke test_SSLSessionContext_setSessionCacheSize_oneConnect out of
   test_SSLSessionContext_setSessionCacheSize_dynamic. Renamed
   test_SSLSessionContext_setSessionCacheSize_basic to
   test_SSLSessionContext_setSessionCacheSize_noConnect to match name
   of _oneConnect. _dynamic was cleaned up a bit as getting it working
   was the only goal of this change list. Fixed to filter
   SSL_RSA_EXPORT_ ciphers since our test certificate key length is
   too long for those. Lower test requirement to 3 unique cipher suites.

	luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java

   Added checks that cipher suites and protocols have standard names.

	luni/src/test/java/javax/net/ssl/SSLSessionTest.java

   Removing known failures related to cipher suite naming. Fixed bug
   of using assertNotNull instead of assertTrue. Added extra
   size/length check which would have found the
   assertNotNull/assertTrue issue.

	luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
	luni/src/test/java/javax/net/ssl/SSLSocketTest.java

   Fixing test the explicitly worked around broken cipher suite naming.

	luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java

   Updated standard cipher suites to RI 6 list, which also now
   specifies ordering, which we now align with.

	support/src/test/java/javax/net/ssl/StandardNames.java

Unrelated

   Remove more now obsolete jars from the test classpath

	run-core-tests

Change-Id: I45c274a9327c9a1aeeccb39ecaf5a3fbe2903c8f
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
index 5c73558..0309838 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
@@ -24,6 +24,8 @@
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.logging.Level;
 import javax.net.ssl.SSLSession;
@@ -45,6 +47,15 @@
     /** Identifies OpenSSL sessions. */
     static final int OPEN_SSL = 1;
 
+    private final Map<ByteArray, SSLSession> sessions
+            = new LinkedHashMap<ByteArray, SSLSession>() {
+        @Override
+        protected boolean removeEldestEntry(
+                Map.Entry<ByteArray, SSLSession> eldest) {
+            return maximumSize > 0 && size() > maximumSize;
+        }
+    };
+
     /**
      * Constructs a new session context.
      *
@@ -57,9 +68,15 @@
     }
 
     /**
-     * Returns the collection of sessions ordered by least-recently-used first.
+     * Returns the collection of sessions ordered from oldest to newest
      */
-    abstract Iterator<SSLSession> sessionIterator();
+    private Iterator<SSLSession> sessionIterator() {
+        synchronized (sessions) {
+            SSLSession[] array = sessions.values().toArray(
+                    new SSLSession[sessions.size()]);
+            return Arrays.asList(array).iterator();
+        }
+    }
 
     public final Enumeration getIds() {
         final Iterator<SSLSession> i = sessionIterator();
@@ -101,7 +118,47 @@
     /**
      * Makes sure cache size is < maximumSize.
      */
-    abstract void trimToSize();
+    protected void trimToSize() {
+        synchronized (sessions) {
+            int size = sessions.size();
+            if (size > maximumSize) {
+                int removals = size - maximumSize;
+                Iterator<SSLSession> i = sessions.values().iterator();
+                do {
+                    SSLSession session = i.next();
+                    i.remove();
+                    sessionRemoved(session);
+                } while (--removals > 0);
+            }
+        }
+    }
+
+    public void setSessionTimeout(int seconds)
+            throws IllegalArgumentException {
+        if (seconds < 0) {
+            throw new IllegalArgumentException("seconds < 0");
+        }
+        timeout = seconds;
+
+        synchronized (sessions) {
+            Iterator<SSLSession> i = sessions.values().iterator();
+            while (i.hasNext()) {
+                SSLSession session = i.next();
+                // SSLSession's know their context and consult the
+                // timeout as part of their validity condition.
+                if (!session.isValid()) {
+                    i.remove();
+                    sessionRemoved(session);
+                }
+            }
+        }
+    }
+
+    /** 
+     * Called when a session is removed. Used by ClientSessionContext
+     * to update its host-and-port based cache.
+     */
+    abstract protected void sessionRemoved(SSLSession session);
 
     public final void setSessionCacheSize(int size)
             throws IllegalArgumentException {
@@ -201,10 +258,31 @@
         }
     }
 
-    /**
-     * Puts an SSLSession in the AbstractSessionContext cache
-     */
-    abstract void putSession(SSLSession session);
+    public SSLSession getSession(byte[] sessionId) {
+        if (sessionId == null) {
+            throw new NullPointerException("sessionId == null");
+        }
+        ByteArray key = new ByteArray(sessionId);
+        SSLSession session;
+        synchronized (sessions) {
+            session = sessions.get(key);
+        }
+        if (session != null && session.isValid()) {
+            return session;
+        }
+        return null;
+    }
+
+    void putSession(SSLSession session) {
+        byte[] id = session.getId();
+        if (id.length == 0) {
+            return;
+        }
+        ByteArray key = new ByteArray(id);
+        synchronized (sessions) {
+            sessions.put(key, session);
+        }
+    }
 
     static void log(Throwable t) {
         java.util.logging.Logger.global.log(Level.WARNING,
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
index dac22f0..0b297a3 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
@@ -16,42 +16,22 @@
 
 package org.apache.harmony.xnet.provider.jsse;
 
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import javax.net.ssl.SSLSession;
 
 /**
  * Caches client sessions. Indexes by host and port. Users are typically
- * looking to reuse any session for a given host and port. Users of the
- * standard API are forced to iterate over the sessions semi-linearly as
- * opposed to in constant time.
+ * looking to reuse any session for a given host and port.
  */
 public class ClientSessionContext extends AbstractSessionContext {
 
-    /** Sessions indexed by host and port in access order. */
-    final Map<HostAndPort, SSLSession> sessions
-            = new LinkedHashMap<HostAndPort, SSLSession>() {
-        @Override
-        protected boolean removeEldestEntry(
-                Map.Entry<HostAndPort, SSLSession> eldest) {
-            // Called while lock is held on sessions.
-            boolean remove = maximumSize > 0 && size() > maximumSize;
-            if (remove) {
-                // don't just update sessions, but also sessionsById
-                removeById(eldest.getValue());
-            }
-            return remove;
-        }
-    };
-
     /**
-     * Sessions indexed by ID. Initialized on demand. Protected from concurrent
-     * access by holding a lock on sessions.
+     * Sessions indexed by host and port. Protect from concurrent
+     * access by holding a lock on sessionsByHostAndPort.
      */
-    Map<ByteArray, SSLSession> sessionsById;
+    final Map<HostAndPort, SSLSession> sessionsByHostAndPort
+        = new HashMap<HostAndPort, SSLSession>();
 
     private SSLClientSessionCache persistentCache;
 
@@ -63,106 +43,10 @@
         this.persistentCache = persistentCache;
     }
 
-    public final void setSessionTimeout(int seconds)
-            throws IllegalArgumentException {
-        if (seconds < 0) {
-            throw new IllegalArgumentException("seconds < 0");
-        }
-        timeout = seconds;
-
-        synchronized (sessions) {
-            Iterator<SSLSession> i = sessions.values().iterator();
-            while (i.hasNext()) {
-                SSLSession session = i.next();
-                // SSLSession's know their context and consult the
-                // timeout as part of their validity condition.
-                if (!session.isValid()) {
-                    i.remove();
-                    // don't just update sessions, but also sessionsById
-                    removeById(session);
-                }
-            }
-        }
-    }
-
-    Iterator<SSLSession> sessionIterator() {
-        synchronized (sessions) {
-            SSLSession[] array = sessions.values().toArray(
-                    new SSLSession[sessions.size()]);
-            return Arrays.asList(array).iterator();
-        }
-    }
-
-    void trimToSize() {
-        synchronized (sessions) {
-            int size = sessions.size();
-            if (size > maximumSize) {
-                int removals = size - maximumSize;
-                Iterator<SSLSession> i = sessions.values().iterator();
-                do {
-                    removeById(i.next());
-                    i.remove();
-                } while (--removals > 0);
-            }
-        }
-    }
-
-    void removeById(SSLSession session) {
-        if (sessionsById != null) {
-            sessionsById.remove(new ByteArray(session.getId()));
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @see #getSession(String, int) for an implementation-specific but more
-     *  efficient approach
-     */
-    public SSLSession getSession(byte[] sessionId) {
-        if (sessionId == null) {
-            throw new NullPointerException("sessionId == null");
-        }
-        /*
-         * This method is typically used in conjunction with getIds() to
-         * iterate over the sessions linearly, so it doesn't make sense for
-         * it to impact access order.
-         *
-         * It also doesn't load sessions from the persistent cache as doing
-         * so would likely force every session to load.
-         */
-
-        ByteArray id = new ByteArray(sessionId);
-        SSLSession session;
-        synchronized (sessions) {
-            indexById();
-            session = sessionsById.get(id);
-        }
-        if (session != null && session.isValid()) {
-            return session;
-        }
-        return null;
-    }
-
-    /**
-     * Ensures that the ID-based index is initialized.
-     */
-    private void indexById() {
-        if (sessionsById == null) {
-            sessionsById = new HashMap<ByteArray, SSLSession>();
-            for (SSLSession session : sessions.values()) {
-                sessionsById.put(new ByteArray(session.getId()), session);
-            }
-        }
-    }
-
-    /**
-     * Adds the given session to the ID-based index if the index has already
-     * been initialized.
-     */
-    private void indexById(byte[] id, SSLSession session) {
-        if (sessionsById != null) {
-            sessionsById.put(new ByteArray(id), session);
+    protected void sessionRemoved(SSLSession session) {
+        HostAndPort hostAndPortKey = new HostAndPort(session);
+        synchronized (sessionsByHostAndPort) {
+            sessionsByHostAndPort.remove(hostAndPortKey);
         }
     }
 
@@ -175,8 +59,9 @@
      */
     public SSLSession getSession(String host, int port) {
         SSLSession session;
-        synchronized (sessions) {
-            session = sessions.get(new HostAndPort(host, port));
+        HostAndPort hostAndPortKey = new HostAndPort(host, port);
+        synchronized (sessionsByHostAndPort) {
+            session = sessionsByHostAndPort.get(hostAndPortKey);
         }
         if (session != null && session.isValid()) {
             return session;
@@ -188,9 +73,9 @@
             if (data != null) {
                 session = toSession(data, host, port);
                 if (session != null && session.isValid()) {
-                    synchronized (sessions) {
-                        sessions.put(new HostAndPort(host, port), session);
-                        indexById(session.getId(), session);
+                    super.putSession(session);
+                    synchronized (sessionsByHostAndPort) {
+                        sessionsByHostAndPort.put(hostAndPortKey, session);
                     }
                     return session;
                 }
@@ -202,15 +87,11 @@
 
     @Override
     void putSession(SSLSession session) {
-        byte[] id = session.getId();
-        if (id.length == 0) {
-            return;
-        }
-        HostAndPort key = new HostAndPort(session.getPeerHost(),
-                session.getPeerPort());
-        synchronized (sessions) {
-            sessions.put(key, session);
-            indexById(id, session);
+        super.putSession(session);
+
+        HostAndPort hostAndPortKey = new HostAndPort(session);
+        synchronized (sessionsByHostAndPort) {
+            sessionsByHostAndPort.put(hostAndPortKey, session);
         }
 
         // TODO: This in a background thread.
@@ -226,6 +107,10 @@
         final String host;
         final int port;
 
+        HostAndPort(SSLSession session) {
+            this(session.getPeerHost(), session.getPeerPort());
+        }
+
         HostAndPort(String host, int port) {
             this.host = host;
             this.port = port;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
index 6e38cf6..02b015b 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
@@ -25,6 +25,10 @@
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import org.bouncycastle.openssl.PEMWriter;
 
 /**
@@ -104,6 +108,106 @@
     private static final String SUPPORTED_PROTOCOL_SSLV3 = "SSLv3";
     private static final String SUPPORTED_PROTOCOL_TLSV1 = "TLSv1";
 
+    public static final Map<String, String> OPENSSL_TO_STANDARD = new HashMap<String, String>();
+    public static final Map<String, String> STANDARD_TO_OPENSSL = new LinkedHashMap<String, String>();
+
+    private static void add(String standard, String openssl) {
+        OPENSSL_TO_STANDARD.put(openssl, standard);
+        STANDARD_TO_OPENSSL.put(standard, openssl);
+    }
+
+    static {
+        // Note these are added in priority order
+        add("SSL_RSA_WITH_RC4_128_MD5",              "RC4-MD5");
+        add("SSL_RSA_WITH_RC4_128_SHA",              "RC4-SHA");
+        add("TLS_RSA_WITH_AES_128_CBC_SHA",          "AES128-SHA");
+        add("TLS_RSA_WITH_AES_256_CBC_SHA",          "AES256-SHA");
+        add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",       "ECDH-ECDSA-RC4-SHA");
+        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",   "ECDH-ECDSA-AES128-SHA");
+        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",   "ECDH-ECDSA-AES256-SHA");
+        add("TLS_ECDH_RSA_WITH_RC4_128_SHA",         "ECDH-RSA-RC4-SHA");
+        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",     "ECDH-RSA-AES128-SHA");
+        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",     "ECDH-RSA-AES256-SHA");
+        add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",      "ECDHE-ECDSA-RC4-SHA");
+        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",  "ECDHE-ECDSA-AES128-SHA");
+        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",  "ECDHE-ECDSA-AES256-SHA");
+        add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",        "ECDHE-RSA-RC4-SHA");
+        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",    "ECDHE-RSA-AES128-SHA");
+        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",    "ECDHE-RSA-AES256-SHA");
+        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",      "DHE-RSA-AES128-SHA");
+        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",      "DHE-RSA-AES256-SHA");
+        add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",      "DHE-DSS-AES128-SHA");
+        add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",      "DHE-DSS-AES256-SHA");
+        add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",         "DES-CBC3-SHA");
+        add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",  "ECDH-ECDSA-DES-CBC3-SHA");
+        add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",    "ECDH-RSA-DES-CBC3-SHA");
+        add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-ECDSA-DES-CBC3-SHA");
+        add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",   "ECDHE-RSA-DES-CBC3-SHA");
+        add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",     "EDH-RSA-DES-CBC3-SHA");
+        add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",     "EDH-DSS-DES-CBC3-SHA");
+        add("SSL_RSA_WITH_DES_CBC_SHA",              "DES-CBC-SHA");
+        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",          "EDH-RSA-DES-CBC-SHA");
+        add("SSL_DHE_DSS_WITH_DES_CBC_SHA",          "EDH-DSS-DES-CBC-SHA");
+        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",        "EXP-RC4-MD5");
+        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",     "EXP-DES-CBC-SHA");
+        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-RSA-DES-CBC-SHA");
+        add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-DSS-DES-CBC-SHA");
+        add("SSL_RSA_WITH_NULL_MD5",                 "NULL-MD5");
+        add("SSL_RSA_WITH_NULL_SHA",                 "NULL-SHA");
+        add("TLS_ECDH_ECDSA_WITH_NULL_SHA",          "ECDH-ECDSA-NULL-SHA");
+        add("TLS_ECDH_RSA_WITH_NULL_SHA",            "ECDH-RSA-NULL-SHA");
+        add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",         "ECDHE-ECDSA-NULL-SHA");
+        add("TLS_ECDHE_RSA_WITH_NULL_SHA",           "ECDHE-RSA-NULL-SHA");
+        add("SSL_DH_anon_WITH_RC4_128_MD5",          "ADH-RC4-MD5");
+        add("TLS_DH_anon_WITH_AES_128_CBC_SHA",      "ADH-AES128-SHA");
+        add("TLS_DH_anon_WITH_AES_256_CBC_SHA",      "ADH-AES256-SHA");
+        add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",     "ADH-DES-CBC3-SHA");
+        add("SSL_DH_anon_WITH_DES_CBC_SHA",          "ADH-DES-CBC-SHA");
+        add("TLS_ECDH_anon_WITH_RC4_128_SHA",        "AECDH-RC4-SHA");
+        add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",    "AECDH-AES128-SHA");
+        add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",    "AECDH-AES256-SHA");
+        add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",   "AECDH-DES-CBC3-SHA");
+        add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",    "EXP-ADH-RC4-MD5");
+        add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "EXP-ADH-DES-CBC-SHA");
+        add("TLS_ECDH_anon_WITH_NULL_SHA",           "AECDH-NULL-SHA");
+        
+        // No Kerberos in Android
+        //add("TLS_KRB5_WITH_RC4_128_SHA",           "KRB5-RC4-SHA");
+        //add("TLS_KRB5_WITH_RC4_128_MD5",           "KRB5-RC4-MD5");
+        //add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",      "KRB5-DES-CBC3-SHA");
+        //add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",      "KRB5-DES-CBC3-MD5");
+        //add("TLS_KRB5_WITH_DES_CBC_SHA",           "KRB5-DES-CBC-SHA");
+        //add("TLS_KRB5_WITH_DES_CBC_MD5",           "KRB5-DES-CBC-MD5");
+        //add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",     "EXP-KRB5-RC4-SHA");
+        //add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",     "EXP-KRB5-RC4-MD5");
+        //add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", "EXP-KRB5-DES-CBC-SHA");
+        //add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", "EXP-KRB5-DES-CBC-MD5");
+
+        // not implemented by either RI or OpenSSL
+        //add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", null);
+        //add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", null);
+
+        // EXPORT1024 suites were never standardized but were widely implemented.
+        // OpenSSL 0.9.8c and later have disabled TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES
+        //add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", "EXP1024-DES-CBC-SHA");
+        //add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",  "EXP1024-RC4-SHA");
+
+        // No RC2
+        //add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",  "EXP-RC2-CBC-MD5");
+        //add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", "EXP-KRB5-RC2-CBC-SHA");
+        //add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", "EXP-KRB5-RC2-CBC-MD5");
+
+        // PSK is Private Shared Key - didn't exist in Froyo's openssl - no JSSE equivalent
+        //add(null, "PSK-3DES-EDE-CBC-SHA");
+        //add(null, "PSK-AES128-CBC-SHA");
+        //add(null, "PSK-AES256-CBC-SHA");
+        //add(null, "PSK-RC4-SHA");
+
+    }
+
+    private static final String[] SUPPORTED_CIPHER_SUITES
+        = STANDARD_TO_OPENSSL.keySet().toArray(new String[0]);
+
     // SSL mode
     public static long SSL_MODE_HANDSHAKE_CUTTHROUGH = 0x00000040L;
 
@@ -113,18 +217,28 @@
 
     public static native int SSL_CTX_new();
 
-    public static native String[] SSL_CTX_get_ciphers(int ssl_ctx);
-
     public static String[] getDefaultCipherSuites() {
-        int ssl_ctx = SSL_CTX_new();
-        String[] supportedCiphers = SSL_CTX_get_ciphers(ssl_ctx);
-        SSL_CTX_free(ssl_ctx);
-        return supportedCiphers;
+        return new String[] {
+            "SSL_RSA_WITH_RC4_128_MD5",
+            "SSL_RSA_WITH_RC4_128_SHA",
+            "TLS_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+            "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+            "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+            "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+            "SSL_RSA_WITH_DES_CBC_SHA",
+            "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+            "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+            "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+            "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+            "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
+        };
     }
 
     public static String[] getSupportedCipherSuites() {
-        // TODO really return full cipher list
-        return getDefaultCipherSuites();
+        return SUPPORTED_CIPHER_SUITES.clone();
     }
 
     public static native void SSL_CTX_free(int ssl_ctx);
@@ -236,7 +350,7 @@
                 optionsToSet &= ~SSL_OP_NO_TLSv1;
                 optionsToClear |= SSL_OP_NO_TLSv1;
             } else {
-                throw new IllegalArgumentException("Protocol " + protocol +
+                throw new IllegalArgumentException("protocol " + protocol +
                                                    " is not supported");
             }
         }
@@ -256,29 +370,25 @@
             }
             if ((!protocol.equals(SUPPORTED_PROTOCOL_SSLV3))
                 && (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1))) {
-                throw new IllegalArgumentException("Protocol " + protocol +
+                throw new IllegalArgumentException("protocol " + protocol +
                                                    " is not supported");
             }
         }
         return protocols;
     }
 
-    public static native String[] SSL_get_ciphers(int ssl);
-
-    public static native void SSL_set_cipher_list(int ssl, String ciphers);
+    public static native void SSL_set_cipher_lists(int ssl, String[] ciphers);
 
     public static void setEnabledCipherSuites(int ssl, String[] cipherSuites) {
         checkEnabledCipherSuites(cipherSuites);
-        String controlString = "";
+        List<String> opensslSuites = new ArrayList<String>();
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
-            if (i == 0) {
-                controlString = cipherSuite;
-            } else {
-                controlString += ":" + cipherSuite;
-            }
+            String openssl = STANDARD_TO_OPENSSL.get(cipherSuite);
+            String cs = (openssl == null) ? cipherSuite : openssl;
+            opensslSuites.add(cs);
         }
-        SSL_set_cipher_list(ssl, controlString);
+        SSL_set_cipher_lists(ssl, opensslSuites.toArray(new String[opensslSuites.size()]));
     }
 
     public static String[] checkEnabledCipherSuites(String[] cipherSuites) {
@@ -286,24 +396,21 @@
             throw new IllegalArgumentException("cipherSuites == null");
         }
         // makes sure all suites are valid, throwing on error
-        String[] supportedCipherSuites = getSupportedCipherSuites();
         for (int i = 0; i < cipherSuites.length; i++) {
             String cipherSuite = cipherSuites[i];
             if (cipherSuite == null) {
                 throw new IllegalArgumentException("cipherSuites[" + i + "] == null");
             }
-            findSuite(supportedCipherSuites, cipherSuite);
+            if (STANDARD_TO_OPENSSL.containsKey(cipherSuite)) {
+                continue;
+            }
+            if (OPENSSL_TO_STANDARD.containsKey(cipherSuite)) {
+                // TODO log warning about using backward compatability
+                continue;
+            }
+            throw new IllegalArgumentException("cipherSuite " + cipherSuite + " is not supported.");
         }
         return cipherSuites;
-    }
-
-    private static void findSuite(String[] supportedCipherSuites, String suite) {
-        for (String supportedCipherSuite : supportedCipherSuites) {
-            if (supportedCipherSuite.equals(suite)) {
-                return;
-            }
-        }
-        throw new IllegalArgumentException("Protocol " + suite + " is not supported.");
     }
 
     /*
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
index b722a97..b889e7d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
@@ -23,9 +23,8 @@
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Iterator;
-import java.util.UnknownFormatConversionException;
+import java.util.Map;
 import java.util.Vector;
-
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLPermission;
 import javax.net.ssl.SSLSession;
@@ -33,7 +32,6 @@
 import javax.net.ssl.SSLSessionBindingListener;
 import javax.net.ssl.SSLSessionContext;
 import javax.security.cert.CertificateEncodingException;
-
 import org.apache.harmony.luni.util.TwoKeyHashMap;
 import org.apache.harmony.security.provider.cert.X509CertImpl;
 
@@ -54,6 +52,8 @@
     protected int sslSessionNativePointer;
     private String peerHost;
     private int peerPort;
+    private String cipherSuite;
+    private String protocol;
     private AbstractSessionContext sessionContext;
     private byte[] id;
 
@@ -310,7 +310,14 @@
      *         actual SSL session.
      */
     public String getCipherSuite() {
-        return NativeCrypto.SSL_SESSION_cipher(sslSessionNativePointer);
+        if (cipherSuite == null) {
+            String name = NativeCrypto.SSL_SESSION_cipher(sslSessionNativePointer);
+            cipherSuite = NativeCrypto.OPENSSL_TO_STANDARD.get(name);
+            if (cipherSuite == null) {
+                cipherSuite = name;
+            }
+        }
+        return cipherSuite;
     }
 
     /**
@@ -322,7 +329,10 @@
      *
      */
     public String getProtocol() {
-        return NativeCrypto.SSL_SESSION_get_version(sslSessionNativePointer);
+        if (protocol == null) {
+            protocol = NativeCrypto.SSL_SESSION_get_version(sslSessionNativePointer);
+        }
+        return protocol;
     }
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
index f643249..acb6098 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
@@ -213,9 +213,38 @@
                 super.getInetAddress().getHostName() == null) {
             return null;
         }
-        return (OpenSSLSessionImpl) sessionContext.getSession(
+        OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(
                 super.getInetAddress().getHostName(),
                 super.getPort());
+        if (session == null) {
+            return null;
+        }
+
+        String protocol = session.getProtocol();
+        boolean protocolFound = false;
+        for (String enabledProtocol : enabledProtocols) {
+            if (protocol.equals(enabledProtocol)) {
+                protocolFound = true;
+                break;
+            }
+        }
+        if (!protocolFound) {
+            return null;
+        }
+
+        String cipherSuite = session.getCipherSuite();
+        boolean cipherSuiteFound = false;
+        for (String enabledCipherSuite : enabledCipherSuites) {
+            if (cipherSuite.equals(enabledCipherSuite)) {
+                cipherSuiteFound = true;
+                break;
+            }
+        }
+        if (!cipherSuiteFound) {
+            return null;
+        }
+        
+        return session;
     }
 
     /**
@@ -323,7 +352,7 @@
         byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer);
         sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId);
         if (sslSession != null) {
-            session.lastAccessedTime = System.currentTimeMillis();
+            sslSession.lastAccessedTime = System.currentTimeMillis();
             LoggerHolder.logger.fine("Reused cached session for "
                                      + getInetAddress() + ".");
             NativeCrypto.SSL_SESSION_free(sslSessionNativePointer);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
index 6ba82ff..0352ef6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
@@ -16,10 +16,6 @@
 
 package org.apache.harmony.xnet.provider.jsse;
 
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
 import javax.net.ssl.SSLSession;
 
 /**
@@ -27,15 +23,6 @@
  * sessions using the ID provided by an SSL client.
  */
 public class ServerSessionContext extends AbstractSessionContext {
-
-    private final Map<ByteArray, SSLSession> sessions
-            = new LinkedHashMap<ByteArray, SSLSession>() {
-        @Override
-        protected boolean removeEldestEntry(
-                Map.Entry<ByteArray, SSLSession> eldest) {
-            return maximumSize > 0 && size() > maximumSize;
-        }
-    };
 
     private SSLServerSessionCache persistentCache;
 
@@ -56,58 +43,13 @@
         this.persistentCache = persistentCache;
     }
 
-    Iterator<SSLSession> sessionIterator() {
-        synchronized (sessions) {
-            SSLSession[] array = sessions.values().toArray(
-                    new SSLSession[sessions.size()]);
-            return Arrays.asList(array).iterator();
-        }
-    }
+    protected void sessionRemoved(SSLSession session) {}
 
-    void trimToSize() {
-        synchronized (sessions) {
-            int size = sessions.size();
-            if (size > maximumSize) {
-                int removals = size - maximumSize;
-                Iterator<SSLSession> i = sessions.values().iterator();
-                do {
-                    i.next();
-                    i.remove();
-                } while (--removals > 0);
-            }
-        }
-    }
-
-    public void setSessionTimeout(int seconds)
-            throws IllegalArgumentException {
-        if (seconds < 0) {
-            throw new IllegalArgumentException("seconds < 0");
-        }
-        timeout = seconds;
-
-        synchronized (sessions) {
-            Iterator<SSLSession> i = sessions.values().iterator();
-            while (i.hasNext()) {
-                SSLSession session = i.next();
-                // SSLSession's know their context and consult the
-                // timeout as part of their validity condition.
-                if (!session.isValid()) {
-                    i.remove();
-                }
-            }
-        }
-    }
-
-    public SSLSession getSession(byte[] sessionId) {
-        if (sessionId == null) {
-            throw new NullPointerException("sessionId == null");
-        }
-        ByteArray key = new ByteArray(sessionId);
-        SSLSession session;
-        synchronized (sessions) {
-            session = sessions.get(key);
-        }
-        if (session != null && session.isValid()) {
+    @Override
+    public SSLSession getSession(byte[] sessionId) 
+    {
+        SSLSession session = super.getSession(sessionId);
+        if (session != null) {
             return session;
         }
 
@@ -117,9 +59,7 @@
             if (data != null) {
                 session = toSession(data, null, -1);
                 if (session != null && session.isValid()) {
-                    synchronized (sessions) {
-                        sessions.put(key, session);
-                    }
+                    super.putSession(session);
                     return session;
                 }
             }
@@ -130,14 +70,7 @@
 
     @Override
     void putSession(SSLSession session) {
-        byte[] id = session.getId();
-        if (id.length == 0) {
-            return;
-        }
-        ByteArray key = new ByteArray(id);
-        synchronized (sessions) {
-            sessions.put(key, session);
-        }
+        super.putSession(session);
 
         // TODO: In background thread.
         if (persistentCache != null) {
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index 2c8a02a..0e9d641 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -1340,43 +1340,6 @@
     return (jint) sslCtx;
 }
 
-static jobjectArray makeCipherList(JNIEnv* env, STACK_OF(SSL_CIPHER)* cipher_list) {
-    // Create a String[].
-    jclass stringClass = env->FindClass("java/lang/String");
-    if (stringClass == NULL) {
-        return NULL;
-    }
-    int cipherCount = sk_SSL_CIPHER_num(cipher_list);
-    jobjectArray array = env->NewObjectArray(cipherCount, stringClass, NULL);
-    if (array == NULL) {
-        return NULL;
-    }
-
-    // Fill in the cipher names.
-    for (int i = 0; i < cipherCount; ++i) {
-        const char* c = sk_SSL_CIPHER_value(cipher_list, i)->name;
-        JNI_TRACE("makeCipherList[i=%d]=%s", i, c);
-        env->SetObjectArrayElement(array, i, env->NewStringUTF(c));
-    }
-    return array;
-}
-
-/**
- * Loads the ciphers suites that are supported by an SSL_CTX
- * and returns them in a string array.
- */
-static jobjectArray NativeCrypto_SSL_CTX_get_ciphers(JNIEnv* env,
-        jclass, jint ssl_ctx_address)
-{
-    SSL_CTX* ssl_ctx = to_SSL_CTX(ssl_ctx_address);
-    JNI_TRACE("ssl_ctx=%p NativeCrypto_SSL_CTX_get_ciphers", ssl_ctx);
-    if (ssl_ctx == NULL) {
-        jniThrowNullPointerException(env, "SSL_CTX is null");
-        return NULL;
-    }
-    return makeCipherList(env, ssl_ctx->cipher_list);
-}
-
 /**
  * public static native void SSL_CTX_free(int ssl_ctx)
  */
@@ -1617,34 +1580,50 @@
 }
 
 /**
- * Loads the ciphers suites that are enabled in the SSL
- * and returns them in a string array.
- */
-static jobjectArray NativeCrypto_SSL_get_ciphers(JNIEnv* env,
-        jclass, jint ssl_address)
-{
-    SSL* ssl = to_SSL(env, ssl_address, true);
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_get_ciphers", ssl);
-    if (ssl == NULL) {
-      return NULL;
-    }
-    return makeCipherList(env, SSL_get_ciphers(ssl));
-}
-
-/**
  * Sets the ciphers suites that are enabled in the SSL
  */
-static void NativeCrypto_SSL_set_cipher_list(JNIEnv* env, jclass,
-        jint ssl_address, jstring controlString)
+static void NativeCrypto_SSL_set_cipher_lists(JNIEnv* env, jclass,
+        jint ssl_address, jobjectArray cipherSuites)
 {
     SSL* ssl = to_SSL(env, ssl_address, true);
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_list controlString=%p", ssl, controlString);
+    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuites=%p", ssl, cipherSuites);
     if (ssl == NULL) {
-      return;
+        return;
     }
-    ScopedUtfChars str(env, controlString);
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_controlString str=%s", ssl, str.c_str());
-    int rc = SSL_set_cipher_list(ssl, str.c_str());
+
+    STACK_OF(SSL_CIPHER)* cipherstack = sk_SSL_CIPHER_new_null();
+    if (cipherstack == NULL) {
+        jniThrowRuntimeException(env, "sk_SSL_CIPHER_new_null failed");
+        return;
+    }
+
+    const SSL_METHOD* ssl_method = ssl->method;
+    int num_ciphers = ssl_method->num_ciphers();
+
+    int length = env->GetArrayLength(cipherSuites);
+    JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists length=%d", ssl, length);
+    for (int i = 0; i < length; i++) {
+        jstring cipherSuite = (jstring) env->GetObjectArrayElement(cipherSuites, i);
+        ScopedUtfChars c(env, cipherSuite);
+        JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists cipherSuite=%s", ssl, c.c_str());
+        bool found = false;
+        for (int j = 0; j < num_ciphers; j++) {
+            const SSL_CIPHER* cipher = ssl_method->get_cipher(j);
+            if ((strcmp(c.c_str(), cipher->name) == 0)
+                    && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
+                sk_SSL_CIPHER_push(cipherstack, cipher);
+                found = true;
+            }
+        }
+        if (!found) {
+            sk_SSL_CIPHER_free(cipherstack);
+            jniThrowException(env, "java/lang/IllegalArgumentException",
+                              "Could not find cipher suite.");
+            return;
+        }
+    }
+
+    int rc = SSL_set_cipher_lists(ssl, cipherstack);
     if (rc == 0) {
         freeSslErrorState();
         jniThrowException(env, "java/lang/IllegalArgumentException",
@@ -2561,53 +2540,51 @@
  * (3) pointer to C function.
  */
 static JNINativeMethod sNativeCryptoMethods[] = {
-    { "clinit",              "()V",           (void*)NativeCrypto_clinit},
-    { "EVP_PKEY_new_DSA",    "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_DSA },
-    { "EVP_PKEY_new_RSA",    "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_RSA },
-    { "EVP_PKEY_free",       "(I)V",          (void*)NativeCrypto_EVP_PKEY_free },
-    { "EVP_new",             "()I",           (void*)NativeCrypto_EVP_new },
-    { "EVP_free",            "(I)V",          (void*)NativeCrypto_EVP_free },
-    { "EVP_DigestFinal",     "(I[BI)I",       (void*)NativeCrypto_EVP_DigestFinal },
-    { "EVP_DigestInit",      "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_DigestInit },
-    { "EVP_DigestBlockSize", "(I)I",          (void*)NativeCrypto_EVP_DigestBlockSize },
-    { "EVP_DigestSize",      "(I)I",          (void*)NativeCrypto_EVP_DigestSize },
-    { "EVP_DigestUpdate",    "(I[BII)V",      (void*)NativeCrypto_EVP_DigestUpdate },
-    { "EVP_VerifyInit",      "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_VerifyInit },
-    { "EVP_VerifyUpdate",    "(I[BII)V",      (void*)NativeCrypto_EVP_VerifyUpdate },
-    { "EVP_VerifyFinal",     "(I[BIII)I",     (void*)NativeCrypto_EVP_VerifyFinal },
-    { "verifySignature",     "([B[BLjava/lang/String;[B[B)I", (void*)NativeCrypto_verifysignature},
-    { "SSL_CTX_new",         "()I",           (void*)NativeCrypto_SSL_CTX_new },
-    { "SSL_CTX_get_ciphers", "(I)[Ljava/lang/String;", (void*)NativeCrypto_SSL_CTX_get_ciphers},
-    { "SSL_CTX_free",        "(I)V",          (void*)NativeCrypto_SSL_CTX_free },
-    { "SSL_new",             "(ILjava/lang/String;Ljava/lang/String;[B)I", (void*)NativeCrypto_SSL_new},
-    { "SSL_get_mode",        "(I)J",          (void*)NativeCrypto_SSL_get_mode },
-    { "SSL_set_mode",        "(IJ)J",         (void*)NativeCrypto_SSL_set_mode },
-    { "SSL_clear_mode",      "(IJ)J",         (void*)NativeCrypto_SSL_clear_mode },
-    { "SSL_get_options",     "(I)J",          (void*)NativeCrypto_SSL_get_options },
-    { "SSL_set_options",     "(IJ)J",         (void*)NativeCrypto_SSL_set_options },
-    { "SSL_clear_options",   "(IJ)J",         (void*)NativeCrypto_SSL_clear_options },
-    { "SSL_get_ciphers",     "(I)[Ljava/lang/String;", (void*)NativeCrypto_SSL_get_ciphers },
-    { "SSL_set_cipher_list", "(ILjava/lang/String;)V", (void*)NativeCrypto_SSL_set_cipher_list },
-    { "SSL_set_verify",      "(II)V",         (void*)NativeCrypto_SSL_set_verify},
-    { "SSL_set_session",     "(II)V",         (void*)NativeCrypto_SSL_set_session },
+    { "clinit",               "()V",           (void*)NativeCrypto_clinit},
+    { "EVP_PKEY_new_DSA",     "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_DSA },
+    { "EVP_PKEY_new_RSA",     "([B[B[B[B[B)I", (void*)NativeCrypto_EVP_PKEY_new_RSA },
+    { "EVP_PKEY_free",        "(I)V",          (void*)NativeCrypto_EVP_PKEY_free },
+    { "EVP_new",              "()I",           (void*)NativeCrypto_EVP_new },
+    { "EVP_free",             "(I)V",          (void*)NativeCrypto_EVP_free },
+    { "EVP_DigestFinal",      "(I[BI)I",       (void*)NativeCrypto_EVP_DigestFinal },
+    { "EVP_DigestInit",       "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_DigestInit },
+    { "EVP_DigestBlockSize",  "(I)I",          (void*)NativeCrypto_EVP_DigestBlockSize },
+    { "EVP_DigestSize",       "(I)I",          (void*)NativeCrypto_EVP_DigestSize },
+    { "EVP_DigestUpdate",     "(I[BII)V",      (void*)NativeCrypto_EVP_DigestUpdate },
+    { "EVP_VerifyInit",       "(ILjava/lang/String;)V", (void*)NativeCrypto_EVP_VerifyInit },
+    { "EVP_VerifyUpdate",     "(I[BII)V",      (void*)NativeCrypto_EVP_VerifyUpdate },
+    { "EVP_VerifyFinal",      "(I[BIII)I",     (void*)NativeCrypto_EVP_VerifyFinal },
+    { "verifySignature",      "([B[BLjava/lang/String;[B[B)I", (void*)NativeCrypto_verifysignature},
+    { "SSL_CTX_new",          "()I",           (void*)NativeCrypto_SSL_CTX_new },
+    { "SSL_CTX_free",         "(I)V",          (void*)NativeCrypto_SSL_CTX_free },
+    { "SSL_new",              "(ILjava/lang/String;Ljava/lang/String;[B)I", (void*)NativeCrypto_SSL_new},
+    { "SSL_get_mode",         "(I)J",          (void*)NativeCrypto_SSL_get_mode },
+    { "SSL_set_mode",         "(IJ)J",         (void*)NativeCrypto_SSL_set_mode },
+    { "SSL_clear_mode",       "(IJ)J",         (void*)NativeCrypto_SSL_clear_mode },
+    { "SSL_get_options",      "(I)J",          (void*)NativeCrypto_SSL_get_options },
+    { "SSL_set_options",      "(IJ)J",         (void*)NativeCrypto_SSL_set_options },
+    { "SSL_clear_options",    "(IJ)J",         (void*)NativeCrypto_SSL_clear_options },
+    { "SSL_set_cipher_lists", "(I[Ljava/lang/String;)V", (void*)NativeCrypto_SSL_set_cipher_lists },
+    { "SSL_set_verify",       "(II)V",         (void*)NativeCrypto_SSL_set_verify},
+    { "SSL_set_session",      "(II)V",         (void*)NativeCrypto_SSL_set_session },
     { "SSL_set_session_creation_enabled", "(IZ)V", (void*)NativeCrypto_SSL_set_session_creation_enabled },
-    { "SSL_do_handshake",    "(ILjava/net/Socket;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$CertificateChainVerifier;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$HandshakeCompletedCallback;IZ)I",(void*)NativeCrypto_SSL_do_handshake},
-    { "SSL_get_certificate", "(I)[[B",        (void*)NativeCrypto_SSL_get_certificate},
-    { "SSL_read_byte",       "(II)I",         (void*)NativeCrypto_SSL_read_byte},
-    { "SSL_read",            "(I[BIII)I",     (void*)NativeCrypto_SSL_read},
-    { "SSL_write_byte",      "(II)V",         (void*)NativeCrypto_SSL_write_byte},
-    { "SSL_write",           "(I[BII)V",      (void*)NativeCrypto_SSL_write},
-    { "SSL_interrupt",       "(I)V",          (void*)NativeCrypto_SSL_interrupt},
-    { "SSL_shutdown",        "(I)V",          (void*)NativeCrypto_SSL_shutdown},
-    { "SSL_free",            "(I)V",          (void*)NativeCrypto_SSL_free},
-    { "SSL_SESSION_session_id", "(I)[B",      (void*)NativeCrypto_SSL_SESSION_session_id },
+    { "SSL_do_handshake",     "(ILjava/net/Socket;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$CertificateChainVerifier;Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$HandshakeCompletedCallback;IZ)I",(void*)NativeCrypto_SSL_do_handshake},
+    { "SSL_get_certificate",  "(I)[[B",        (void*)NativeCrypto_SSL_get_certificate},
+    { "SSL_read_byte",        "(II)I",         (void*)NativeCrypto_SSL_read_byte},
+    { "SSL_read",             "(I[BIII)I",     (void*)NativeCrypto_SSL_read},
+    { "SSL_write_byte",       "(II)V",         (void*)NativeCrypto_SSL_write_byte},
+    { "SSL_write",            "(I[BII)V",      (void*)NativeCrypto_SSL_write},
+    { "SSL_interrupt",        "(I)V",          (void*)NativeCrypto_SSL_interrupt},
+    { "SSL_shutdown",         "(I)V",          (void*)NativeCrypto_SSL_shutdown},
+    { "SSL_free",             "(I)V",          (void*)NativeCrypto_SSL_free},
+    { "SSL_SESSION_session_id", "(I)[B",       (void*)NativeCrypto_SSL_SESSION_session_id },
     { "SSL_SESSION_get_peer_cert_chain", "(II)[[B", (void*)NativeCrypto_SSL_SESSION_get_peer_cert_chain },
-    { "SSL_SESSION_get_time", "(I)J",         (void*)NativeCrypto_SSL_SESSION_get_time },
+    { "SSL_SESSION_get_time", "(I)J",          (void*)NativeCrypto_SSL_SESSION_get_time },
     { "SSL_SESSION_get_version", "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_get_version },
-    { "SSL_SESSION_cipher",  "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_cipher },
-    { "SSL_SESSION_free",    "(I)V",          (void*)NativeCrypto_SSL_SESSION_free },
-    { "i2d_SSL_SESSION",     "(I)[B",         (void*)NativeCrypto_i2d_SSL_SESSION },
-    { "d2i_SSL_SESSION",     "([BI)I",        (void*)NativeCrypto_d2i_SSL_SESSION },
+    { "SSL_SESSION_cipher",   "(I)Ljava/lang/String;", (void*)NativeCrypto_SSL_SESSION_cipher },
+    { "SSL_SESSION_free",     "(I)V",          (void*)NativeCrypto_SSL_SESSION_free },
+    { "i2d_SSL_SESSION",      "(I)[B",         (void*)NativeCrypto_i2d_SSL_SESSION },
+    { "d2i_SSL_SESSION",      "([BI)I",        (void*)NativeCrypto_d2i_SSL_SESSION },
 };
 
 int register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) {
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
index 855949d..f8aed75 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
@@ -16,32 +16,44 @@
 
 package javax.net.ssl;
 
-import dalvik.annotation.KnownFailure;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import junit.framework.TestCase;
 
 public class SSLSessionContextTest extends TestCase {
 
-    public static final void assertSSLSessionContextSize(int expected, SSLSessionContext s) {
-        assertEquals(expected, Collections.list(s.getIds()).size());
+    public static final void assertSSLSessionContextSize(int expected, SSLContext sslContext) {
+        assertSSLSessionContextSize(expected, 
+                                    sslContext.getClientSessionContext(),
+                                    sslContext.getServerSessionContext());
+    }
+
+    public static final void assertSSLSessionContextSize(int expected, 
+                                                         SSLSessionContext client, 
+                                                         SSLSessionContext server) {
+        assertSSLSessionContextSize(expected, client, false);
+        assertSSLSessionContextSize(expected, server, true);
+    }
+
+    public static final void assertSSLSessionContextSize(int expected, SSLSessionContext s, boolean server) {
+        int size = Collections.list(s.getIds()).size();
+        if (server && TestSSLContext.sslServerSocketSupportsSessionTickets()) {
+            assertEquals(0, size);
+        } else {
+            assertEquals(expected, size);
+        }
     }
 
     public void test_SSLSessionContext_getIds() {
         TestSSLContext c = TestSSLContext.create();
-        assertSSLSessionContextSize(0, c.sslContext.getClientSessionContext());
-        assertSSLSessionContextSize(0, c.sslContext.getServerSessionContext());
+        assertSSLSessionContextSize(0, c.sslContext);
 
         TestSSLSocketPair s = TestSSLSocketPair.create();
-        assertSSLSessionContextSize(1, s.c.sslContext.getClientSessionContext());
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext());
-        } else {
-            assertSSLSessionContextSize(1, s.c.sslContext.getServerSessionContext());
-        }
+        assertSSLSessionContextSize(1, s.c.sslContext);
         Enumeration clientIds = s.c.sslContext.getClientSessionContext().getIds();
         Enumeration serverIds = s.c.sslContext.getServerSessionContext().getIds();
         byte[] clientId = (byte[]) clientIds.nextElement();
@@ -101,15 +113,15 @@
                      s.c.sslContext.getServerSessionContext().getSessionCacheSize());
     }
 
-    public void test_SSLSessionContext_setSessionCacheSize_basic() {
+    public void test_SSLSessionContext_setSessionCacheSize_noConnect() {
         TestSSLContext c = TestSSLContext.create();
-        assertBasicSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
-                                               c.sslContext.getClientSessionContext());
-        assertBasicSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
-                                               c.sslContext.getServerSessionContext());
+        assertNoConnectSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE,
+                                                   c.sslContext.getClientSessionContext());
+        assertNoConnectSetSessionCacheSizeBehavior(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
+                                                   c.sslContext.getServerSessionContext());
     }
 
-    private static void assertBasicSetSessionCacheSizeBehavior(int expectedDefault, SSLSessionContext s) {
+    private static void assertNoConnectSetSessionCacheSizeBehavior(int expectedDefault, SSLSessionContext s) {
         try {
             s.setSessionCacheSize(-1);
             fail();
@@ -120,9 +132,7 @@
         assertEquals(1, s.getSessionCacheSize());
     }
 
-    @KnownFailure("Using OpenSSL cipher suite names")
-    public void test_SSLSessionContext_setSessionCacheSize_dynamic() {
-
+    public void test_SSLSessionContext_setSessionCacheSize_oneConnect() {
         TestSSLSocketPair s = TestSSLSocketPair.create();
         SSLSessionContext client = s.c.sslContext.getClientSessionContext();
         SSLSessionContext server = s.c.sslContext.getServerSessionContext();
@@ -130,21 +140,29 @@
                      client.getSessionCacheSize());
         assertEquals(TestSSLContext.EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE,
                      server.getSessionCacheSize());
-        assertSSLSessionContextSize(1, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(1, server);
-        }
+        assertSSLSessionContextSize(1, s.c.sslContext);
+    }
 
-        LinkedList<String> uniqueCipherSuites
-            = new LinkedList(Arrays.asList(s.server.getEnabledCipherSuites()));
-        uniqueCipherSuites.remove(s.client.getSession().getCipherSuite());
+    public void test_SSLSessionContext_setSessionCacheSize_dynamic() {
+        TestSSLContext c = TestSSLContext.create();
+        SSLSessionContext client = c.sslContext.getClientSessionContext();
+        SSLSessionContext server = c.sslContext.getServerSessionContext();
 
+        String[] supportedCipherSuites = c.serverSocket.getSupportedCipherSuites();
+        c.serverSocket.setEnabledCipherSuites(supportedCipherSuites);
+        LinkedList<String> uniqueCipherSuites 
+            = new LinkedList(Arrays.asList(supportedCipherSuites));
         // only use RSA cipher suites which will work with our TrustProvider
         Iterator<String> i = uniqueCipherSuites.iterator();
         while (i.hasNext()) {
             String cipherSuite = i.next();
+
+            // Certificate key length too long for export ciphers
+            if (cipherSuite.startsWith("SSL_RSA_EXPORT_")) {
+                i.remove();
+                continue;
+            }
+
             if (cipherSuite.startsWith("SSL_RSA_")) {
                 continue;
             }
@@ -161,7 +179,7 @@
         }
 
         /*
-         * having more than 5 uniqueCipherSuites is a test
+         * having more than 3 uniqueCipherSuites is a test
          * requirement, not a requirement of the interface or
          * implementation. It simply allows us to make sure that we
          * will not get a cached session ID since we'll have to
@@ -170,59 +188,32 @@
          * reused the unique cipher suites every time it resets the
          * session cache.
          */
-        // TODO Fix Known Failure
-        // Need to fix CipherSuites methods to use JSSE names
-        assertTrue(uniqueCipherSuites.size() > 5);
-
-        TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 1
-        assertSSLSessionContextSize(2, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(2, server);
-        }
-        TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 2
-        assertSSLSessionContextSize(3, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(3, server);
-        }
+        assertTrue(uniqueCipherSuites.size() >= 3);
+        String cipherSuite1 = uniqueCipherSuites.get(0);
+        String cipherSuite2 = uniqueCipherSuites.get(1);
+        String cipherSuite3 = uniqueCipherSuites.get(2);
+        
+        TestSSLSocketPair.connect(c, new String[] { cipherSuite1 });
+        assertSSLSessionContextSize(1, c.sslContext);
+        TestSSLSocketPair.connect(c, new String[] { cipherSuite2 });
+        assertSSLSessionContextSize(2, c.sslContext);
+        TestSSLSocketPair.connect(c, new String[] { cipherSuite3 });
+        assertSSLSessionContextSize(3, c.sslContext);
 
         client.setSessionCacheSize(1);
         server.setSessionCacheSize(1);
         assertEquals(1, client.getSessionCacheSize());
         assertEquals(1, server.getSessionCacheSize());
-        assertSSLSessionContextSize(1, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(1, server);
-        }
-        TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 3
-        assertSSLSessionContextSize(1, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(1, server);
-        }
+        assertSSLSessionContextSize(1, c.sslContext);
+        TestSSLSocketPair.connect(c, new String[] { cipherSuite1 });
+        assertSSLSessionContextSize(1, c.sslContext);
 
         client.setSessionCacheSize(2);
         server.setSessionCacheSize(2);
-        TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 4
-        assertSSLSessionContextSize(2, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(2, server);
-        }
-        TestSSLSocketPair.connect(s.c, new String[] { uniqueCipherSuites.remove() }); // 5
-        assertSSLSessionContextSize(2, client);
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, server);
-        } else {
-            assertSSLSessionContextSize(2, server);
-        }
+        TestSSLSocketPair.connect(c, new String[] { cipherSuite2 });
+        assertSSLSessionContextSize(2, c.sslContext);
+        TestSSLSocketPair.connect(c, new String[] { cipherSuite3 });
+        assertSSLSessionContextSize(2, c.sslContext);
     }
 
     public void test_SSLSessionContext_getSessionTimeout() {
@@ -262,16 +253,10 @@
         }
 
         TestSSLSocketPair s = TestSSLSocketPair.create();
-        assertSSLSessionContextSize(1, s.c.sslContext.getClientSessionContext());
-        if (TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-            assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext());
-        } else {
-            assertSSLSessionContextSize(1, s.c.sslContext.getServerSessionContext());
-        }
+        assertSSLSessionContextSize(1, s.c.sslContext);
         Thread.sleep(1 * 1000);
         s.c.sslContext.getClientSessionContext().setSessionTimeout(1);
         s.c.sslContext.getServerSessionContext().setSessionTimeout(1);
-        assertSSLSessionContextSize(0, s.c.sslContext.getClientSessionContext());
-        assertSSLSessionContextSize(0, s.c.sslContext.getServerSessionContext());
+        assertSSLSessionContextSize(0, s.c.sslContext);
     }
 }
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
index 36b565b..eb15e57 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionTest.java
@@ -47,6 +47,7 @@
         assertNotNull(s.client.getCipherSuite());
         assertEquals(s.server.getCipherSuite(),
                      s.client.getCipherSuite());
+        assertTrue(StandardNames.CIPHER_SUITES.contains(s.server.getCipherSuite()));
     }
 
     public void test_SSLSession_getCreationTime() {
@@ -199,6 +200,7 @@
         assertNotNull(s.client.getProtocol());
         assertEquals(s.server.getProtocol(),
                      s.client.getProtocol());
+        assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(s.server.getProtocol()));
     }
 
     public void test_SSLSession_getSessionContext() {
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
index bb76390..15e2e71 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
@@ -36,7 +36,6 @@
         assertTrue(SSLSocketFactory.class.isAssignableFrom(sf.getClass()));
     }
 
-    @KnownFailure("Using OpenSSL cipher suite names")
     public void test_SSLSocketFactory_getDefaultCipherSuites() {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         String[] cipherSuites = sf.getDefaultCipherSuites();
@@ -52,13 +51,10 @@
 
         // Make sure all cipherSuites names are expected
         for (String cipherSuite : cipherSuites) {
-            // TODO Fix Known Failure
-            // Need to fix CipherSuites methods to use JSSE names
             assertTrue(StandardNames.CIPHER_SUITES.contains(cipherSuite));
         }
     }
 
-    @KnownFailure("Using OpenSSL cipher suite names")
     public void test_SSLSocketFactory_getSupportedCipherSuites() {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         String[] cipherSuites = sf.getSupportedCipherSuites();
@@ -75,11 +71,11 @@
         // Make sure all cipherSuites names are expected
         Set remainingCipherSuites = new HashSet<String>(StandardNames.CIPHER_SUITES);
         for (String cipherSuite : cipherSuites) {
-            assertNotNull(remainingCipherSuites.remove(cipherSuite));
+            assertTrue(remainingCipherSuites.remove(cipherSuite));
         }
-        // TODO Fix Known Failure
-        // Need to fix CipherSuites methods to use JSSE names
         assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
+
+        assertEquals(StandardNames.CIPHER_SUITES.size(), cipherSuites.length);
     }
 
     @KnownFailure("Should not parse bogus port number -1 during createSocket")
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
index f9766a1..3a44510 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
@@ -33,7 +33,6 @@
 
 public class SSLSocketTest extends TestCase {
 
-    @KnownFailure("Using OpenSSL cipher suite names")
     public void test_SSLSocket_getSupportedCipherSuites() throws Exception {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         SSLSocket ssl = (SSLSocket) sf.createSocket();
@@ -42,14 +41,12 @@
         assertTrue(cipherSuites.length != 0);
         Set remainingCipherSuites = new HashSet<String>(StandardNames.CIPHER_SUITES);
         for (String cipherSuite : cipherSuites) {
-            assertNotNull(remainingCipherSuites.remove(cipherSuite));
+            assertTrue(remainingCipherSuites.remove(cipherSuite));
         }
-        // TODO Fix Known Failure
-        // Need to fix CipherSuites methods to use JSSE names
         assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
+        assertEquals(StandardNames.CIPHER_SUITES.size(), cipherSuites.length);
     }
 
-    @KnownFailure("Using OpenSSL cipher suite names")
     public void test_SSLSocket_getEnabledCipherSuites() throws Exception {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         SSLSocket ssl = (SSLSocket) sf.createSocket();
@@ -66,8 +63,6 @@
 
         // Make sure all cipherSuites names are expected
         for (String cipherSuite : cipherSuites) {
-            // TODO Fix Known Failure
-            // Need to fix CipherSuites methods to use JSSE names
             assertTrue(StandardNames.CIPHER_SUITES.contains(cipherSuite));
         }
     }
diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
index cdad187..bce302a 100644
--- a/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
+++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
@@ -178,7 +178,7 @@
     @AndroidOnly("Uses bks key store. Change useBKS to false to run on the RI")
     public void test_getCipherSuite() {
         try {
-            assertEquals(cipherSuite, clientSession.getCipherSuite());
+            assertEquals(CIPHER_SUITE, clientSession.getCipherSuite());
         } catch (Exception ex) {
             fail("Unexpected exception " + ex);
         }
@@ -571,9 +571,6 @@
         public void valueUnbound(SSLSessionBindingEvent event) {}
     }
 
-
-
-    String cipherSuiteBKS = "AES256-SHA";
     /**
      * Defines the keystore contents for the server, BKS version. Holds just a
      * single self-generated key. The subject name is "Test Server".
@@ -634,7 +631,7 @@
         "uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef" +
         "lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
 
-    String cipherSuiteJKS = "SSL_RSA_WITH_RC4_128_MD5";
+    private static final String CIPHER_SUITE = "SSL_RSA_WITH_RC4_128_MD5";
     /**
      * Defines the keystore contents for the server, JKS version. Holds just a
      * single self-generated key. The subject name is "Test Server".
@@ -706,8 +703,6 @@
     String testData = "PING";
 
     private String PASSWORD = "android";
-
-    String cipherSuite = (useBKS ? cipherSuiteBKS : cipherSuiteJKS);
 
     /**
      * Implements a test SSL socket server. It waits for a connection on a given
diff --git a/run-core-tests b/run-core-tests
index b1df621..893b0d6 100755
--- a/run-core-tests
+++ b/run-core-tests
@@ -25,7 +25,7 @@
 
 # Build the classpath by putting together the jar file for each module.
 classpath="/system/framework/sqlite-jdbc.jar" # Bonus item for jdbc testing.
-modules="dom json luni-kernel luni prefs support x-net xml"
+modules="dom json luni support xml"
 for module in $modules; do
   classpath="$classpath:/system/framework/core-tests-$module.jar"
 done
diff --git a/support/src/test/java/javax/net/ssl/StandardNames.java b/support/src/test/java/javax/net/ssl/StandardNames.java
index ccd3ee1..86dbd78 100644
--- a/support/src/test/java/javax/net/ssl/StandardNames.java
+++ b/support/src/test/java/javax/net/ssl/StandardNames.java
@@ -18,11 +18,15 @@
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
 /**
  * This class defines expected string names for protocols, key types, client and server auth types, cipher suites.
+ * 
  * Based on documentation from http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#AppA
+ *
+ * Java 6 version http://java.sun.com/javase/6/docs/technotes/guides/security/SunProviders.html
  */
 public final class StandardNames {
 
@@ -63,50 +67,106 @@
         "RSA_EXPORT1024",
         "UNKNOWN"));
 
-    // removed cipher suites not actually found in RI
-    public static final Set<String> CIPHER_SUITES = new HashSet<String>(Arrays.asList(
-        "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
-        "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
-        "SSL_DHE_DSS_WITH_DES_CBC_SHA",
-        "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
-        "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
-        "SSL_DHE_RSA_WITH_DES_CBC_SHA",
-        //"SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
-        //"SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
-        "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-        "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
-        "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
-        "SSL_DH_anon_WITH_DES_CBC_SHA",
-        "SSL_DH_anon_WITH_RC4_128_MD5",
-        //"SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA",
-        //"SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",
-        "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
-        //"SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",
-        "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
-        "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
-        "SSL_RSA_WITH_DES_CBC_SHA",
-        "SSL_RSA_WITH_NULL_MD5",
-        "SSL_RSA_WITH_NULL_SHA",
-        "SSL_RSA_WITH_RC4_128_MD5",
-        "SSL_RSA_WITH_RC4_128_SHA",
-        "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
-        //"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
-        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
-        //"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
-        "TLS_DH_anon_WITH_AES_128_CBC_SHA",
-        //"TLS_DH_anon_WITH_AES_256_CBC_SHA",
-        "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
-        "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
-        //"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",
-        //"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",
-        "TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
-        "TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
-        "TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
-        "TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
-        "TLS_KRB5_WITH_DES_CBC_MD5",
-        "TLS_KRB5_WITH_DES_CBC_SHA",
-        "TLS_KRB5_WITH_RC4_128_MD5",
-        "TLS_KRB5_WITH_RC4_128_SHA",
-        "TLS_RSA_WITH_AES_128_CBC_SHA"));
-        //"TLS_RSA_WITH_AES_256_CBC_SHA"));
+    public static final Set<String> CIPHER_SUITES_NEITHER = new HashSet<String>();
+
+    public static final Set<String> CIPHER_SUITES_RI = new LinkedHashSet<String>();
+    public static final Set<String> CIPHER_SUITES_OPENSSL = new LinkedHashSet<String>();
+
+    public static final Set<String> CIPHER_SUITES;
+
+    private static final void addRi(String cipherSuite) {
+        CIPHER_SUITES_RI.add(cipherSuite);
+    }
+
+    private static final void addOpenSsl(String cipherSuite) {
+        CIPHER_SUITES_OPENSSL.add(cipherSuite);
+    }
+
+    private static final void addBoth(String cipherSuite) {
+        addRi(cipherSuite);
+        addOpenSsl(cipherSuite);
+    }
+
+    static {
+        // Note these are added in priority order as defined by RI 6 documentation.
+        addBoth(   "SSL_RSA_WITH_RC4_128_MD5");
+        addBoth(   "SSL_RSA_WITH_RC4_128_SHA");
+        addBoth(   "TLS_RSA_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_RSA_WITH_AES_256_CBC_SHA");
+        addOpenSsl("TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
+        addOpenSsl("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+        addOpenSsl("TLS_ECDH_RSA_WITH_RC4_128_SHA");
+        addOpenSsl("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
+        addOpenSsl("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
+        addOpenSsl("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
+        addOpenSsl("TLS_ECDHE_RSA_WITH_RC4_128_SHA");
+        addOpenSsl("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
+        addBoth(   "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
+        addBoth(   "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
+        addBoth(   "SSL_RSA_WITH_3DES_EDE_CBC_SHA");
+        addOpenSsl("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
+        addOpenSsl("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
+        addOpenSsl("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
+        addOpenSsl("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "SSL_RSA_WITH_DES_CBC_SHA");
+        addBoth(   "SSL_DHE_RSA_WITH_DES_CBC_SHA");
+        addBoth(   "SSL_DHE_DSS_WITH_DES_CBC_SHA");
+        addBoth(   "SSL_RSA_EXPORT_WITH_RC4_40_MD5");
+        addBoth(   "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA");
+        addBoth(   "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
+        addBoth(   "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+        addBoth(   "SSL_RSA_WITH_NULL_MD5");
+        addBoth(   "SSL_RSA_WITH_NULL_SHA");
+        addOpenSsl("TLS_ECDH_ECDSA_WITH_NULL_SHA");
+        addOpenSsl("TLS_ECDH_RSA_WITH_NULL_SHA");
+        addOpenSsl("TLS_ECDHE_ECDSA_WITH_NULL_SHA");
+        addOpenSsl("TLS_ECDHE_RSA_WITH_NULL_SHA");
+        addBoth(   "SSL_DH_anon_WITH_RC4_128_MD5");
+        addBoth(   "TLS_DH_anon_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_DH_anon_WITH_AES_256_CBC_SHA");
+        addBoth(   "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "SSL_DH_anon_WITH_DES_CBC_SHA");
+        addOpenSsl("TLS_ECDH_anon_WITH_RC4_128_SHA");
+        addOpenSsl("TLS_ECDH_anon_WITH_AES_128_CBC_SHA");
+        addOpenSsl("TLS_ECDH_anon_WITH_AES_256_CBC_SHA");
+        addOpenSsl("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5");
+        addBoth(   "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA");
+        addOpenSsl("TLS_ECDH_anon_WITH_NULL_SHA");
+
+        // Android does not have Keberos support
+        addRi     ("TLS_KRB5_WITH_RC4_128_SHA");
+        addRi     ("TLS_KRB5_WITH_RC4_128_MD5");
+        addRi     ("TLS_KRB5_WITH_3DES_EDE_CBC_SHA");
+        addRi     ("TLS_KRB5_WITH_3DES_EDE_CBC_MD5");
+        addRi     ("TLS_KRB5_WITH_DES_CBC_SHA");
+        addRi     ("TLS_KRB5_WITH_DES_CBC_MD5");
+        addRi     ("TLS_KRB5_EXPORT_WITH_RC4_40_SHA");
+        addRi     ("TLS_KRB5_EXPORT_WITH_RC4_40_MD5");
+        addRi     ("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA");
+        addRi     ("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5");
+
+        // Dropped
+        CIPHER_SUITES_NEITHER.add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
+        CIPHER_SUITES_NEITHER.add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
+
+        // Old non standard exportable encryption
+        CIPHER_SUITES_NEITHER.add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA");
+        CIPHER_SUITES_NEITHER.add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA");
+        
+        // No RC2
+        CIPHER_SUITES_NEITHER.add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5");
+        CIPHER_SUITES_NEITHER.add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA");
+        CIPHER_SUITES_NEITHER.add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5");
+        
+        CIPHER_SUITES = (TestSSLContext.IS_RI) ? CIPHER_SUITES_RI : CIPHER_SUITES_OPENSSL;
+    }
 }