external/conscrypt: ask OpenSSL for supported cipher suites.

Rather than enumerate the list of supported cipher suites in conscrypt,
ask OpenSSL for the list and just maintain a mapping from OpenSSL's
names to the standard, external name.

(The mapping could also be removed with BoringSSL since it can return
the standard name for an SSL_CIPHER*. But in order to keep OpenSSL
compat this change doesn't depend on that.)

(cherry picked from commit d9a68f656782ee2fa0ca918e00522cdd25d33fdf)

Bug: 20531880
Change-Id: Ib541c9787093e7b900052fdf12dd2a2029b4b020
diff --git a/src/main/java/org/conscrypt/NativeCrypto.java b/src/main/java/org/conscrypt/NativeCrypto.java
index a407931..a70f6f3 100644
--- a/src/main/java/org/conscrypt/NativeCrypto.java
+++ b/src/main/java/org/conscrypt/NativeCrypto.java
@@ -31,9 +31,11 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import javax.crypto.BadPaddingException;
 import javax.crypto.IllegalBlockSizeException;
 import javax.net.ssl.SSLException;
@@ -561,12 +563,23 @@
     private static final String SUPPORTED_PROTOCOL_TLSV1_1 = "TLSv1.1";
     private static final String SUPPORTED_PROTOCOL_TLSV1_2 = "TLSv1.2";
 
+    // STANDARD_TO_OPENSSL_CIPHER_SUITES is a map from OpenSSL-style
+    // cipher-suite names to the standard name for the same (i.e. the name that
+    // is registered with IANA).
     public static final Map<String, String> OPENSSL_TO_STANDARD_CIPHER_SUITES
             = new HashMap<String, String>();
+
+    // STANDARD_TO_OPENSSL_CIPHER_SUITES is a map from "standard" cipher suite
+    // names (i.e. the names that are registered with IANA) to the
+    // OpenSSL-style name for the same.
     public static final Map<String, String> STANDARD_TO_OPENSSL_CIPHER_SUITES
             = new LinkedHashMap<String, String>();
 
-    private static void add(String standard, String openssl) {
+    // SUPPORTED_CIPHER_SUITES_SET contains all the cipher suites supported by
+    // OpenSSL, named using "standard" (as opposed to OpenSSL-style) names.
+    public static final Set<String> SUPPORTED_CIPHER_SUITES_SET = new HashSet<String>();
+
+    private static void add(String openssl, String standard) {
         OPENSSL_TO_STANDARD_CIPHER_SUITES.put(openssl, standard);
         STANDARD_TO_OPENSSL_CIPHER_SUITES.put(standard, openssl);
     }
@@ -602,129 +615,93 @@
     public static final String TLS_FALLBACK_SCSV = "TLS_FALLBACK_SCSV";
 
     static {
-        add("SSL_RSA_WITH_RC4_128_MD5",              "RC4-MD5");
-        add("SSL_RSA_WITH_RC4_128_SHA",              "RC4-SHA");
-        add("TLS_RSA_WITH_AES_128_CBC_SHA",          "AES128-SHA");
-        add("TLS_RSA_WITH_AES_256_CBC_SHA",          "AES256-SHA");
-        add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",       "ECDH-ECDSA-RC4-SHA");
-        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",   "ECDH-ECDSA-AES128-SHA");
-        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",   "ECDH-ECDSA-AES256-SHA");
-        add("TLS_ECDH_RSA_WITH_RC4_128_SHA",         "ECDH-RSA-RC4-SHA");
-        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",     "ECDH-RSA-AES128-SHA");
-        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",     "ECDH-RSA-AES256-SHA");
-        add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",      "ECDHE-ECDSA-RC4-SHA");
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",  "ECDHE-ECDSA-AES128-SHA");
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",  "ECDHE-ECDSA-AES256-SHA");
-        add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",        "ECDHE-RSA-RC4-SHA");
-        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",    "ECDHE-RSA-AES128-SHA");
-        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",    "ECDHE-RSA-AES256-SHA");
-        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",      "DHE-RSA-AES128-SHA");
-        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",      "DHE-RSA-AES256-SHA");
-        add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",         "DES-CBC3-SHA");
-        add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",  "ECDH-ECDSA-DES-CBC3-SHA");
-        add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",    "ECDH-RSA-DES-CBC3-SHA");
-        add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-ECDSA-DES-CBC3-SHA");
-        add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",   "ECDHE-RSA-DES-CBC3-SHA");
-        add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",     "EDH-RSA-DES-CBC3-SHA");
-        add("SSL_RSA_WITH_DES_CBC_SHA",              "DES-CBC-SHA");
-        add("SSL_DHE_RSA_WITH_DES_CBC_SHA",          "EDH-RSA-DES-CBC-SHA");
-        add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",        "EXP-RC4-MD5");
-        add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",     "EXP-DES-CBC-SHA");
-        add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-RSA-DES-CBC-SHA");
-        add("SSL_RSA_WITH_NULL_MD5",                 "NULL-MD5");
-        add("SSL_RSA_WITH_NULL_SHA",                 "NULL-SHA");
-        add("TLS_ECDH_ECDSA_WITH_NULL_SHA",          "ECDH-ECDSA-NULL-SHA");
-        add("TLS_ECDH_RSA_WITH_NULL_SHA",            "ECDH-RSA-NULL-SHA");
-        add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",         "ECDHE-ECDSA-NULL-SHA");
-        add("TLS_ECDHE_RSA_WITH_NULL_SHA",           "ECDHE-RSA-NULL-SHA");
-        add("SSL_DH_anon_WITH_RC4_128_MD5",          "ADH-RC4-MD5");
-        add("TLS_DH_anon_WITH_AES_128_CBC_SHA",      "ADH-AES128-SHA");
-        add("TLS_DH_anon_WITH_AES_256_CBC_SHA",      "ADH-AES256-SHA");
-        add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",     "ADH-DES-CBC3-SHA");
-        add("SSL_DH_anon_WITH_DES_CBC_SHA",          "ADH-DES-CBC-SHA");
-        add("TLS_ECDH_anon_WITH_RC4_128_SHA",        "AECDH-RC4-SHA");
-        add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",    "AECDH-AES128-SHA");
-        add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",    "AECDH-AES256-SHA");
-        add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",   "AECDH-DES-CBC3-SHA");
-        add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",    "EXP-ADH-RC4-MD5");
-        add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "EXP-ADH-DES-CBC-SHA");
-        add("TLS_ECDH_anon_WITH_NULL_SHA",           "AECDH-NULL-SHA");
-
-        // TLSv1.2 cipher suites
-        add("TLS_RSA_WITH_NULL_SHA256",                "NULL-SHA256");
-        add("TLS_RSA_WITH_AES_128_CBC_SHA256",         "AES128-SHA256");
-        add("TLS_RSA_WITH_AES_256_CBC_SHA256",         "AES256-SHA256");
-        add("TLS_RSA_WITH_AES_128_GCM_SHA256",         "AES128-GCM-SHA256");
-        add("TLS_RSA_WITH_AES_256_GCM_SHA384",         "AES256-GCM-SHA384");
-        add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",     "DHE-RSA-AES128-SHA256");
-        add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",     "DHE-RSA-AES256-SHA256");
-        add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",     "DHE-RSA-AES128-GCM-SHA256");
-        add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",     "DHE-RSA-AES256-GCM-SHA384");
-        add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",    "ECDH-RSA-AES128-SHA256");
-        add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",    "ECDH-RSA-AES256-SHA384");
-        add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",    "ECDH-RSA-AES128-GCM-SHA256");
-        add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",    "ECDH-RSA-AES256-GCM-SHA384");
-        add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",  "ECDH-ECDSA-AES128-SHA256");
-        add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",  "ECDH-ECDSA-AES256-SHA384");
-        add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",  "ECDH-ECDSA-AES128-GCM-SHA256");
-        add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",  "ECDH-ECDSA-AES256-GCM-SHA384");
-        add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",   "ECDHE-RSA-AES128-SHA256");
-        add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",   "ECDHE-RSA-AES256-SHA384");
-        add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",   "ECDHE-RSA-AES128-GCM-SHA256");
-        add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",   "ECDHE-RSA-AES256-GCM-SHA384");
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "ECDHE-ECDSA-AES128-SHA256");
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "ECDHE-ECDSA-AES256-SHA384");
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "ECDHE-ECDSA-AES128-GCM-SHA256");
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "ECDHE-ECDSA-AES256-GCM-SHA384");
-        add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",     "ADH-AES128-SHA256");
-        add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",     "ADH-AES256-SHA256");
-        add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",     "ADH-AES128-GCM-SHA256");
-        add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",     "ADH-AES256-GCM-SHA384");
-
-        // No Kerberos in Android
-        // add("TLS_KRB5_WITH_RC4_128_SHA",           "KRB5-RC4-SHA");
-        // add("TLS_KRB5_WITH_RC4_128_MD5",           "KRB5-RC4-MD5");
-        // add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",      "KRB5-DES-CBC3-SHA");
-        // add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",      "KRB5-DES-CBC3-MD5");
-        // add("TLS_KRB5_WITH_DES_CBC_SHA",           "KRB5-DES-CBC-SHA");
-        // add("TLS_KRB5_WITH_DES_CBC_MD5",           "KRB5-DES-CBC-MD5");
-        // add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",     "EXP-KRB5-RC4-SHA");
-        // add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",     "EXP-KRB5-RC4-MD5");
-        // add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", "EXP-KRB5-DES-CBC-SHA");
-        // add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", "EXP-KRB5-DES-CBC-MD5");
-
-        // not implemented by either RI or OpenSSL
-        // add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", null);
-        // add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", null);
-
-        // No DSS support in BoringSSL
-        // add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-DSS-DES-CBC-SHA");
-        // add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",     "EDH-DSS-DES-CBC3-SHA");
-        // add("SSL_DHE_DSS_WITH_DES_CBC_SHA",          "EDH-DSS-DES-CBC-SHA");
-        // add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",      "DHE-DSS-AES128-SHA");
-        // add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",   "DHE-DSS-AES128-SHA256");
-        // add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",   "DHE-DSS-AES128-GCM-SHA256");
-        // add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",      "DHE-DSS-AES256-SHA");
-        // add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",   "DHE-DSS-AES256-SHA256");
-        // add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",   "DHE-DSS-AES256-GCM-SHA384");
-
-        // EXPORT1024 suites were never standardized but were widely implemented.
-        // OpenSSL 0.9.8c and later have disabled TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES
-        // add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", "EXP1024-DES-CBC-SHA");
-        // add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",  "EXP1024-RC4-SHA");
-
-        // No RC2
-        // add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",  "EXP-RC2-CBC-MD5");
-        // add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", "EXP-KRB5-RC2-CBC-SHA");
-        // add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", "EXP-KRB5-RC2-CBC-MD5");
-
-        // Pre-Shared Key (PSK) cipher suites
-        add("TLS_PSK_WITH_3DES_EDE_CBC_SHA", "PSK-3DES-EDE-CBC-SHA");
-        add("TLS_PSK_WITH_AES_128_CBC_SHA", "PSK-AES128-CBC-SHA");
-        add("TLS_PSK_WITH_AES_256_CBC_SHA", "PSK-AES256-CBC-SHA");
-        add("TLS_PSK_WITH_RC4_128_SHA", "PSK-RC4-SHA");
-        add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", "ECDHE-PSK-AES128-CBC-SHA");
-        add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", "ECDHE-PSK-AES256-CBC-SHA");
+        add("ADH-AES128-GCM-SHA256",		"TLS_DH_anon_WITH_AES_128_GCM_SHA256");
+        add("ADH-AES128-SHA",			"TLS_DH_anon_WITH_AES_128_CBC_SHA");
+        add("ADH-AES128-SHA256",		"TLS_DH_anon_WITH_AES_128_CBC_SHA256");
+        add("ADH-AES256-GCM-SHA384",		"TLS_DH_anon_WITH_AES_256_GCM_SHA384");
+        add("ADH-AES256-SHA",			"TLS_DH_anon_WITH_AES_256_CBC_SHA");
+        add("ADH-AES256-SHA256",		"TLS_DH_anon_WITH_AES_256_CBC_SHA256");
+        add("ADH-DES-CBC-SHA",			"SSL_DH_anon_WITH_DES_CBC_SHA");
+        add("ADH-DES-CBC3-SHA",			"SSL_DH_anon_WITH_3DES_EDE_CBC_SHA");
+        add("ADH-RC4-MD5",			"SSL_DH_anon_WITH_RC4_128_MD5");
+        add("AECDH-AES128-SHA",			"TLS_ECDH_anon_WITH_AES_128_CBC_SHA");
+        add("AECDH-AES256-SHA",			"TLS_ECDH_anon_WITH_AES_256_CBC_SHA");
+        add("AECDH-DES-CBC3-SHA",		"TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA");
+        add("AECDH-NULL-SHA",			"TLS_ECDH_anon_WITH_NULL_SHA");
+        add("AECDH-RC4-SHA",			"TLS_ECDH_anon_WITH_RC4_128_SHA");
+        add("AES128-GCM-SHA256",		"TLS_RSA_WITH_AES_128_GCM_SHA256");
+        add("AES128-SHA",			"TLS_RSA_WITH_AES_128_CBC_SHA");
+        add("AES128-SHA256",			"TLS_RSA_WITH_AES_128_CBC_SHA256");
+        add("AES256-GCM-SHA384",		"TLS_RSA_WITH_AES_256_GCM_SHA384");
+        add("AES256-SHA",			"TLS_RSA_WITH_AES_256_CBC_SHA");
+        add("AES256-SHA256",			"TLS_RSA_WITH_AES_256_CBC_SHA256");
+        add("DES-CBC-SHA",			"SSL_RSA_WITH_DES_CBC_SHA");
+        add("DES-CBC3-SHA",			"SSL_RSA_WITH_3DES_EDE_CBC_SHA");
+        add("DHE-RSA-AES128-GCM-SHA256",	"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256");
+        add("DHE-RSA-AES128-SHA",		"TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
+        add("DHE-RSA-AES128-SHA256",		"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256");
+        add("DHE-RSA-AES256-GCM-SHA384",	"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384");
+        add("DHE-RSA-AES256-SHA",		"TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
+        add("DHE-RSA-AES256-SHA256",		"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256");
+        add("DHE-RSA-CHACHA20-POLY1305",	"TLS_DHE_RSA_WITH_CHACHA20_POLY1305");
+        add("ECDH-ECDSA-AES128-GCM-SHA256",    	"TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256");
+        add("ECDH-ECDSA-AES128-SHA",		"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
+        add("ECDH-ECDSA-AES128-SHA256",		"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256");
+        add("ECDH-ECDSA-AES256-GCM-SHA384",    	"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384");
+        add("ECDH-ECDSA-AES256-SHA",		"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
+        add("ECDH-ECDSA-AES256-SHA384",		"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384");
+        add("ECDH-ECDSA-DES-CBC3-SHA",		"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
+        add("ECDH-ECDSA-NULL-SHA",		"TLS_ECDH_ECDSA_WITH_NULL_SHA");
+        add("ECDH-ECDSA-RC4-SHA",		"TLS_ECDH_ECDSA_WITH_RC4_128_SHA");
+        add("ECDH-RSA-AES128-GCM-SHA256",      	"TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256");
+        add("ECDH-RSA-AES128-SHA",		"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
+        add("ECDH-RSA-AES128-SHA256",		"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256");
+        add("ECDH-RSA-AES256-GCM-SHA384",      	"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384");
+        add("ECDH-RSA-AES256-SHA",		"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
+        add("ECDH-RSA-AES256-SHA384",		"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384");
+        add("ECDH-RSA-DES-CBC3-SHA",		"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
+        add("ECDH-RSA-NULL-SHA",		"TLS_ECDH_RSA_WITH_NULL_SHA");
+        add("ECDH-RSA-RC4-SHA",			"TLS_ECDH_RSA_WITH_RC4_128_SHA");
+        add("ECDHE-ECDSA-AES128-GCM-SHA256",   	"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
+        add("ECDHE-ECDSA-AES128-SHA",		"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
+        add("ECDHE-ECDSA-AES128-SHA256",	"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256");
+        add("ECDHE-ECDSA-AES256-GCM-SHA384",   	"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
+        add("ECDHE-ECDSA-AES256-SHA",		"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA");
+        add("ECDHE-ECDSA-AES256-SHA384",	"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384");
+        add("ECDHE-ECDSA-CHACHA20-POLY1305",   	"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305");
+        add("ECDHE-ECDSA-DES-CBC3-SHA",		"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA");
+        add("ECDHE-ECDSA-NULL-SHA",		"TLS_ECDHE_ECDSA_WITH_NULL_SHA");
+        add("ECDHE-ECDSA-RC4-SHA",		"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
+        add("ECDHE-PSK-AES128-CBC-SHA",		"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA");
+        add("ECDHE-PSK-AES128-GCM-SHA256",     	"TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256");
+        add("ECDHE-PSK-AES256-CBC-SHA",		"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA");
+        add("ECDHE-PSK-AES256-GCM-SHA384",     	"TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384");
+        add("ECDHE-RSA-AES128-GCM-SHA256",     	"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
+        add("ECDHE-RSA-AES128-SHA",		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
+        add("ECDHE-RSA-AES128-SHA256",		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256");
+        add("ECDHE-RSA-AES256-GCM-SHA384",     	"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");
+        add("ECDHE-RSA-AES256-SHA",		"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
+        add("ECDHE-RSA-AES256-SHA384",		"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384");
+        add("ECDHE-RSA-CHACHA20-POLY1305",     	"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305");
+        add("ECDHE-RSA-DES-CBC3-SHA",		"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA");
+        add("ECDHE-RSA-NULL-SHA",		"TLS_ECDHE_RSA_WITH_NULL_SHA");
+        add("ECDHE-RSA-RC4-SHA",		"TLS_ECDHE_RSA_WITH_RC4_128_SHA");
+        add("EDH-RSA-DES-CBC-SHA",		"SSL_DHE_RSA_WITH_DES_CBC_SHA");
+        add("EDH-RSA-DES-CBC3-SHA",		"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
+        add("EXP-ADH-DES-CBC-SHA",		"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA");
+        add("EXP-ADH-RC4-MD5",			"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5");
+        add("EXP-DES-CBC-SHA",			"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA");
+        add("EXP-EDH-RSA-DES-CBC-SHA",		"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
+        add("EXP-RC4-MD5",			"SSL_RSA_EXPORT_WITH_RC4_40_MD5");
+        add("NULL-MD5",				"SSL_RSA_WITH_NULL_MD5");
+        add("NULL-SHA",				"SSL_RSA_WITH_NULL_SHA");
+        add("NULL-SHA256",			"TLS_RSA_WITH_NULL_SHA256");
+        add("PSK-3DES-EDE-CBC-SHA",		"TLS_PSK_WITH_3DES_EDE_CBC_SHA");
+        add("PSK-AES128-CBC-SHA",		"TLS_PSK_WITH_AES_128_CBC_SHA");
+        add("PSK-AES256-CBC-SHA",		"TLS_PSK_WITH_AES_256_CBC_SHA");
+        add("PSK-RC4-SHA",			"TLS_PSK_WITH_RC4_128_SHA");
+        add("RC4-MD5",				"SSL_RSA_WITH_RC4_128_MD5");
+        add("RC4-SHA",				"SSL_RSA_WITH_RC4_128_SHA");
 
         // Signaling Cipher Suite Value for secure renegotiation handled as special case.
         // add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", null);
@@ -735,9 +712,20 @@
 
     private static final String[] SUPPORTED_CIPHER_SUITES;
     static {
-        int size = STANDARD_TO_OPENSSL_CIPHER_SUITES.size();
+        // Cipher selection string must work with OpenSSL and BoringSSL.
+        String[] allOpenSSLCipherSuites = get_cipher_names("ALL:-EXP:-SRP:-SEED:-CAMELLIA:-DSS:-RC2:-DES-CBC-MD5:-DES-CBC3-MD5");
+
+        int size = allOpenSSLCipherSuites.length;
         SUPPORTED_CIPHER_SUITES = new String[size + 2];
-        STANDARD_TO_OPENSSL_CIPHER_SUITES.keySet().toArray(SUPPORTED_CIPHER_SUITES);
+        for (int i = 0; i < size; i++) {
+            String standardName = OPENSSL_TO_STANDARD_CIPHER_SUITES.get(allOpenSSLCipherSuites[i]);
+            if (standardName == null) {
+                throw new IllegalArgumentException("Unknown cipher suite supported by native code: " +
+                                                   allOpenSSLCipherSuites[i]);
+            }
+            SUPPORTED_CIPHER_SUITES[i] = standardName;
+            SUPPORTED_CIPHER_SUITES_SET.add(standardName);
+        }
         SUPPORTED_CIPHER_SUITES[size] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
         SUPPORTED_CIPHER_SUITES[size + 1] = TLS_FALLBACK_SCSV;
     }
@@ -972,10 +960,14 @@
                     cipherSuite.equals(TLS_FALLBACK_SCSV)) {
                 continue;
             }
-            if (STANDARD_TO_OPENSSL_CIPHER_SUITES.containsKey(cipherSuite)) {
+            if (SUPPORTED_CIPHER_SUITES_SET.contains(cipherSuite)) {
                 continue;
             }
-            if (OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(cipherSuite)) {
+
+            // For backwards compatibility, it's allowed for |cipherSuite| to
+            // be an OpenSSL-style cipher-suite name.
+            String standardName = OPENSSL_TO_STANDARD_CIPHER_SUITES.get(cipherSuite);
+            if (standardName != null && SUPPORTED_CIPHER_SUITES_SET.contains(standardName)) {
                 // TODO log warning about using backward compatability
                 continue;
             }
@@ -1218,4 +1210,6 @@
     public static native long ERR_peek_last_error();
 
     public static native String SSL_CIPHER_get_kx_name(long cipherAddress);
+
+    public static native String[] get_cipher_names(String selection);
 }
diff --git a/src/main/native/org_conscrypt_NativeCrypto.cpp b/src/main/native/org_conscrypt_NativeCrypto.cpp
index 8661705..a1432d9 100644
--- a/src/main/native/org_conscrypt_NativeCrypto.cpp
+++ b/src/main/native/org_conscrypt_NativeCrypto.cpp
@@ -10102,6 +10102,40 @@
     return env->NewStringUTF(kx_name);
 }
 
+static jobjectArray NativeCrypto_get_cipher_names(JNIEnv *env, jclass, jstring selectorJava) {
+    ScopedUtfChars selector(env, selectorJava);
+    if (selector.c_str() == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "selector == NULL");
+        return 0;
+    }
+
+    JNI_TRACE("NativeCrypto_get_cipher_names %s", selector.c_str());
+
+    Unique_SSL_CTX sslCtx(SSL_CTX_new(SSLv23_method()));
+    Unique_SSL ssl(SSL_new(sslCtx.get()));
+
+    if (!SSL_set_cipher_list(ssl.get(), selector.c_str())) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Unable to set SSL cipher list");
+        return 0;
+    }
+    STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl.get());
+
+    size_t size = sk_SSL_CIPHER_num(ciphers);
+    ScopedLocalRef<jobjectArray> cipherNamesArray(env, env->NewObjectArray(size, stringClass, NULL));
+    if (cipherNamesArray.get() == NULL) {
+        return NULL;
+    }
+
+    for (size_t i = 0; i < size; i++) {
+        const char *name = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciphers, i));
+        ScopedLocalRef<jstring> cipherName(env, env->NewStringUTF(name));
+        env->SetObjectArrayElement(cipherNamesArray.get(), i, cipherName.get());
+    }
+
+    JNI_TRACE("NativeCrypto_get_cipher_names(%s) => success (%zd entries)", selector.c_str(), size);
+    return cipherNamesArray.release();
+}
+
 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
 #define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
 #define REF_EC_GROUP "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef$EC_GROUP;"
@@ -10337,6 +10371,7 @@
     NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
     NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
     NATIVE_METHOD(NativeCrypto, SSL_CIPHER_get_kx_name, "(J)Ljava/lang/String;"),
+    NATIVE_METHOD(NativeCrypto, get_cipher_names, "(Ljava/lang/String;)[Ljava/lang/String;"),
 };
 
 static jclass getGlobalRefToClass(JNIEnv* env, const char* className) {