Elliptic Crypto support for OpenSSLSocketImpl

Summary:
- Enable Elliptic Crypto support for OpenSSL based SSLSocket instances
- More RI compliant usage of key types, client auth types, and server auth types
- Steps toward TLS_EMPTY_RENEGOTIATION_INFO_SCSV support, currently test updates

Details:

Elliptic Curve changes

    CipherSuite updates for EC
    - Adding KEY_EXCHANGE_EC* and corresponding CipherSuites Updated
      isAnonymous, getKeyType (now renamed getServerKeyType) to handle
      new EC cases.  Added new getAuthType for use by
      checkServerTrusted callers.
    - Restructured code to handle two SUITES_BY_CODE_* arrays
    - Remove KEY_EXCHANGE_DH_* definitions which unused because the
      corresponding CipherSuites were previously disabled.
    - Changed AES CipherSuites definitions to use "_CBC" to match other definitions.
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java

    openssl EC
    - NativeCrypto now registers TLS_EC_* cipher suites and has update default list
    - Improved auth type arguments to checkClientTrusted/checkServerTrusted
    - NativeCrypto support for emphemeral EC keys
	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

non-openssl SSL/TLS cleanups

    - cleanup around code trying to cope with DiffieHellman vs DH since either should work.
    - changed client to use new CipherSuite.getAuthType shared with NativeCrypto implementation
    - changed server to use CipherSuite.getKeyType
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java

Consolidate CertificateRequestType code into CipherSuite so that its
shared between java and openssl implementations. This includes the
KEY_TYPE_ string constants, TLS_CT_* byte constants and the 'String
keyType(byte)' (now renamed getClientKeyType) code that depends on them.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java

Tests

   Differentiate between supported list of cipher suites openssl-based
   SSLSocket and SSLEngine based, since the SSLEngine code does not support EC.

	luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
	luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java

   Added testing for expected default cipher suites. Before we just ensured the values were valid.
	luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
	support/src/test/java/libcore/java/security/StandardNames.java

   Updated to handle new EC cipher suites codes. Added test for new getClientKeyType.
	luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java

   Better use of "standard names" particularly to correctly deal with
   the subtle differences between key types, client auth types, and
   server auth types. TestKeyManager and TestTrustManager now verify
   the values they are passed are acceptable.

	support/src/test/java/libcore/java/security/StandardNames.java
	support/src/test/java/libcore/javax/net/ssl/TestKeyManager.java
	support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java

   Changed to timeout after 30 seconds and to log to reveal both client and server issues.
	support/src/test/java/libcore/javax/net/ssl/TestSSLSocketPair.java

Bug: 3058375
Change-Id: I14d1d0285d591c99cc211324f3595a5be682cab1
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
index 748e7df..49f63bf 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
@@ -31,15 +31,6 @@
 public class CertificateRequest extends Message {
 
     /**
-     * Client certificate types as defined in
-     * TLS 1.0 spec., 7.4.4. Certificate request
-     */
-    public static final byte RSA_SIGN = 1;
-    public static final byte DSS_SIGN = 2;
-    public static final byte RSA_FIXED_DH = 3;
-    public static final byte DSS_FIXED_DH = 4;
-
-    /**
      * Requested certificate types
      */
     final byte[] certificate_types;
@@ -161,23 +152,12 @@
         if (types == null) {
             types = new String[certificate_types.length];
             for (int i = 0; i < types.length; i++) {
-                switch (certificate_types[i]) {
-                case 1:
-                    types[i] = "RSA";
-                    break;
-                case 2:
-                    types[i] = "DSA";
-                    break;
-                case 3:
-                    types[i] = "DH_RSA";
-                    break;
-                case 4:
-                    types[i] = "DH_DSA";
-                    break;
-                default:
+                String type = CipherSuite.getClientKeyType(certificate_types[i]);
+                if (type == null) {
                     fatalAlert(AlertProtocol.DECODE_ERROR,
                             "DECODE ERROR: incorrect CertificateRequest");
                 }
+                types[i] = type;
             }
         }
         return types;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
index 9d3b1ad..c20a0b9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
@@ -86,12 +86,21 @@
     static final int KEY_EXCHANGE_DHE_DSS_EXPORT = 4;
     static final int KEY_EXCHANGE_DHE_RSA = 5;
     static final int KEY_EXCHANGE_DHE_RSA_EXPORT = 6;
-    static final int KEY_EXCHANGE_DH_DSS = 7;
-    static final int KEY_EXCHANGE_DH_RSA = 8;
+    // BEGIN android-removed
+    // static final int KEY_EXCHANGE_DH_DSS = 7;
+    // static final int KEY_EXCHANGE_DH_RSA = 8;
+    // END android-removed
     static final int KEY_EXCHANGE_DH_anon = 9;
     static final int KEY_EXCHANGE_DH_anon_EXPORT = 10;
-    static final int KEY_EXCHANGE_DH_DSS_EXPORT = 11;
-    static final int KEY_EXCHANGE_DH_RSA_EXPORT = 12;
+    // BEGIN android-removed
+    // static final int KEY_EXCHANGE_DH_DSS_EXPORT = 11;
+    // static final int KEY_EXCHANGE_DH_RSA_EXPORT = 12;
+    // END android-removed
+    static final int KEY_EXCHANGE_ECDH_ECDSA = 13;
+    static final int KEY_EXCHANGE_ECDHE_ECDSA = 14;
+    static final int KEY_EXCHANGE_ECDH_RSA = 15;
+    static final int KEY_EXCHANGE_ECDHE_RSA = 16;
+    static final int KEY_EXCHANGE_ECDH_anon = 17;
 
     /**
      * TLS cipher suite codes
@@ -143,6 +152,33 @@
     static final byte[] CODE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = { 0x00, 0x39 };
     static final byte[] CODE_TLS_DH_anon_WITH_AES_256_CBC_SHA = { 0x00, 0x3A };
 
+    // EC Cipher Suites from RFC 4492 - http://www.ietf.org/rfc/rfc4492.txt
+    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_NULL_SHA = { (byte) 0xc0, 0x01};
+    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x02};
+    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x03};
+    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x04};
+    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x05};
+    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_NULL_SHA = { (byte) 0xc0, 0x06};
+    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x07};
+    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x08};
+    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x09};
+    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x0A};
+    static final byte[] CODE_TLS_ECDH_RSA_WITH_NULL_SHA = { (byte) 0xc0, 0x0B};
+    static final byte[] CODE_TLS_ECDH_RSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x0C};
+    static final byte[] CODE_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x0D};
+    static final byte[] CODE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x0E};
+    static final byte[] CODE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x0F};
+    static final byte[] CODE_TLS_ECDHE_RSA_WITH_NULL_SHA = { (byte) 0xc0, 0x10};
+    static final byte[] CODE_TLS_ECDHE_RSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x11};
+    static final byte[] CODE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x12};
+    static final byte[] CODE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x13};
+    static final byte[] CODE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x14};
+    static final byte[] CODE_TLS_ECDH_anon_WITH_NULL_SHA = { (byte) 0xc0, 0x15};
+    static final byte[] CODE_TLS_ECDH_anon_WITH_RC4_128_SHA = { (byte) 0xc0, 0x16};
+    static final byte[] CODE_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x17};
+    static final byte[] CODE_TLS_ECDH_anon_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x18};
+    static final byte[] CODE_TLS_ECDH_anon_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x19};
+
     static final CipherSuite SSL_NULL_WITH_NULL_NULL = new CipherSuite(
             "SSL_NULL_WITH_NULL_NULL", true, 0, null, null, null,
             CODE_SSL_NULL_WITH_NULL_NULL);
@@ -270,7 +306,7 @@
                               false,
                               KEY_EXCHANGE_RSA,
                               "RSA",
-                              "AES_128",
+                              "AES_128_CBC",
                               "SHA",
                               CODE_TLS_RSA_WITH_AES_128_CBC_SHA);
     static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA
@@ -278,7 +314,7 @@
                               false,
                               KEY_EXCHANGE_DHE_DSS,
                               "DSA",
-                              "AES_128",
+                              "AES_128_CBC",
                               "SHA",
                               CODE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
     static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA
@@ -286,7 +322,7 @@
                               false,
                               KEY_EXCHANGE_DHE_RSA,
                               "RSA",
-                              "AES_128",
+                              "AES_128_CBC",
                               "SHA",
                               CODE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
     static final CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA
@@ -294,7 +330,7 @@
                               false,
                               KEY_EXCHANGE_DH_anon,
                               "DH",
-                              "AES_128",
+                              "AES_128_CBC",
                               "SHA",
                               CODE_TLS_DH_anon_WITH_AES_128_CBC_SHA);
     static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA
@@ -302,7 +338,7 @@
                               false,
                               KEY_EXCHANGE_RSA,
                               "RSA",
-                              "AES_256",
+                              "AES_256_CBC",
                               "SHA",
                               CODE_TLS_RSA_WITH_AES_256_CBC_SHA);
     static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA
@@ -310,7 +346,7 @@
                               false,
                               KEY_EXCHANGE_DHE_DSS,
                               "DSA",
-                              "AES_256",
+                              "AES_256_CBC",
                               "SHA",
                               CODE_TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
     static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA
@@ -318,7 +354,7 @@
                               false,
                               KEY_EXCHANGE_DHE_RSA,
                               "RSA",
-                              "AES_256",
+                              "AES_256_CBC",
                               "SHA",
                               CODE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
     static final CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA
@@ -326,79 +362,342 @@
                               false,
                               KEY_EXCHANGE_DH_anon,
                               "DH",
-                              "AES_256",
+                              "AES_256_CBC",
                               "SHA",
                               CODE_TLS_DH_anon_WITH_AES_256_CBC_SHA);
 
-    // array for quick access to cipher suite by code
-    private static final CipherSuite[] SUITES_BY_CODE = {
+    static final CipherSuite TLS_ECDH_ECDSA_WITH_NULL_SHA
+            = new CipherSuite("TLS_ECDH_ECDSA_WITH_NULL_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_ECDSA,
+                              "EC",
+                              null,
+                              "SHA",
+                              CODE_TLS_ECDH_ECDSA_WITH_NULL_SHA);
+    static final CipherSuite TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+            = new CipherSuite("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_ECDSA,
+                              "EC",
+                              "RC4_128",
+                              "SHA",
+                              CODE_TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
+    static final CipherSuite TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+            = new CipherSuite("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_ECDSA,
+                              "EC",
+                              "3DES_EDE_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA);
+    static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+            = new CipherSuite("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_ECDSA,
+                              "EC",
+                              "AES_128_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
+    static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+            = new CipherSuite("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_ECDSA,
+                              "EC",
+                              "AES_256_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA);
+    static final CipherSuite TLS_ECDHE_ECDSA_WITH_NULL_SHA
+            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_ECDSA,
+                              "EC",
+                              null,
+                              "SHA",
+                              CODE_TLS_ECDHE_ECDSA_WITH_NULL_SHA);
+    static final CipherSuite TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_ECDSA,
+                              "EC",
+                              "RC4_128",
+                              "SHA",
+                              CODE_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA);
+    static final CipherSuite TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_ECDSA,
+                              "EC",
+                              "3DES_EDE_CBC",
+                              "SHA",
+                              CODE_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA);
+    static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_ECDSA,
+                              "EC",
+                              "AES_128_CBC",
+                              "SHA",
+                              CODE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
+    static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_ECDSA,
+                              "EC",
+                              "AES_256_CBC",
+                              "SHA",
+                              CODE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
+    static final CipherSuite TLS_ECDH_RSA_WITH_NULL_SHA
+            = new CipherSuite("TLS_ECDH_RSA_WITH_NULL_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_RSA,
+                              "EC",
+                              null,
+                              "SHA",
+                              CODE_TLS_ECDH_RSA_WITH_NULL_SHA);
+    static final CipherSuite TLS_ECDH_RSA_WITH_RC4_128_SHA
+            = new CipherSuite("TLS_ECDH_RSA_WITH_RC4_128_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_RSA,
+                              "EC",
+                              "RC4_128",
+                              "SHA",
+                              CODE_TLS_ECDH_RSA_WITH_RC4_128_SHA);
+    static final CipherSuite TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+            = new CipherSuite("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_RSA,
+                              "EC",
+                              "3DES_EDE_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA);
+    static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+            = new CipherSuite("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_RSA,
+                              "EC",
+                              "AES_128_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
+    static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+            = new CipherSuite("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_RSA,
+                              "EC",
+                              "AES_256_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
+    static final CipherSuite TLS_ECDHE_RSA_WITH_NULL_SHA
+            = new CipherSuite("TLS_ECDHE_RSA_WITH_NULL_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_RSA,
+                              "EC",
+                              null,
+                              "SHA",
+                              CODE_TLS_ECDHE_RSA_WITH_NULL_SHA);
+    static final CipherSuite TLS_ECDHE_RSA_WITH_RC4_128_SHA
+            = new CipherSuite("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_RSA,
+                              "EC",
+                              "RC4_128",
+                              "SHA",
+                              CODE_TLS_ECDHE_RSA_WITH_RC4_128_SHA);
+    static final CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+            = new CipherSuite("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_RSA,
+                              "EC",
+                              "3DES_EDE_CBC",
+                              "SHA",
+                              CODE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA);
+    static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+            = new CipherSuite("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_RSA,
+                              "EC",
+                              "AES_128_CBC",
+                              "SHA",
+                              CODE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
+    static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+            = new CipherSuite("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDHE_RSA,
+                              "EC",
+                              "AES_256_CBC",
+                              "SHA",
+                              CODE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
+    static final CipherSuite TLS_ECDH_anon_WITH_NULL_SHA
+            = new CipherSuite("TLS_ECDH_anon_WITH_NULL_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_anon,
+                              "EC",
+                              null,
+                              "SHA",
+                              CODE_TLS_ECDH_anon_WITH_NULL_SHA);
+    static final CipherSuite TLS_ECDH_anon_WITH_RC4_128_SHA
+            = new CipherSuite("TLS_ECDH_anon_WITH_RC4_128_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_anon,
+                              "EC",
+                              "RC4_128",
+                              "SHA",
+                              CODE_TLS_ECDH_anon_WITH_RC4_128_SHA);
+    static final CipherSuite TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
+            = new CipherSuite("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_anon,
+                              "EC",
+                              "3DES_EDE_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA);
+    static final CipherSuite TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+            = new CipherSuite("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_anon,
+                              "EC",
+                              "AES_128_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
+    static final CipherSuite TLS_ECDH_anon_WITH_AES_256_CBC_SHA
+            = new CipherSuite("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
+                              false,
+                              KEY_EXCHANGE_ECDH_anon,
+                              "EC",
+                              "AES_256_CBC",
+                              "SHA",
+                              CODE_TLS_ECDH_anon_WITH_AES_256_CBC_SHA);
+
+    // arrays for quick access to cipher suite by code
+    private static final CipherSuite[] SUITES_BY_CODE_0x00 = {
         // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
-        SSL_NULL_WITH_NULL_NULL,                        // { 0x00, 0x00 };
-        SSL_RSA_WITH_NULL_MD5,                          // { 0x00, 0x01 };
-        SSL_RSA_WITH_NULL_SHA,                          // { 0x00, 0x02 };
-        SSL_RSA_EXPORT_WITH_RC4_40_MD5,                 // { 0x00, 0x03 };
-        SSL_RSA_WITH_RC4_128_MD5,                       // { 0x00, 0x04 };
-        SSL_RSA_WITH_RC4_128_SHA,                       // { 0x00, 0x05 };
+        SSL_NULL_WITH_NULL_NULL,                          // { 0x00, 0x00 };
+        SSL_RSA_WITH_NULL_MD5,                            // { 0x00, 0x01 };
+        SSL_RSA_WITH_NULL_SHA,                            // { 0x00, 0x02 };
+        SSL_RSA_EXPORT_WITH_RC4_40_MD5,                   // { 0x00, 0x03 };
+        SSL_RSA_WITH_RC4_128_MD5,                         // { 0x00, 0x04 };
+        SSL_RSA_WITH_RC4_128_SHA,                         // { 0x00, 0x05 };
         // BEGIN android-changed
-        null, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,    // { 0x00, 0x06 };
-        null, // TLS_RSA_WITH_IDEA_CBC_SHA,             // { 0x00, 0x07 };
+        null, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,      // { 0x00, 0x06 };
+        null, // TLS_RSA_WITH_IDEA_CBC_SHA,               // { 0x00, 0x07 };
         // END android-changed
-        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,              // { 0x00, 0x08 };
-        SSL_RSA_WITH_DES_CBC_SHA,                       // { 0x00, 0x09 };
-        SSL_RSA_WITH_3DES_EDE_CBC_SHA,                  // { 0x00, 0x0a };
+        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,                // { 0x00, 0x08 };
+        SSL_RSA_WITH_DES_CBC_SHA,                         // { 0x00, 0x09 };
+        SSL_RSA_WITH_3DES_EDE_CBC_SHA,                    // { 0x00, 0x0a };
         // BEGIN android-changed
-        null, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA   // { 0x00, 0x0b };
-        null, // SSL_DH_DSS_WITH_DES_CBC_SHA,           // { 0x00, 0x0c };
-        null, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,      // { 0x00, 0x0d };
-        null, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,  // { 0x00, 0x0e };
-        null, // SSL_DH_RSA_WITH_DES_CBC_SHA,           // { 0x00, 0x0f };
-        null, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,      // { 0x00, 0x10 };
+        null, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA     // { 0x00, 0x0b };
+        null, // SSL_DH_DSS_WITH_DES_CBC_SHA,             // { 0x00, 0x0c };
+        null, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,        // { 0x00, 0x0d };
+        null, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,    // { 0x00, 0x0e };
+        null, // SSL_DH_RSA_WITH_DES_CBC_SHA,             // { 0x00, 0x0f };
+        null, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,        // { 0x00, 0x10 };
         // END android-changed
-        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,          // { 0x00, 0x11 };
-        SSL_DHE_DSS_WITH_DES_CBC_SHA,                   // { 0x00, 0x12 };
-        SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,              // { 0x00, 0x13 };
-        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,          // { 0x00, 0x14 };
-        SSL_DHE_RSA_WITH_DES_CBC_SHA,                   // { 0x00, 0x15 };
-        SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,              // { 0x00, 0x16 };
-        SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,             // { 0x00, 0x17 };
-        SSL_DH_anon_WITH_RC4_128_MD5,                   // { 0x00, 0x18 };
-        SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,          // { 0x00, 0x19 };
-        SSL_DH_anon_WITH_DES_CBC_SHA,                   // { 0x00, 0x1A };
-        SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,              // { 0x00, 0x1B };
+        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,            // { 0x00, 0x11 };
+        SSL_DHE_DSS_WITH_DES_CBC_SHA,                     // { 0x00, 0x12 };
+        SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,                // { 0x00, 0x13 };
+        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,            // { 0x00, 0x14 };
+        SSL_DHE_RSA_WITH_DES_CBC_SHA,                     // { 0x00, 0x15 };
+        SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,                // { 0x00, 0x16 };
+        SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,               // { 0x00, 0x17 };
+        SSL_DH_anon_WITH_RC4_128_MD5,                     // { 0x00, 0x18 };
+        SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,            // { 0x00, 0x19 };
+        SSL_DH_anon_WITH_DES_CBC_SHA,                     // { 0x00, 0x1A };
+        SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,                // { 0x00, 0x1B };
         // BEGIN android-added
-        null, // SSL_FORTEZZA_KEA_WITH_NULL_SHA         // { 0x00, 0x1C };
-        null, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA // { 0x00, 0x1D };
-        null, // TLS_KRB5_WITH_DES_CBC_SHA              // { 0x00, 0x1E };
-        null, // TLS_KRB5_WITH_3DES_EDE_CBC_SHA         // { 0x00, 0x1F };
-        null, // TLS_KRB5_WITH_RC4_128_SHA              // { 0x00, 0x20 };
-        null, // TLS_KRB5_WITH_IDEA_CBC_SHA             // { 0x00, 0x21 };
-        null, // TLS_KRB5_WITH_DES_CBC_MD5              // { 0x00, 0x22 };
-        null, // TLS_KRB5_WITH_3DES_EDE_CBC_MD5         // { 0x00, 0x23 };
-        null, // TLS_KRB5_WITH_RC4_128_MD5              // { 0x00, 0x24 };
-        null, // TLS_KRB5_WITH_IDEA_CBC_MD5             // { 0x00, 0x25 };
-        null, // TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA    // { 0x00, 0x26 };
-        null, // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA    // { 0x00, 0x27 };
-        null, // TLS_KRB5_EXPORT_WITH_RC4_40_SHA        // { 0x00, 0x28 };
-        null, // TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5    // { 0x00, 0x29 };
-        null, // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5    // { 0x00, 0x2A };
-        null, // TLS_KRB5_EXPORT_WITH_RC4_40_MD5        // { 0x00, 0x2B };
-        null, // TLS_PSK_WITH_NULL_SHA                  // { 0x00, 0x2C };
-        null, // TLS_DHE_PSK_WITH_NULL_SHA              // { 0x00, 0x2D };
-        null, // TLS_RSA_PSK_WITH_NULL_SHA              // { 0x00, 0x2E };
-        TLS_RSA_WITH_AES_128_CBC_SHA,                   // { 0x00, 0x2F };
-        null, // TLS_DH_DSS_WITH_AES_128_CBC_SHA        // { 0x00, 0x30 };
-        null, // TLS_DH_RSA_WITH_AES_128_CBC_SHA        // { 0x00, 0x31 };
-        TLS_DHE_DSS_WITH_AES_128_CBC_SHA,               // { 0x00, 0x32 };
-        TLS_DHE_RSA_WITH_AES_128_CBC_SHA,               // { 0x00, 0x33 };
-        TLS_DH_anon_WITH_AES_128_CBC_SHA,               // { 0x00, 0x34 };
-        TLS_RSA_WITH_AES_256_CBC_SHA,                   // { 0x00, 0x35 };
-        null, // TLS_DH_DSS_WITH_AES_256_CBC_SHA,       // { 0x00, 0x36 };
-        null, // TLS_DH_RSA_WITH_AES_256_CBC_SHA,       // { 0x00, 0x37 };
-        TLS_DHE_DSS_WITH_AES_256_CBC_SHA,               // { 0x00, 0x38 };
-        TLS_DHE_RSA_WITH_AES_256_CBC_SHA,               // { 0x00, 0x39 };
-        TLS_DH_anon_WITH_AES_256_CBC_SHA,               // { 0x00, 0x3A };
+        null, // SSL_FORTEZZA_KEA_WITH_NULL_SHA           // { 0x00, 0x1C };
+        null, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA   // { 0x00, 0x1D };
+        null, // TLS_KRB5_WITH_DES_CBC_SHA                // { 0x00, 0x1E };
+        null, // TLS_KRB5_WITH_3DES_EDE_CBC_SHA           // { 0x00, 0x1F };
+        null, // TLS_KRB5_WITH_RC4_128_SHA                // { 0x00, 0x20 };
+        null, // TLS_KRB5_WITH_IDEA_CBC_SHA               // { 0x00, 0x21 };
+        null, // TLS_KRB5_WITH_DES_CBC_MD5                // { 0x00, 0x22 };
+        null, // TLS_KRB5_WITH_3DES_EDE_CBC_MD5           // { 0x00, 0x23 };
+        null, // TLS_KRB5_WITH_RC4_128_MD5                // { 0x00, 0x24 };
+        null, // TLS_KRB5_WITH_IDEA_CBC_MD5               // { 0x00, 0x25 };
+        null, // TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA      // { 0x00, 0x26 };
+        null, // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA      // { 0x00, 0x27 };
+        null, // TLS_KRB5_EXPORT_WITH_RC4_40_SHA          // { 0x00, 0x28 };
+        null, // TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5      // { 0x00, 0x29 };
+        null, // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5      // { 0x00, 0x2A };
+        null, // TLS_KRB5_EXPORT_WITH_RC4_40_MD5          // { 0x00, 0x2B };
+        null, // TLS_PSK_WITH_NULL_SHA                    // { 0x00, 0x2C };
+        null, // TLS_DHE_PSK_WITH_NULL_SHA                // { 0x00, 0x2D };
+        null, // TLS_RSA_PSK_WITH_NULL_SHA                // { 0x00, 0x2E };
+        TLS_RSA_WITH_AES_128_CBC_SHA,                     // { 0x00, 0x2F };
+        null, // TLS_DH_DSS_WITH_AES_128_CBC_SHA          // { 0x00, 0x30 };
+        null, // TLS_DH_RSA_WITH_AES_128_CBC_SHA          // { 0x00, 0x31 };
+        TLS_DHE_DSS_WITH_AES_128_CBC_SHA,                 // { 0x00, 0x32 };
+        TLS_DHE_RSA_WITH_AES_128_CBC_SHA,                 // { 0x00, 0x33 };
+        TLS_DH_anon_WITH_AES_128_CBC_SHA,                 // { 0x00, 0x34 };
+        TLS_RSA_WITH_AES_256_CBC_SHA,                     // { 0x00, 0x35 };
+        null, // TLS_DH_DSS_WITH_AES_256_CBC_SHA,         // { 0x00, 0x36 };
+        null, // TLS_DH_RSA_WITH_AES_256_CBC_SHA,         // { 0x00, 0x37 };
+        TLS_DHE_DSS_WITH_AES_256_CBC_SHA,                 // { 0x00, 0x38 };
+        TLS_DHE_RSA_WITH_AES_256_CBC_SHA,                 // { 0x00, 0x39 };
+        TLS_DH_anon_WITH_AES_256_CBC_SHA,                 // { 0x00, 0x3A };
         // END android-added
     };
+    private static final CipherSuite[] SUITES_BY_CODE_0xc0 = {
+        null,                                             // { 0xc0, 0x00};
+        TLS_ECDH_ECDSA_WITH_NULL_SHA,                     // { 0xc0, 0x01};
+        TLS_ECDH_ECDSA_WITH_RC4_128_SHA,                  // { 0xc0, 0x02};
+        TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,             // { 0xc0, 0x03};
+        TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,              // { 0xc0, 0x04};
+        TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,              // { 0xc0, 0x05};
+        TLS_ECDHE_ECDSA_WITH_NULL_SHA,                    // { 0xc0, 0x06};
+        TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,                 // { 0xc0, 0x07};
+        TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,            // { 0xc0, 0x08};
+        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,             // { 0xc0, 0x09};
+        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,             // { 0xc0, 0x0A};
+        TLS_ECDH_RSA_WITH_NULL_SHA,                       // { 0xc0, 0x0B};
+        TLS_ECDH_RSA_WITH_RC4_128_SHA,                    // { 0xc0, 0x0C};
+        TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,               // { 0xc0, 0x0D};
+        TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,                // { 0xc0, 0x0E};
+        TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,                // { 0xc0, 0x0F};
+        TLS_ECDHE_RSA_WITH_NULL_SHA,                      // { 0xc0, 0x10};
+        TLS_ECDHE_RSA_WITH_RC4_128_SHA,                   // { 0xc0, 0x11};
+        TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,              // { 0xc0, 0x12};
+        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,               // { 0xc0, 0x13};
+        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,               // { 0xc0, 0x14};
+        TLS_ECDH_anon_WITH_NULL_SHA,                      // { 0xc0, 0x15};
+        TLS_ECDH_anon_WITH_RC4_128_SHA,                   // { 0xc0, 0x16};
+        TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,              // { 0xc0, 0x17};
+        TLS_ECDH_anon_WITH_AES_128_CBC_SHA,               // { 0xc0, 0x18};
+        TLS_ECDH_anon_WITH_AES_256_CBC_SHA,               // { 0xc0, 0x19};
+        // TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,             // { 0xc0, 0x1A};
+        // TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,         // { 0xc0, 0x1B};
+        // TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,         // { 0xc0, 0x1C};
+        // TLS_SRP_SHA_WITH_AES_128_CBC_SHA,              // { 0xc0, 0x1D};
+        // TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,          // { 0xc0, 0x1E};
+        // TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,          // { 0xc0, 0x1F};
+        // TLS_SRP_SHA_WITH_AES_256_CBC_SHA,              // { 0xc0, 0x20};
+        // TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,          // { 0xc0, 0x21};
+        // TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,          // { 0xc0, 0x22};
+        // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,       // { 0xc0, 0x23};
+        // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,       // { 0xc0, 0x24};
+        // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,        // { 0xc0, 0x25};
+        // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,        // { 0xc0, 0x26};
+        // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,         // { 0xc0, 0x27};
+        // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,         // { 0xc0, 0x28};
+        // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,          // { 0xc0, 0x29};
+        // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,          // { 0xc0, 0x2A};
+        // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,       // { 0xc0, 0x2B};
+        // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,       // { 0xc0, 0x2C};
+        // TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,        // { 0xc0, 0x2D};
+        // TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,        // { 0xc0, 0x2E};
+        // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,         // { 0xc0, 0x2F};
+        // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,         // { 0xc0, 0x30};
+        // TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,          // { 0xc0, 0x31};
+        // TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,          // { 0xc0, 0x32};
+        // TLS_ECDHE_PSK_WITH_RC4_128_SHA,                // { 0xc0, 0x33};
+        // TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,           // { 0xc0, 0x34};
+        // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,            // { 0xc0, 0x35};
+        // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,            // { 0xc0, 0x36};
+        // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,         // { 0xc0, 0x37};
+        // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,         // { 0xc0, 0x38};
+        // TLS_ECDHE_PSK_WITH_NULL_SHA,                   // { 0xc0, 0x39};
+        // TLS_ECDHE_PSK_WITH_NULL_SHA256,                // { 0xc0, 0x3A};
+        // TLS_ECDHE_PSK_WITH_NULL_SHA384,                // { 0xc0, 0x3B};
+    };
 
     // hash for quick access to cipher suite by name
     private static final Hashtable<String, CipherSuite> SUITES_BY_NAME;
@@ -422,36 +721,14 @@
     static final CipherSuite[] DEFAULT_CIPHER_SUITES;
 
     static {
-        int count = 0;
         SUITES_BY_NAME = new Hashtable<String, CipherSuite>();
-        for (int i = 0; i < SUITES_BY_CODE.length; i++) {
-            if (SUITES_BY_CODE[i] == SSL_NULL_WITH_NULL_NULL) {
-                continue;
-            }
-            if (SUITES_BY_CODE[i] == null) {
-                continue;
-            }
-            SUITES_BY_NAME.put(SUITES_BY_CODE[i].getName(), SUITES_BY_CODE[i]);
-            if (SUITES_BY_CODE[i].supported) {
-                count++;
-            }
-        }
+        int count_0x00 = registerCipherSuitesByCode(SUITES_BY_CODE_0x00);
+        int count_0xc0 = registerCipherSuitesByCode(SUITES_BY_CODE_0xc0);
+        int count = count_0x00 + count_0xc0;
         SUPPORTED_CIPHER_SUITES = new CipherSuite[count];
         SUPPORTED_CIPHER_SUITE_NAMES = new String[count];
-        count = 0;
-        for (int i = 0; i < SUITES_BY_CODE.length; i++) {
-            if (SUITES_BY_CODE[i] == SSL_NULL_WITH_NULL_NULL) {
-                continue;
-            }
-            if (SUITES_BY_CODE[i] == null) {
-                continue;
-            }
-            if (SUITES_BY_CODE[i].supported) {
-                SUPPORTED_CIPHER_SUITES[count] = SUITES_BY_CODE[i];
-                SUPPORTED_CIPHER_SUITE_NAMES[count] = SUPPORTED_CIPHER_SUITES[count].getName();
-                count++;
-            }
-        }
+        registerSupportedCipherSuites(0, SUITES_BY_CODE_0x00);
+        registerSupportedCipherSuites(count_0x00, SUITES_BY_CODE_0xc0);
 
         CipherSuite[] defaultCipherSuites = {
                 SSL_RSA_WITH_RC4_128_MD5,
@@ -484,6 +761,38 @@
             }
         }
     }
+    private static int registerCipherSuitesByCode(CipherSuite[] cipherSuites) {
+        int count = 0;
+        for (int i = 0; i < cipherSuites.length; i++) {
+            if (cipherSuites[i] == SSL_NULL_WITH_NULL_NULL) {
+                continue;
+            }
+            if (cipherSuites[i] == null) {
+                continue;
+            }
+            SUITES_BY_NAME.put(cipherSuites[i].getName(), cipherSuites[i]);
+            if (cipherSuites[i].supported) {
+                count++;
+            }
+        }
+        return count;
+    }
+    private static void registerSupportedCipherSuites(int offset, CipherSuite[] cipherSuites) {
+        int count = offset;
+        for (int i = 0; i < cipherSuites.length; i++) {
+            if (cipherSuites[i] == SSL_NULL_WITH_NULL_NULL) {
+                continue;
+            }
+            if (cipherSuites[i] == null) {
+                continue;
+            }
+            if (cipherSuites[i].supported) {
+                SUPPORTED_CIPHER_SUITES[count] = cipherSuites[i];
+                SUPPORTED_CIPHER_SUITE_NAMES[count] = SUPPORTED_CIPHER_SUITES[count].getName();
+                count++;
+            }
+        }
+    }
 
     /**
      * Returns CipherSuite by name
@@ -497,12 +806,14 @@
      * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., A.5. The CipherSuite</a>
      */
     public static CipherSuite getByCode(byte b1, byte b2) {
-        if (b1 != 0 || (b2 & 0xFF) > SUITES_BY_CODE.length) {
-            // Unknown
-            return new CipherSuite("UNKNOWN_" + b1 + "_" + b2, false, 0, null,
-                    null, null, new byte[] { b1, b2 });
+        int i1 = b1 & 0xff;
+        int i2 = b2 & 0xff;
+        CipherSuite cs = getCipherSuiteByCode(0, i1, i2);
+        if (cs != null) {
+            return cs;
         }
-        return SUITES_BY_CODE[b2];
+        return new CipherSuite("UNKNOWN_" + i1 + "_" + i2, false, 0, null,
+                               null, null, new byte[] { b1, b2 });
     }
 
     /**
@@ -510,15 +821,30 @@
      * as described in TLS 1.0 spec., E. Backward Compatibility With SSL
      */
     public static CipherSuite getByCode(byte b1, byte b2, byte b3) {
-        if (b1 == 0 && b2 == 0) {
-            if ((b3 & 0xFF) <= SUITES_BY_CODE.length) {
-                return SUITES_BY_CODE[b3];
-            }
+        int i1 = b1 & 0xff;
+        int i2 = b2 & 0xff;
+        int i3 = b3 & 0xff;
+        CipherSuite cs = getCipherSuiteByCode(i1, i2, i3);
+        if (cs != null) {
+            return cs;
         }
-        // as TLSv1 equivalent of V2CipherSpec should be included in
-        // V2ClientHello, ignore V2CipherSpec
-        return new CipherSuite("UNKNOWN_" + b1 + "_" + b2 + "_" + b3, false, 0,
-                null, null, null, new byte[] { b1, b2, b3 });
+        return new CipherSuite("UNKNOWN_" + i1 + "_" + i2 + "_" + i3, false, 0,
+                               null, null, null, new byte[] { b1, b2, b3 });
+    }
+
+    private static CipherSuite getCipherSuiteByCode(int i1, int i2, int i3) {
+        CipherSuite[] cipherSuites;
+        if (i1 == 0x00 && i2 == 0x00) {
+            cipherSuites = SUITES_BY_CODE_0x00;
+        } else if (i1 == 0x00 && i2 == 0xc0) {
+            cipherSuites = SUITES_BY_CODE_0xc0;
+        } else {
+            return null;
+        }
+        if (i3 >= cipherSuites.length) {
+            return null;
+        }
+        return cipherSuites[i3];
     }
 
     /**
@@ -588,14 +914,14 @@
             effectiveKeyBytes = 24;
             ivSize = 8;
             blockSize = 8;
-        } else if ("AES_128".equals(cipherName)) {
+        } else if ("AES_128_CBC".equals(cipherName)) {
             this.cipherName = "AES/CBC/NoPadding";
             keyMaterial = 16;
             expandedKeyMaterial = 16;
             effectiveKeyBytes = 16;
             ivSize = 16;
             blockSize = 16;
-        } else if ("AES_256".equals(cipherName)) {
+        } else if ("AES_256_CBC".equals(cipherName)) {
             this.cipherName = "AES/CBC/NoPadding";
             keyMaterial = 32;
             expandedKeyMaterial = 32;
@@ -635,6 +961,12 @@
             }
         }
 
+        // We define the Elliptic Curve cipher suites for use with
+        // code shared by OpenSSL, but they are not supported by
+        // SSLEngine or SSLSocket's built with SSLEngine.
+        if (this.name.startsWith("TLS_EC")) {
+            supported = false;
+        }
     }
 
     /**
@@ -643,7 +975,8 @@
      */
     public boolean isAnonymous() {
         if (keyExchange == KEY_EXCHANGE_DH_anon
-                || keyExchange == KEY_EXCHANGE_DH_anon_EXPORT) {
+                || keyExchange == KEY_EXCHANGE_DH_anon_EXPORT
+                || keyExchange == KEY_EXCHANGE_ECDH_anon) {
             return true;
         }
         return false;
@@ -737,30 +1070,126 @@
         return isExportable;
     }
 
+    static final String KEY_TYPE_RSA = "RSA";
+    static final String KEY_TYPE_DSA = "DSA";
+    static final String KEY_TYPE_DH_RSA = "DH_RSA";
+    static final String KEY_TYPE_DH_DSA = "DH_DSA";
+    static final String KEY_TYPE_EC = "EC";
+    static final String KEY_TYPE_EC_EC = "EC_EC";
+    static final String KEY_TYPE_EC_RSA = "EC_RSA";
+
     /**
-     * Returns key type constant suitable for calling X509KeyManager
-     * and X509ExtendedKeyManager "choose" methods.
+     * Returns key type constant suitable for calling
+     * X509KeyManager.chooseServerAlias or
+     * X509ExtendedKeyManager.chooseEngineServerAlias.
      */
-    public String getKeyType() {
+    public String getServerKeyType() {
         switch (keyExchange) {
             case KEY_EXCHANGE_DHE_RSA:
             case KEY_EXCHANGE_DHE_RSA_EXPORT:
-            case KEY_EXCHANGE_DH_RSA:
-            case KEY_EXCHANGE_DH_RSA_EXPORT:
+            case KEY_EXCHANGE_ECDHE_RSA:
             case KEY_EXCHANGE_RSA:
             case KEY_EXCHANGE_RSA_EXPORT:
-                return NativeCrypto.KEY_TYPE_RSA;
+                return KEY_TYPE_RSA;
             case KEY_EXCHANGE_DHE_DSS:
             case KEY_EXCHANGE_DHE_DSS_EXPORT:
-            case KEY_EXCHANGE_DH_DSS:
-            case KEY_EXCHANGE_DH_DSS_EXPORT:
-                return NativeCrypto.KEY_TYPE_DSA;
+                return KEY_TYPE_DSA;
+            case KEY_EXCHANGE_ECDH_ECDSA:
+            case KEY_EXCHANGE_ECDHE_ECDSA:
+                return KEY_TYPE_EC_EC;
+            case KEY_EXCHANGE_ECDH_RSA:
+                return KEY_TYPE_EC_RSA;
             case KEY_EXCHANGE_DH_anon:
             case KEY_EXCHANGE_DH_anon_EXPORT:
+            case KEY_EXCHANGE_ECDH_anon:
                 return null;
             default:
                 throw new IllegalStateException("Unknown key type for key exchange " + keyExchange);
         }
     }
-}
 
+    /**
+     * Client certificate types as defined in
+     * TLS 1.0 spec., 7.4.4. Certificate request.
+     * EC constants from RFC 4492.
+     * Names match openssl constants.
+     */
+    static final byte TLS_CT_RSA_SIGN = 1;
+    static final byte TLS_CT_DSS_SIGN = 2;
+    static final byte TLS_CT_RSA_FIXED_DH = 3;
+    static final byte TLS_CT_DSS_FIXED_DH = 4;
+    static final byte TLS_CT_ECDSA_SIGN = 64;
+    static final byte TLS_CT_RSA_FIXED_ECDH = 65;
+    static final byte TLS_CT_ECDSA_FIXED_ECDH = 66;
+
+    /**
+     * Similar to getServerKeyType, but returns value given TLS
+     * ClientCertificateType byte values from a CertificateRequest
+     * message for use with X509KeyManager.chooseClientAlias or
+     * X509ExtendedKeyManager.chooseEngineClientAlias.
+     */
+    public static String getClientKeyType(byte keyType) {
+        // See also http://www.ietf.org/assignments/tls-parameters/tls-parameters.xml
+        switch (keyType) {
+            case TLS_CT_RSA_SIGN:
+                return KEY_TYPE_RSA; // RFC rsa_sign
+            case TLS_CT_DSS_SIGN:
+                return KEY_TYPE_DSA; // RFC dss_sign
+            case TLS_CT_RSA_FIXED_DH:
+                return KEY_TYPE_DH_RSA; // RFC rsa_fixed_dh
+            case TLS_CT_DSS_FIXED_DH:
+                return KEY_TYPE_DH_DSA; // RFC dss_fixed_dh
+            case TLS_CT_ECDSA_SIGN:
+                return KEY_TYPE_EC; // RFC ecdsa_sign
+            case TLS_CT_RSA_FIXED_ECDH:
+                return KEY_TYPE_EC_RSA; // RFC rsa_fixed_ecdh
+            case TLS_CT_ECDSA_FIXED_ECDH:
+                return KEY_TYPE_EC_EC; // RFC ecdsa_fixed_ecdh
+            default:
+                return null;
+        }
+    }
+
+    private static final String AUTH_TYPE_RSA = "RSA";
+    private static final String AUTH_TYPE_RSA_EXPORT = "RSA_EXPORT";
+    private static final String AUTH_TYPE_DHE_DSS = "DHE_DSS";
+    private static final String AUTH_TYPE_DHE_RSA = "DHE_RSA";
+    private static final String AUTH_TYPE_DH_DSS = "DH_DSS";
+    private static final String AUTH_TYPE_DH_RSA = "DH_RSA";
+    private static final String AUTH_TYPE_ECDH_ECDSA = "ECDH_ECDSA";
+    private static final String AUTH_TYPE_ECDH_RSA = "ECDH_RSA";
+    private static final String AUTH_TYPE_ECDHE_ECDSA = "ECDHE_ECDSA";
+    private static final String AUTH_TYPE_ECDHE_RSA = "ECDHE_RSA";
+
+    /**
+     * Returns auth type constant suitable for calling X509TrustManager.checkServerTrusted.
+     */
+    public String getAuthType(boolean emphemeral) {
+        switch (keyExchange) {
+            case KEY_EXCHANGE_RSA:
+                return AUTH_TYPE_RSA;
+            case KEY_EXCHANGE_RSA_EXPORT:
+                return emphemeral ? AUTH_TYPE_RSA_EXPORT : AUTH_TYPE_RSA;
+            case KEY_EXCHANGE_DHE_DSS:
+            case KEY_EXCHANGE_DHE_DSS_EXPORT:
+                return AUTH_TYPE_DHE_DSS;
+            case KEY_EXCHANGE_DHE_RSA:
+            case KEY_EXCHANGE_DHE_RSA_EXPORT:
+                return AUTH_TYPE_DHE_RSA;
+            case KEY_EXCHANGE_ECDH_ECDSA:
+                return AUTH_TYPE_ECDH_ECDSA;
+            case KEY_EXCHANGE_ECDHE_ECDSA:
+                return AUTH_TYPE_ECDHE_ECDSA;
+            case KEY_EXCHANGE_ECDH_RSA:
+                return AUTH_TYPE_ECDH_RSA;
+            case KEY_EXCHANGE_ECDHE_RSA:
+                return AUTH_TYPE_ECDHE_RSA;
+            case KEY_EXCHANGE_DH_anon:
+            case KEY_EXCHANGE_DH_anon_EXPORT:
+            case KEY_EXCHANGE_ECDH_anon:
+                return null;
+            default:
+                throw new IllegalStateException("Unknown auth type for key exchange " + keyExchange);
+        }
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
index 11300f7..a09914e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
@@ -93,8 +93,7 @@
                 session.setPeer(socketOwner.getInetAddress().getHostName(), socketOwner.getPort());
             }
             // END android-added
-            session.protocol = ProtocolVersion.getLatestVersion(parameters
-                    .getEnabledProtocols());
+            session.protocol = ProtocolVersion.getLatestVersion(parameters.getEnabledProtocols());
             recordProtocol.setVersion(session.protocol.version);
         } else {
             fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created ");
@@ -117,8 +116,7 @@
                 session.setPeer(socketOwner.getInetAddress().getHostName(), socketOwner.getPort());
             }
             // END android-added
-            session.protocol = ProtocolVersion.getLatestVersion(parameters
-                    .getEnabledProtocols());
+            session.protocol = ProtocolVersion.getLatestVersion(parameters.getEnabledProtocols());
             recordProtocol.setVersion(session.protocol.version);
             startSession();
         } else {
@@ -198,24 +196,22 @@
                     serverHello = new ServerHello(io_stream, length);
 
                     //check protocol version
-                    ProtocolVersion servProt = ProtocolVersion
-                            .getByVersion(serverHello.server_version);
+                    ProtocolVersion servProt = ProtocolVersion.getByVersion(serverHello.server_version);
                     String[] enabled = parameters.getEnabledProtocols();
                     find: {
                         for (int i = 0; i < enabled.length; i++) {
-                            if (servProt.equals(ProtocolVersion
-                                    .getByName(enabled[i]))) {
+                            if (servProt.equals(ProtocolVersion.getByName(enabled[i]))) {
                                 break find;
                             }
                         }
                         fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                "Bad server hello protocol version");
+                                   "Bad server hello protocol version");
                     }
 
                     // check compression method
                     if (serverHello.compression_method != 0) {
                         fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                "Bad server hello compression method");
+                                   "Bad server hello compression method");
                     }
 
                     //check cipher_suite
@@ -224,13 +220,12 @@
                     // END android-changed
                     find: {
                         for (int i = 0; i < enabledSuites.length; i++) {
-                            if (serverHello.cipher_suite
-                                    .equals(enabledSuites[i])) {
+                            if (serverHello.cipher_suite.equals(enabledSuites[i])) {
                                 break find;
                             }
                         }
                         fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                "Bad server hello cipher suite");
+                                   "Bad server hello cipher suite");
                     }
 
                     if (isResuming) {
@@ -242,11 +237,10 @@
                             isResuming = false;
                         } else if (!session.protocol.equals(servProt)) {
                             fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                    "Bad server hello protocol version");
-                        } else if (!session.cipherSuite
-                                .equals(serverHello.cipher_suite)) {
+                                       "Bad server hello protocol version");
+                        } else if (!session.cipherSuite.equals(serverHello.cipher_suite)) {
                             fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                    "Bad server hello cipher suite");
+                                       "Bad server hello cipher suite");
                         }
                         if (serverHello.server_version[1] == 1) {
                             computerReferenceVerifyDataTLS("server finished");
@@ -283,12 +277,10 @@
                         unexpectedMessage();
                         return;
                     }
-                    certificateRequest = new CertificateRequest(io_stream,
-                            length);
+                    certificateRequest = new CertificateRequest(io_stream, length);
                     break;
                 case 14: // SERVER_HELLO_DONE
-                    if (serverHello == null || serverHelloDone != null
-                            || isResuming) {
+                    if (serverHello == null || serverHelloDone != null || isResuming) {
                         unexpectedMessage();
                         return;
                     }
@@ -458,29 +450,12 @@
                 return;
             }
         } else {
-            PublicKey serverPublic;
-            KeyAgreement agreement = null;
-            DHParameterSpec spec;
             try {
-                KeyFactory kf = null;
-                try {
-                    kf = KeyFactory.getInstance("DH");
-                } catch (NoSuchAlgorithmException e) {
-                    kf = KeyFactory.getInstance("DiffieHellman");
-                }
-
-                try {
-                    agreement = KeyAgreement.getInstance("DH");
-                } catch (NoSuchAlgorithmException ee) {
-                    agreement = KeyAgreement.getInstance("DiffieHellman");
-                }
-
-                KeyPairGenerator kpg = null;
-                try {
-                    kpg = KeyPairGenerator.getInstance("DH");
-                } catch (NoSuchAlgorithmException e) {
-                    kpg = KeyPairGenerator.getInstance("DiffieHellman");
-                }
+                KeyFactory kf = KeyFactory.getInstance("DH");
+                KeyAgreement agreement = KeyAgreement.getInstance("DH");
+                KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
+                PublicKey serverPublic;
+                DHParameterSpec spec;
                 if (serverKeyExchange != null) {
                     serverPublic = kf.generatePublic(new DHPublicKeySpec(
                             serverKeyExchange.par3, serverKeyExchange.par1,
@@ -560,42 +535,12 @@
      * Verifies certificate path
      */
     private void verifyServerCert() {
-        String authType = null;
-        switch (session.cipherSuite.keyExchange) {
-        case 1: // KeyExchange_RSA
-            authType = "RSA";
-            break;
-        case 2: // KeyExchange_RSA_EXPORT
-            if (serverKeyExchange != null ) {
-                // ephemeral RSA key is used
-                authType = "RSA_EXPORT";
-            } else {
-                authType = "RSA";
-            }
-            break;
-        case 3: // KeyExchange_DHE_DSS
-        case 4: // KeyExchange_DHE_DSS_EXPORT
-            authType = "DHE_DSS";
-            break;
-        case 5: // KeyExchange_DHE_RSA
-        case 6: // KeyExchange_DHE_RSA_EXPORT
-            authType = "DHE_RSA";
-            break;
-        case 7: // KeyExchange_DH_DSS
-        case 11: // KeyExchange_DH_DSS_EXPORT
-            authType = "DH_DSS";
-            break;
-        case 8: // KeyExchange_DH_RSA
-        case 12: // KeyExchange_DH_RSA_EXPORT
-            authType = "DH_RSA";
-            break;
-        case 9: // KeyExchange_DH_anon
-        case 10: // KeyExchange_DH_anon_EXPORT
+        String authType = session.cipherSuite.getAuthType(serverKeyExchange != null);
+        if (authType == null) {
             return;
         }
         try {
-            parameters.getTrustManager().checkServerTrusted(serverCert.certs,
-                    authType);
+            parameters.getTrustManager().checkServerTrusted(serverCert.certs, authType);
         } catch (CertificateException e) {
             fatalAlert(AlertProtocol.BAD_CERTIFICATE, "Not trusted server certificate", e);
             return;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
index 8fabe29..bd83989 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
@@ -96,7 +96,7 @@
     protected SSLSessionImpl session;
 
     /**
-     * Sended and received handshake messages
+     * Sent and received handshake messages
      */
     protected ClientHello clientHello;
     protected ServerHello serverHello;
@@ -479,8 +479,7 @@
     }
 
     /**
-     *
-     * Clears previously sended and received handshake messages
+     * Clears previously sent and received handshake messages
      */
     protected void clearMessages() {
         io_stream.clearBuffer();
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
index 5ba78c0..f354c67 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
@@ -173,7 +173,7 @@
                 }
                 // key algorithm does not match
                 if (!certKeyAlg.equals(keyAlgorithm)) {
-                    continue ;
+                    continue;
                 }
                 /*
                  * TODO find a more reliable test for signature
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 c3088ec..f39d6ad 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
@@ -161,32 +161,31 @@
 
     static {
         // Note these are added in priority order
-        // Android doesn't currently support Elliptic Curve
         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_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("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");
@@ -198,22 +197,22 @@
         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("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("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");
+        add("TLS_ECDH_anon_WITH_NULL_SHA",           "AECDH-NULL-SHA");
 
         // No Kerberos in Android
         // add("TLS_KRB5_WITH_RC4_128_SHA",           "KRB5-RC4-SHA");
@@ -246,6 +245,9 @@
         // add(null, "PSK-AES128-CBC-SHA");
         // add(null, "PSK-AES256-CBC-SHA");
         // add(null, "PSK-RC4-SHA");
+
+        // Signaling Cipher Suite Value for secure renegotiation
+        // add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",     null);
     }
 
     private static final String[] SUPPORTED_CIPHER_SUITES;
@@ -270,9 +272,28 @@
             "SSL_RSA_WITH_RC4_128_MD5",
             "SSL_RSA_WITH_RC4_128_SHA",
             "TLS_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+            "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+            "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+            "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
             "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
             "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+            "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
             "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+            "TLS_ECDHE_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",
@@ -281,7 +302,8 @@
             "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"
+            "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+            // "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
         };
     }
 
@@ -293,36 +315,6 @@
 
     public static native int SSL_new(int ssl_ctx) throws SSLException;
 
-    public static final String KEY_TYPE_RSA = "RSA";
-    public static final String KEY_TYPE_DSA = "DSA";
-    public static final String KEY_TYPE_DH_RSA = "DH_RSA";
-    public static final String KEY_TYPE_DH_DSA = "DH_DSA";
-    public static final String KEY_TYPE_EC = "EC";
-    public static final String KEY_TYPE_EC_EC = "EC_EC";
-    public static final String KEY_TYPE_EC_RSA = "EC_RSA";
-
-    public static String keyType(int keyType) {
-        // See also http://www.ietf.org/assignments/tls-parameters/tls-parameters.xml
-        switch (keyType) {
-            case 1: // openssl TLS_CT_RSA_SIGN
-                return KEY_TYPE_RSA; // RFC rsa_sign
-            case 2: // openssl TLS_CT_DSS_SIGN
-                return KEY_TYPE_DSA; // RFC dss_sign
-            case 3: // openssl TLS_CT_RSA_FIXED_DH
-                return KEY_TYPE_DH_RSA; // RFC rsa_fixed_dh
-            case 4: // openssl TLS_CT_DSS_FIXED_DH
-                return KEY_TYPE_DH_DSA; // RFC dss_fixed_dh
-            case 64: // openssl TLS_CT_ECDSA_SIGN
-                return KEY_TYPE_EC; // RFC ecdsa_sign
-            case 65: // openssl TLS_CT_RSA_FIXED_ECDH
-                return KEY_TYPE_EC_RSA; // RFC rsa_fixed_ecdh
-            case 66: // openssl TLS_CT_ECDSA_FIXED_ECDH
-                return KEY_TYPE_EC_EC; // RFC ecdsa_fixed_ecdh
-            default:
-                return null;
-        }
-    }
-
     public static byte[][] encodeCertificates(Certificate[] certificates)
             throws CertificateEncodingException {
         byte[][] certificateBytes = new byte[certificates.length][];
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
index b2bdafb..0c3f9c7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
@@ -208,28 +208,28 @@
          * an anonymous cipher is picked.
          */
         for (String enabledCipherSuite : enabledCipherSuites) {
-            String keyType = CipherSuite.getByName(enabledCipherSuite).getKeyType();
+            String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType();
             if (keyType == null) {
                 // anonymous always work
                 return;
             }
-            if (keyType.equals(NativeCrypto.KEY_TYPE_RSA)
-                    || keyType.equals(NativeCrypto.KEY_TYPE_DH_RSA)) {
+            if (keyType.equals(CipherSuite.KEY_TYPE_RSA)
+                    || keyType.equals(CipherSuite.KEY_TYPE_DH_RSA)) {
                 if (checkForPrivateKey(keyType, RSAPrivateKey.class)) {
                     return;
                 }
                 continue;
             }
-            if (keyType.equals(NativeCrypto.KEY_TYPE_DSA)
-                    || keyType.equals(NativeCrypto.KEY_TYPE_DH_DSA)) {
+            if (keyType.equals(CipherSuite.KEY_TYPE_DSA)
+                    || keyType.equals(CipherSuite.KEY_TYPE_DH_DSA)) {
                 if (checkForPrivateKey(keyType, DSAPrivateKey.class)) {
                     return;
                 }
                 continue;
             }
-            if (keyType.equals(NativeCrypto.KEY_TYPE_EC)
-                    || keyType.equals(NativeCrypto.KEY_TYPE_EC_RSA)
-                    || keyType.equals(NativeCrypto.KEY_TYPE_EC_EC)) {
+            if (keyType.equals(CipherSuite.KEY_TYPE_EC)
+                    || keyType.equals(CipherSuite.KEY_TYPE_EC_RSA)
+                    || keyType.equals(CipherSuite.KEY_TYPE_EC_EC)) {
                 if (checkForPrivateKey(keyType, ECPrivateKey.class)) {
                     return;
                 }
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 715394c..deefd60 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
@@ -374,7 +374,7 @@
             if (!client) {
                 Set<String> keyTypes = new HashSet<String>();
                 for (String enabledCipherSuite : enabledCipherSuites) {
-                    String keyType = CipherSuite.getByName(enabledCipherSuite).getKeyType();
+                    String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType();
                     if (keyType != null) {
                         keyTypes.add(keyType);
                     }
@@ -585,7 +585,7 @@
 
         String[] keyTypes = new String[keyTypeBytes.length];
         for (int i = 0; i < keyTypeBytes.length; i++) {
-            keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]);
+            keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]);
         }
 
         X500Principal[] issuers;
@@ -675,8 +675,9 @@
                 sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain,
                                                                    authMethod);
             } else {
+                String authType = peerCertificateChain[0].getPublicKey().getAlgorithm();
                 sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain,
-                                                                   authMethod);
+                                                                   authType);
             }
 
         } catch (CertificateException e) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
index 181b92c..f9df058 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
@@ -140,7 +140,7 @@
                     if (clientCert.certs.length == 0) {
                         if (parameters.getNeedClientAuth()) {
                             fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                    "HANDSHAKE FAILURE: no client certificate received");
+                                       "HANDSHAKE FAILURE: no client certificate received");
                         }
                     } else {
                         String authType = clientCert.getAuthType();
@@ -149,7 +149,7 @@
                                     clientCert.certs, authType);
                         } catch (CertificateException e) {
                             fatalAlert(AlertProtocol.BAD_CERTIFICATE,
-                                    "Untrusted Client Certificate ", e);
+                                       "Untrusted Client Certificate ", e);
                         }
                         session.peerCertificates = clientCert.certs;
                     }
@@ -187,15 +187,14 @@
                     ds.setSHA(sha_hash);
                     if (!ds.verifySignature(certificateVerify.signedHash)) {
                         fatalAlert(AlertProtocol.DECRYPT_ERROR,
-                                "DECRYPT ERROR: CERTIFICATE_VERIFY incorrect signature");
+                                   "DECRYPT ERROR: CERTIFICATE_VERIFY incorrect signature");
                     }
                     break;
                 case 16: // CLIENT_KEY_EXCHANGE
                     if (isResuming
                             || serverHelloDone == null
                             || clientKeyExchange != null
-                            || (clientCert == null && parameters
-                                    .getNeedClientAuth())) {
+                            || (clientCert == null && parameters.getNeedClientAuth())) {
                         unexpectedMessage();
                         return;
                     }
@@ -208,8 +207,7 @@
                         try {
                             c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                             c.init(Cipher.DECRYPT_MODE, privKey);
-                            preMasterSecret = c
-                                    .doFinal(clientKeyExchange.exchange_keys);
+                            preMasterSecret = c.doFinal(clientKeyExchange.exchange_keys);
                             // check preMasterSecret:
                             if (preMasterSecret.length != 48
                                     || preMasterSecret[0] != clientHello.client_version[0]
@@ -222,7 +220,7 @@
                             }
                         } catch (Exception e) {
                             fatalAlert(AlertProtocol.INTERNAL_ERROR,
-                                    "INTERNAL ERROR", e);
+                                       "INTERNAL ERROR", e);
                         }
                     } else { // diffie hellman key exchange
                         clientKeyExchange = new ClientKeyExchange(io_stream,
@@ -233,26 +231,12 @@
                             // matched server cert. DH params
 
                             // client cert. contains fixed DH parameters
-                            preMasterSecret = ((DHPublicKey) clientCert.certs[0]
-                                    .getPublicKey()).getY().toByteArray();
+                            preMasterSecret = ((DHPublicKey) clientCert.certs[0].getPublicKey()).getY().toByteArray();
                         } else {
-                            PublicKey clientPublic;
-                            KeyAgreement agreement;
                             try {
-                                KeyFactory kf = null;
-                                try {
-                                    kf = KeyFactory.getInstance("DH");
-                                } catch (NoSuchAlgorithmException ee) {
-                                    kf = KeyFactory
-                                            .getInstance("DiffieHellman");
-                                }
-                                try {
-                                    agreement = KeyAgreement.getInstance("DH");
-                                } catch (NoSuchAlgorithmException ee) {
-                                    agreement = KeyAgreement.getInstance("DiffieHellman");
-                                }
-                                clientPublic = kf
-                                        .generatePublic(new DHPublicKeySpec(
+                                KeyFactory kf = KeyFactory.getInstance("DH");
+                                KeyAgreement agreement = KeyAgreement.getInstance("DH");
+                                PublicKey clientPublic = kf.generatePublic(new DHPublicKeySpec(
                                                 new BigInteger(
                                                         1,
                                                         clientKeyExchange.exchange_keys),
@@ -263,7 +247,7 @@
                                 preMasterSecret = agreement.generateSecret();
                             } catch (Exception e) {
                                 fatalAlert(AlertProtocol.INTERNAL_ERROR,
-                                        "INTERNAL ERROR", e);
+                                           "INTERNAL ERROR", e);
                                 return;
                             }
                         }
@@ -348,14 +332,14 @@
                 }
             }
             fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                    "HANDSHAKE FAILURE. Incorrect client hello message");
+                       "HANDSHAKE FAILURE. Incorrect client hello message");
         }
 
         if (!ProtocolVersion.isSupported(clientHello.client_version)) {
             fatalAlert(AlertProtocol.PROTOCOL_VERSION,
-                    "PROTOCOL VERSION. Unsupported client version "
-                    + clientHello.client_version[0]
-                    + clientHello.client_version[1]);
+                       "PROTOCOL VERSION. Unsupported client version "
+                       + clientHello.client_version[0]
+                       + clientHello.client_version[1]);
         }
 
         isResuming = false;
@@ -406,7 +390,7 @@
                     }
                 }
                 fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                        "HANDSHAKE FAILURE. Incorrect client hello message");
+                           "HANDSHAKE FAILURE. Incorrect client hello message");
             }
         } else {
             cipher_suite = selectSuite(clientHello.cipher_suites);
@@ -415,7 +399,7 @@
             }
             if (!parameters.getEnableSessionCreation()) {
                 fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                        "SSL Session may not be created");
+                           "SSL Session may not be created");
             }
             session = new SSLSessionImpl(cipher_suite, parameters.getSecureRandom());
             // BEGIN android-added
@@ -445,27 +429,9 @@
         //    create and send server certificate message if needed
         if (!cipher_suite.isAnonymous()) { // need to send server certificate
             X509Certificate[] certs = null;
-            String certType = null;
-            switch (cipher_suite.keyExchange) {
-                case CipherSuite.KEY_EXCHANGE_RSA:
-                case CipherSuite.KEY_EXCHANGE_RSA_EXPORT:
-                case CipherSuite.KEY_EXCHANGE_DHE_RSA:
-                case CipherSuite.KEY_EXCHANGE_DHE_RSA_EXPORT:
-                    certType = "RSA";
-                    break;
-                case CipherSuite.KEY_EXCHANGE_DHE_DSS:
-                case CipherSuite.KEY_EXCHANGE_DHE_DSS_EXPORT:
-                case CipherSuite.KEY_EXCHANGE_DH_DSS_EXPORT:
-                    certType = "DSA";
-                    break;
-                case CipherSuite.KEY_EXCHANGE_DH_DSS:
-                    certType = "DH_DSA";
-                    break;
-                case CipherSuite.KEY_EXCHANGE_DH_RSA:
-                    certType = "DH_RSA";
-                    break;
-                default:
-                    fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO CERT TYPE FOR " + cipher_suite.getName());
+            String certType = cipher_suite.getServerKeyType();
+            if (certType == null) {
+                fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO CERT TYPE FOR " + cipher_suite.getName());
             }
             // obtain certificates from key manager
             String alias = null;
@@ -522,11 +488,7 @@
                     || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA_EXPORT
                     || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DH_anon
                     || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DH_anon_EXPORT) {
-                try {
-                    kpg = KeyPairGenerator.getInstance("DH");
-                } catch (NoSuchAlgorithmException ee) {
-                    kpg = KeyPairGenerator.getInstance("DiffieHellman");
-                }
+                kpg = KeyPairGenerator.getInstance("DH");
                 p = new BigInteger(1, DHParameters.getPrime());
                 g = new BigInteger("2");
                 DHParameterSpec spec = new DHParameterSpec(p, g);
@@ -546,14 +508,8 @@
                     rsakey = (RSAPublicKey) kp.getPublic();
                 } else {
                     DHPublicKey dhkey = (DHPublicKey) kp.getPublic();
-                    KeyFactory kf = null;
-                    try {
-                        kf = KeyFactory.getInstance("DH");
-                    } catch (NoSuchAlgorithmException e) {
-                            kf = KeyFactory.getInstance("DiffieHellman");
-                    }
-                    dhkeySpec = kf.getKeySpec(dhkey,
-                            DHPublicKeySpec.class);
+                    KeyFactory kf = KeyFactory.getInstance("DH");
+                    dhkeySpec = kf.getKeySpec(dhkey, DHPublicKeySpec.class);
                 }
                 if (!cipher_suite.isAnonymous()) { // calculate signed_params
 
@@ -626,7 +582,8 @@
                 // don't send certificateRequest
                 break certRequest;
             }
-            byte[] requestedClientCertTypes = {1, 2}; // rsa sign, dsa sign
+            byte[] requestedClientCertTypes = { CipherSuite.TLS_CT_RSA_SIGN,
+                                                CipherSuite.TLS_CT_DSS_SIGN };
             certificateRequest = new CertificateRequest(
                     requestedClientCertTypes, accepted);
             send(certificateRequest);
@@ -673,15 +630,15 @@
     }
 
     // find appropriate cipher_suite in the client suites
-    private CipherSuite selectSuite(CipherSuite[] client_suites) {
-        for (int i = 0; i < client_suites.length; i++) {
-            if (!client_suites[i].supported) {
+    private CipherSuite selectSuite(CipherSuite[] clientSuites) {
+        for (CipherSuite clientSuite : clientSuites) {
+            if (!clientSuite.supported) {
                 continue;
             }
             // BEGIN android-changed
-            for (int j = 0; j < parameters.getEnabledCipherSuitesMember().length; j++) {
-                if (client_suites[i].equals(parameters.getEnabledCipherSuitesMember()[j])) {
-                    return client_suites[i];
+            for (CipherSuite enabledCipherSuite : parameters.getEnabledCipherSuitesMember()) {
+                if (clientSuite.equals(enabledCipherSuite)) {
+                    return clientSuite;
                 }
             }
             // END android-changed
diff --git a/luni/src/main/native/NativeCrypto.cpp b/luni/src/main/native/NativeCrypto.cpp
index 9e9ece4..0ce14a6 100644
--- a/luni/src/main/native/NativeCrypto.cpp
+++ b/luni/src/main/native/NativeCrypto.cpp
@@ -91,6 +91,13 @@
 };
 typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
 
+struct EC_KEY_Delete {
+    void operator()(EC_KEY* p) const {
+        EC_KEY_free(p);
+    }
+};
+typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
+
 struct EVP_PKEY_Delete {
     void operator()(EVP_PKEY* p) const {
         EVP_PKEY_free(p);
@@ -1198,11 +1205,14 @@
  * 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:
+ * Finally, we have two emphemeral keys setup by OpenSSL callbacks:
  *
  * (8) a set of ephemeral RSA keys that is lazily generated if a peer
  * wants to use an exportable RSA cipher suite.
  *
+ * (9) a set of ephemeral EC keys that is lazily generated if a peer
+ * wants to use an TLS_ECDHE_* cipher suite.
+ *
  */
 class AppData {
   public:
@@ -1214,6 +1224,7 @@
     jobject sslHandshakeCallbacks;
     jobject fileDescriptor;
     Unique_RSA ephemeralRsa;
+    Unique_EC_KEY ephemeralEc;
 
     /**
      * Creates the application data context for the SSL*.
@@ -1247,7 +1258,8 @@
             waitingThreads(0),
             env(NULL),
             sslHandshakeCallbacks(NULL),
-            ephemeralRsa(NULL) {
+            ephemeralRsa(NULL),
+            ephemeralEc(NULL) {
         fdsEmergency[0] = -1;
         fdsEmergency[1] = -1;
     }
@@ -1651,6 +1663,31 @@
     return tmp_dh;
 }
 
+static EC_KEY* ecGenerateKey(int keylength __attribute__ ((unused))) {
+    // TODO selected curve based on keylength
+    Unique_EC_KEY ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (ec.get() == NULL) {
+        return NULL;
+    }
+    return ec.release();
+}
+
+/**
+ * Call back to ask for an ephemeral EC key for TLS_ECDHE_* cipher suites
+ */
+static EC_KEY* tmp_ecdh_callback(SSL* ssl __attribute__ ((unused)),
+                                 int is_export __attribute__ ((unused)),
+                                 int keylength) {
+    JNI_TRACE("ssl=%p tmp_ecdh_callback is_export=%d keylength=%d", ssl, is_export, keylength);
+    AppData* appData = toAppData(ssl);
+    if (appData->ephemeralEc.get() == NULL) {
+        JNI_TRACE("ssl=%p tmp_ecdh_callback generating ephemeral EC key", ssl);
+        appData->ephemeralEc.reset(ecGenerateKey(keylength));
+    }
+    JNI_TRACE("ssl=%p tmp_ecdh_callback => %p", ssl, appData->ephemeralEc.get());
+    return appData->ephemeralEc.get();
+}
+
 /*
  * public static native int SSL_CTX_new();
  */
@@ -1669,7 +1706,9 @@
                         // We also disable compression for better compatibility b/2710492 b/2710497
                         | SSL_OP_NO_COMPRESSION
                         // Because dhGenerateParameters uses DSA_generate_parameters_ex
-                        | SSL_OP_SINGLE_DH_USE);
+                        | SSL_OP_SINGLE_DH_USE
+                        // Because ecGenerateParameters uses a fixed named curve
+                        | SSL_OP_SINGLE_ECDH_USE);
 
     int mode = SSL_CTX_get_mode(sslCtx.get());
     /*
@@ -1697,6 +1736,7 @@
     SSL_CTX_set_client_cert_cb(sslCtx.get(), client_cert_cb);
     SSL_CTX_set_tmp_rsa_callback(sslCtx.get(), tmp_rsa_callback);
     SSL_CTX_set_tmp_dh_callback(sslCtx.get(), tmp_dh_callback);
+    SSL_CTX_set_tmp_ecdh_callback(sslCtx.get(), tmp_ecdh_callback);
 
     JNI_TRACE("NativeCrypto_SSL_CTX_new => %p", sslCtx.get());
     return (jint) sslCtx.release();
@@ -1783,6 +1823,8 @@
         return;
     }
 
+    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey EVP_PKEY_type=%d",
+              ssl, EVP_PKEY_type(privatekeyevp.get()->type));
     int ret = SSL_use_PrivateKey(ssl, privatekeyevp.get());
     if (ret == 1) {
         privatekeyevp.release();
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
index 6b77c69..4a16fe8 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
@@ -61,7 +61,7 @@
         TestSSLContext c = TestSSLContext.create();
         SSLEngine e = c.clientContext.createSSLEngine();
         String[] cipherSuites = e.getSupportedCipherSuites();
-        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE, cipherSuites);
         assertNotSame(cipherSuites, e.getSupportedCipherSuites());
         c.close();
     }
@@ -105,12 +105,6 @@
                 if (cipherSuite.startsWith("TLS_KRB5_")) {
                     continue;
                 }
-                /*
-                 * Elliptic Curve cipher suites are not supported on Android
-                 */
-                if (!StandardNames.IS_RI && cipherSuite.startsWith("TLS_EC")) {
-                    continue;
-                }
 
                 final String[] cipherSuiteArray
                         = (secureRenegotiation
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
index 1165fd6..14a54fd 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
@@ -38,7 +38,7 @@
     public void test_SSLSocketFactory_getDefaultCipherSuites() {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         String[] cipherSuites = sf.getDefaultCipherSuites();
-        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        StandardNames.assertDefaultCipherSuites(cipherSuites);
         assertNotSame(cipherSuites, sf.getDefaultCipherSuites());
     }
 
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 84468c9..00b2c85 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -25,6 +25,8 @@
 import java.security.Principal;
 import java.security.cert.Certificate;
 import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
 import javax.net.ssl.HandshakeCompletedEvent;
 import javax.net.ssl.HandshakeCompletedListener;
 import javax.net.ssl.SSLContext;
@@ -102,7 +104,19 @@
 
         TestSSLContext c = TestSSLContext.create(testKeyStore, testKeyStore,
                                                  clientProvider, serverProvider);
-        String[] cipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
+        String[] cipherSuites;
+        if (clientProvider.equals(serverProvider)) {
+            cipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
+        } else {
+            String[] clientCipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
+            String[] serverCipherSuites = c.serverContext.getSocketFactory().getSupportedCipherSuites();
+            Set<String> ccs = new HashSet<String>(Arrays.asList(clientCipherSuites));
+            Set<String> scs = new HashSet<String>(Arrays.asList(serverCipherSuites));
+            Set<String> cs = new HashSet<String>(ccs);
+            cs.retainAll(scs);
+            cipherSuites = cs.toArray(new String[cs.size()]);
+        }
+
         for (String cipherSuite : cipherSuites) {
             try {
                 /*
@@ -121,12 +135,6 @@
                 if (cipherSuite.startsWith("TLS_KRB5_")) {
                     continue;
                 }
-                /*
-                 * Elliptic Curve cipher suites are not supported on Android
-                 */
-                if (!StandardNames.IS_RI && cipherSuite.startsWith("TLS_EC")) {
-                    continue;
-                }
 
                 String[] cipherSuiteArray
                         = (secureRenegotiation
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
index 5b007f7..50f1cd0 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
+++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
@@ -61,9 +61,9 @@
         byte[] bytes = cs.toBytes();
         assertNotNull(name, bytes);
         assertEquals(name, 2, bytes.length);
-        assertEquals(name, 0, bytes[0]);
-        assertSame(name, cs, CipherSuite.getByCode((byte) 0, bytes[1]));
-        assertSame(name, cs, CipherSuite.getByCode((byte) 0, (byte) 0, bytes[1]));
+        assertTrue(name + bytes[0], bytes[0] == (byte) 0x00 || bytes[0] == (byte) 0xc0);
+        assertSame(name, cs, CipherSuite.getByCode(bytes[0], bytes[1]));
+        assertSame(name, cs, CipherSuite.getByCode((byte) 0, bytes[0], bytes[1]));
 
         assertTrue(name, cs.toString().contains(name));
 
@@ -92,7 +92,7 @@
                    cs.isExportable() == name.contains("_EXPORT_")
                    || cs.isExportable() == name.contains("_NULL_"));
 
-        String keyType = cs.getKeyType();
+        String keyType = cs.getServerKeyType();
         assertEquals(name, cs.isAnonymous(), keyType == null);
         assertTrue(name, keyType == null || StandardNames.KEY_TYPES.contains(keyType));
     }
@@ -121,9 +121,43 @@
 
     public void test_getSupportedCipherSuiteNames() throws Exception {
         String[] names = CipherSuite.getSupportedCipherSuiteNames();
-        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES, names);
+        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE, names);
         for (String name : names) {
             test_CipherSuite(name);
         }
     }
+
+    public void test_getClientKeyType() throws Exception {
+        byte b = Byte.MIN_VALUE;
+        do {
+            String byteString = Byte.toString(b);
+            String keyType = CipherSuite.getClientKeyType(b);
+            switch (b) {
+                case 1:
+                    assertEquals(byteString, "RSA", keyType);
+                    break;
+                case 2:
+                    assertEquals(byteString, "DSA", keyType);
+                    break;
+                case 3:
+                    assertEquals(byteString, "DH_RSA", keyType);
+                    break;
+                case 4:
+                    assertEquals(byteString, "DH_DSA", keyType);
+                    break;
+                case 64:
+                    assertEquals(byteString, "EC", keyType);
+                    break;
+                case 65:
+                    assertEquals(byteString, "EC_RSA", keyType);
+                    break;
+                case 66:
+                    assertEquals(byteString, "EC_EC", keyType);
+                    break;
+                default:
+                    assertNull(byteString, keyType);
+            }
+            b++;
+        } while (b != Byte.MIN_VALUE);
+    }
 }
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
index f533ba6..b40c6c8 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
+++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
@@ -42,6 +42,7 @@
 import javax.net.ssl.SSLProtocolException;
 import javax.security.auth.x500.X500Principal;
 import junit.framework.TestCase;
+import org.apache.harmony.xnet.provider.jsse.CipherSuite;
 import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks;
 
 public class NativeCryptoTest extends TestCase {
@@ -691,9 +692,9 @@
         // this depends on the SSL_set_cipher_lists call in beforeHandshake
         // the three returned are the non-ephemeral cases.
         assertEquals(3, clientCallback.keyTypes.length);
-        assertEquals("RSA", NativeCrypto.keyType(clientCallback.keyTypes[0]));
-        assertEquals("DSA", NativeCrypto.keyType(clientCallback.keyTypes[1]));
-        assertEquals("EC", NativeCrypto.keyType(clientCallback.keyTypes[2]));
+        assertEquals("RSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[0]));
+        assertEquals("DSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[1]));
+        assertEquals("EC", CipherSuite.getClientKeyType(clientCallback.keyTypes[2]));
         assertEqualPrincipals(CA_PRINCIPALS,
                               clientCallback.asn1DerEncodedX500Principals);
         assertFalse(serverCallback.clientCertificateRequestedCalled);
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index e27bb1b..bf33cd7 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -18,10 +18,13 @@
 
 import java.security.Security;
 import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import junit.framework.Assert;
@@ -463,8 +466,21 @@
         }
     }
 
-    public static final Set<String> CLIENT_AUTH_TYPES = new HashSet<String>(KEY_TYPES);
+    /**
+     * Valid values for X509TrustManager.checkClientTrusted authType,
+     * either the algorithm of the public key or UNKNOWN.
+     */
+    public static final Set<String> CLIENT_AUTH_TYPES = new HashSet<String>(Arrays.asList(
+        "RSA",
+        "DSA",
+        "EC",
+        "UNKNOWN"));
 
+    /**
+     * Valid values for X509TrustManager.checkServerTrusted authType,
+     * either key exchange algorithm part of the cipher suite
+     * or UNKNOWN.
+     */
     public static final Set<String> SERVER_AUTH_TYPES = new HashSet<String>(Arrays.asList(
         "DHE_DSS",
         "DHE_DSS_EXPORT",
@@ -479,6 +495,10 @@
         "RSA",
         "RSA_EXPORT",
         "RSA_EXPORT1024",
+        "ECDH_ECDSA",
+        "ECDH_RSA",
+        "ECDHE_ECDSA",
+        "ECDHE_RSA",
         "UNKNOWN"));
 
     public static final String CIPHER_SUITE_INVALID = "SSL_NULL_WITH_NULL_NULL";
@@ -509,32 +529,31 @@
 
     static {
         // Note these are added in priority order as defined by RI 6 documentation.
-        // Android currently does not support Elliptic Curve
         addBoth(   "SSL_RSA_WITH_RC4_128_MD5");
         addBoth(   "SSL_RSA_WITH_RC4_128_SHA");
         addBoth(   "TLS_RSA_WITH_AES_128_CBC_SHA");
         addBoth(   "TLS_RSA_WITH_AES_256_CBC_SHA");
-        addRi(     "TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
-        addRi(     "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
-        addRi(     "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
-        addRi(     "TLS_ECDH_RSA_WITH_RC4_128_SHA");
-        addRi(     "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
-        addRi(     "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
-        addRi(     "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
-        addRi(     "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
-        addRi(     "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
-        addRi(     "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
-        addRi(     "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
-        addRi(     "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
+        addBoth(   "TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
+        addBoth(   "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
+        addBoth(   "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+        addBoth(   "TLS_ECDH_RSA_WITH_RC4_128_SHA");
+        addBoth(   "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
+        addBoth(   "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
+        addBoth(   "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
+        addBoth(   "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
+        addBoth(   "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
+        addBoth(   "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
+        addBoth(   "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
+        addBoth(   "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
         addBoth(   "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
         addBoth(   "TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
         addBoth(   "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
         addBoth(   "TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
         addBoth(   "SSL_RSA_WITH_3DES_EDE_CBC_SHA");
-        addRi(     "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
-        addRi(     "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
-        addRi(     "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
-        addRi(     "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "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");
@@ -546,22 +565,22 @@
         addBoth(   "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
         addBoth(   "SSL_RSA_WITH_NULL_MD5");
         addBoth(   "SSL_RSA_WITH_NULL_SHA");
-        addRi(     "TLS_ECDH_ECDSA_WITH_NULL_SHA");
-        addRi(     "TLS_ECDH_RSA_WITH_NULL_SHA");
-        addRi(     "TLS_ECDHE_ECDSA_WITH_NULL_SHA");
-        addRi(     "TLS_ECDHE_RSA_WITH_NULL_SHA");
+        addBoth(   "TLS_ECDH_ECDSA_WITH_NULL_SHA");
+        addBoth(   "TLS_ECDH_RSA_WITH_NULL_SHA");
+        addBoth(   "TLS_ECDHE_ECDSA_WITH_NULL_SHA");
+        addBoth(   "TLS_ECDHE_RSA_WITH_NULL_SHA");
         addBoth(   "SSL_DH_anon_WITH_RC4_128_MD5");
         addBoth(   "TLS_DH_anon_WITH_AES_128_CBC_SHA");
         addBoth(   "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");
-        addRi(     "TLS_ECDH_anon_WITH_RC4_128_SHA");
-        addRi(     "TLS_ECDH_anon_WITH_AES_128_CBC_SHA");
-        addRi(     "TLS_ECDH_anon_WITH_AES_256_CBC_SHA");
-        addRi(     "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA");
+        addBoth(   "TLS_ECDH_anon_WITH_RC4_128_SHA");
+        addBoth(   "TLS_ECDH_anon_WITH_AES_128_CBC_SHA");
+        addBoth(   "TLS_ECDH_anon_WITH_AES_256_CBC_SHA");
+        addBoth(   "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");
-        addRi(     "TLS_ECDH_anon_WITH_NULL_SHA");
+        addBoth(   "TLS_ECDH_anon_WITH_NULL_SHA");
 
         // RFC 5746's Signaling Cipher Suite Value to indicate a request for secure renegotiation
         addRi(CIPHER_SUITE_SECURE_RENEGOTIATION);
@@ -594,6 +613,60 @@
         CIPHER_SUITES = (IS_RI) ? CIPHER_SUITES_RI : CIPHER_SUITES_OPENSSL;
     }
 
+    public static final List<String> CIPHER_SUITES_DEFAULT = Arrays.asList(
+        "SSL_RSA_WITH_RC4_128_MD5",
+        "SSL_RSA_WITH_RC4_128_SHA",
+        "TLS_RSA_WITH_AES_128_CBC_SHA",
+        "TLS_RSA_WITH_AES_256_CBC_SHA",
+        "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+        "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+        "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+        "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+        "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+        "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+        "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+        "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+        "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+        "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+        "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+        "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+        "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+        "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+        "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+        "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+        "TLS_ECDHE_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");
+    static {
+        if (IS_RI) {
+            CIPHER_SUITES_DEFAULT.add(CIPHER_SUITE_SECURE_RENEGOTIATION);
+        }
+    }
+
+    public static final Set<String> CIPHER_SUITES_SSLENGINE = new HashSet<String>(CIPHER_SUITES);
+    static {
+        // No Elliptic Curve support on SSLEngine based provider
+        if (!IS_RI) {
+            Iterator<String> i = CIPHER_SUITES_SSLENGINE.iterator();
+            while (i.hasNext()) {
+                if (i.next().startsWith("TLS_EC")) {
+                    i.remove();
+                }
+            }
+        }
+    }
+
     /**
      * Asserts that the cipher suites array is non-null and that it
      * all of its contents are cipher suites known to this
@@ -625,7 +698,7 @@
      */
     public static void assertSupportedCipherSuites(Set<String> expected, String[] cipherSuites) {
         Set<String> remainingCipherSuites = assertValidCipherSuites(expected, cipherSuites);
-        assertEquals("Extra cipher suites", Collections.EMPTY_SET, remainingCipherSuites);
+        assertEquals("Missing cipher suites", Collections.EMPTY_SET, remainingCipherSuites);
         assertEquals(expected.size(), cipherSuites.length);
     }
 
@@ -659,7 +732,15 @@
      */
     public static void assertSupportedProtocols(Set<String> expected, String[] protocols) {
         Set<String> remainingProtocols = assertValidProtocols(expected, protocols);
-        assertEquals("Extra protocols", Collections.EMPTY_SET, remainingProtocols);
+        assertEquals("Missing protocols", Collections.EMPTY_SET, remainingProtocols);
         assertEquals(expected.size(), protocols.length);
     }
+
+    /**
+     * Assert cipher suites match the default list in content and priority order.
+     */
+    public static void assertDefaultCipherSuites(String[] cipherSuites) {
+        assertValidCipherSuites(CIPHER_SUITES, cipherSuites);
+        assertEquals(CIPHER_SUITES_DEFAULT, Arrays.asList(cipherSuites));
+    }
 }
diff --git a/support/src/test/java/libcore/javax/net/ssl/TestKeyManager.java b/support/src/test/java/libcore/javax/net/ssl/TestKeyManager.java
index 1617b6b..03420fe6 100644
--- a/support/src/test/java/libcore/javax/net/ssl/TestKeyManager.java
+++ b/support/src/test/java/libcore/javax/net/ssl/TestKeyManager.java
@@ -26,6 +26,7 @@
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.X509ExtendedKeyManager;
 import libcore.java.io.NullPrintStream;
+import libcore.java.security.StandardNames;
 
 /**
  * TestKeyManager is a simple proxy class that wraps an existing
@@ -68,9 +69,22 @@
         }
         dumpIssuers(issuers);
         dumpSocket(socket);
+        assertKeyTypes(keyTypes);
         return dumpAlias(keyManager.chooseClientAlias(keyTypes, issuers, socket));
     }
 
+    private void assertKeyTypes(String[] keyTypes) {
+        for (String keyType : keyTypes) {
+            assertKeyType(keyType);
+        }
+    }
+
+    private void assertKeyType(String keyType) {
+        if (!StandardNames.KEY_TYPES.contains(keyType)) {
+            throw new AssertionError("Unexpected key type " + keyType);
+        }
+    }
+
     public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
         out.print("TestKeyManager.chooseServerAlias");
         out.print(" | keyType: ");
@@ -78,6 +92,7 @@
         out.print(' ');
         dumpIssuers(issuers);
         dumpSocket(socket);
+        assertKeyType(keyType);
         return dumpAlias(keyManager.chooseServerAlias(keyType, issuers, socket));
     }
 
@@ -126,6 +141,7 @@
         out.print(" | keyType: ");
         out.print(keyType);
         dumpIssuers(issuers);
+        assertKeyType(keyType);
         return dumpAliases(keyManager.getClientAliases(keyType, issuers));
     }
 
@@ -134,6 +150,7 @@
         out.print(" | keyType: ");
         out.print(keyType);
         dumpIssuers(issuers);
+        assertKeyType(keyType);
         return dumpAliases(keyManager.getServerAliases(keyType, issuers));
     }
 
@@ -166,6 +183,7 @@
         }
         dumpIssuers(issuers);
         dumpEngine(e);
+        assertKeyTypes(keyTypes);
         return dumpAlias(keyManager.chooseEngineClientAlias(keyTypes, issuers, e));
     }
 
@@ -176,6 +194,7 @@
         out.print(' ');
         dumpIssuers(issuers);
         dumpEngine(e);
+        assertKeyType(keyType);
         return dumpAlias(keyManager.chooseEngineServerAlias(keyType, issuers, e));
     }
 
diff --git a/support/src/test/java/libcore/javax/net/ssl/TestSSLSocketPair.java b/support/src/test/java/libcore/javax/net/ssl/TestSSLSocketPair.java
index abbcf8c..55ce3bb 100644
--- a/support/src/test/java/libcore/javax/net/ssl/TestSSLSocketPair.java
+++ b/support/src/test/java/libcore/javax/net/ssl/TestSSLSocketPair.java
@@ -17,9 +17,11 @@
 package libcore.javax.net.ssl;
 
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 import javax.net.ssl.SSLSocket;
 
 /**
@@ -95,8 +97,30 @@
                 });
             executor.shutdown();
 
-            s.get();
-            c.get();
+            // catch client and server exceptions separately so we can
+            // potentially log both.
+            Exception serverException;
+            try {
+                s.get(30, TimeUnit.SECONDS);
+                serverException = null;
+            } catch (Exception e) {
+                serverException = e;
+                e.printStackTrace();
+            }
+            Exception clientException;
+            try {
+                c.get(30, TimeUnit.SECONDS);
+                clientException = null;
+            } catch (Exception e) {
+                clientException = e;
+                e.printStackTrace();
+            }
+            if (serverException != null) {
+                throw serverException;
+            }
+            if (clientException != null) {
+                throw clientException;
+            }
             return new SSLSocket[] { server, client };
         } catch (RuntimeException e) {
             throw e;
diff --git a/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java b/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java
index 38dc1e8..c3511b4 100644
--- a/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java
+++ b/support/src/test/java/libcore/javax/net/ssl/TestTrustManager.java
@@ -22,6 +22,7 @@
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import libcore.java.io.NullPrintStream;
+import libcore.java.security.StandardNames;
 
 /**
  * TestTrustManager is a simple proxy class that wraps an existing
@@ -61,6 +62,7 @@
                   + "chain=" + chain.length + " "
                   + "authType=" + authType + " ");
         try {
+            assertClientAuthType(authType);
             trustManager.checkClientTrusted(chain, authType);
             out.println("OK");
         } catch (CertificateException e) {
@@ -69,12 +71,19 @@
         }
     }
 
+    private void assertClientAuthType(String authType) {
+        if (!StandardNames.CLIENT_AUTH_TYPES.contains(authType)) {
+            throw new AssertionError("Unexpected client auth type " + authType);
+        }
+    }
+
     public void checkServerTrusted(X509Certificate[] chain, String authType)
             throws CertificateException {
         out.print("TestTrustManager.checkServerTrusted "
                   + "chain=" + chain.length + " "
                   + "authType=" + authType + " ");
         try {
+            assertServerAuthType(authType);
             trustManager.checkServerTrusted(chain, authType);
             out.println("OK");
         } catch (CertificateException e) {
@@ -83,6 +92,12 @@
         }
     }
 
+    private void assertServerAuthType(String authType) {
+        if (!StandardNames.SERVER_AUTH_TYPES.contains(authType)) {
+            throw new AssertionError("Unexpected server auth type " + authType);
+        }
+    }
+
     /**
      * Returns the list of certificate issuer authorities which are trusted for
      * authentication of peers.