Further tidy up cipher logic.

With SSL2 gone, there's no need for this split between the abstract
cipher framework and ciphers. Put the cipher suite table in ssl_cipher.c
and move other SSL_CIPHER logic there. With that gone, prune the
cipher-related hooks in SSL_PROTOCOL_METHOD.

BUG=468889

Change-Id: I48579de8bc4c0ea52781ba1b7b57bc5b4919d21c
Reviewed-on: https://boringssl-review.googlesource.com/4961
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 473588d..ef7a9c9 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -151,14 +151,9 @@
   s->d1 = NULL;
 }
 
-const SSL_CIPHER *dtls1_get_cipher(size_t i) {
-  const SSL_CIPHER *ciph = ssl3_get_cipher(i);
+int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
   /* DTLS does not support stream ciphers. */
-  if (ciph == NULL || ciph->algorithm_enc == SSL_RC4) {
-    return NULL;
-  }
-
-  return ciph;
+  return cipher->algorithm_enc != SSL_RC4;
 }
 
 void dtls1_start_timer(SSL *s) {
diff --git a/ssl/d1_meth.c b/ssl/d1_meth.c
index eb30b0e..d90f75b 100644
--- a/ssl/d1_meth.c
+++ b/ssl/d1_meth.c
@@ -71,8 +71,7 @@
     dtls1_dispatch_alert,
     ssl3_ctrl,
     ssl3_ctx_ctrl,
-    ssl3_num_ciphers,
-    dtls1_get_cipher,
+    dtls1_supports_cipher,
     DTLS1_HM_HEADER_LENGTH,
     dtls1_set_handshake_header,
     dtls1_handshake_write,
diff --git a/ssl/internal.h b/ssl/internal.h
index 38360bd..7d9a5ad 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -260,6 +260,9 @@
 #define SSL_PKEY_ECC 2
 #define SSL_PKEY_NUM 3
 
+/* ssl_cipher_get_value returns the cipher suite id of |cipher|. */
+uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher);
+
 /* ssl_cipher_get_cert_index returns the |SSL_PKEY_*| value corresponding to the
  * certificate type of |cipher| or -1 if there is none. */
 int ssl_cipher_get_cert_index(const SSL_CIPHER *cipher);
@@ -633,8 +636,9 @@
   int (*ssl_dispatch_alert)(SSL *s);
   long (*ssl_ctrl)(SSL *s, int cmd, long larg, void *parg);
   long (*ssl_ctx_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
-  size_t (*num_ciphers)(void);
-  const SSL_CIPHER *(*get_cipher)(size_t i);
+  /* supports_cipher returns one if |cipher| is supported by this protocol and
+   * zero otherwise. */
+  int (*supports_cipher)(const SSL_CIPHER *cipher);
   /* Handshake header length */
   unsigned int hhlen;
   /* Set the handshake header */
@@ -783,8 +787,6 @@
   unsigned int change_cipher_spec_ok;
 } DTLS1_STATE;
 
-extern const SSL_CIPHER ssl3_ciphers[];
-
 extern const SSL3_ENC_METHOD TLSv1_enc_data;
 extern const SSL3_ENC_METHOD TLSv1_1_enc_data;
 extern const SSL3_ENC_METHOD TLSv1_2_enc_data;
@@ -801,8 +803,6 @@
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx);
-int ssl_cipher_id_cmp(const void *in_a, const void *in_b);
-int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp);
 STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs);
 int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p);
 struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_dup(
@@ -843,8 +843,6 @@
  * |len|. It returns one on success and zero on failure. */
 int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server);
 
-const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value);
-uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c);
 int ssl3_init_finished_mac(SSL *s);
 int ssl3_send_server_certificate(SSL *s);
 int ssl3_send_new_session_ticket(SSL *s);
@@ -876,8 +874,7 @@
                           const EVP_MD **out_md, EVP_PKEY *pkey);
 
 int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen);
-size_t ssl3_num_ciphers(void);
-const SSL_CIPHER *ssl3_get_cipher(size_t i);
+int ssl3_supports_cipher(const SSL_CIPHER *cipher);
 int ssl3_dispatch_alert(SSL *s);
 int ssl3_expect_change_cipher_spec(SSL *s);
 int ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek);
@@ -952,7 +949,7 @@
 int dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
 int dtls1_handshake_write(SSL *s);
 
-const SSL_CIPHER *dtls1_get_cipher(size_t i);
+int dtls1_supports_cipher(const SSL_CIPHER *cipher);
 void dtls1_start_timer(SSL *s);
 void dtls1_stop_timer(SSL *s);
 int dtls1_is_timer_expired(SSL *s);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index f1698b7..dbfa355 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -816,7 +816,7 @@
     memcpy(s->session->session_id, CBS_data(&session_id), CBS_len(&session_id));
   }
 
-  c = ssl3_get_cipher_by_value(cipher_suite);
+  c = SSL_get_cipher_by_value(cipher_suite);
   if (c == NULL) {
     /* unknown cipher */
     al = SSL_AD_ILLEGAL_PARAMETER;
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 4fbe92d..1c28a73 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -160,323 +160,6 @@
 #include "internal.h"
 
 
-#define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers) / sizeof(SSL_CIPHER))
-
-/* list of available SSLv3 ciphers (sorted by id) */
-const SSL_CIPHER ssl3_ciphers[] = {
-    /* The RSA ciphers */
-    /* Cipher 04 */
-    {
-     SSL3_TXT_RSA_RC4_128_MD5, SSL3_CK_RSA_RC4_128_MD5, SSL_kRSA, SSL_aRSA,
-     SSL_RC4, SSL_MD5, SSL_SSLV3, SSL_MEDIUM,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher 05 */
-    {
-     SSL3_TXT_RSA_RC4_128_SHA, SSL3_CK_RSA_RC4_128_SHA, SSL_kRSA, SSL_aRSA,
-     SSL_RC4, SSL_SHA1, SSL_SSLV3, SSL_MEDIUM,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher 0A */
-    {
-     SSL3_TXT_RSA_DES_192_CBC3_SHA, SSL3_CK_RSA_DES_192_CBC3_SHA, SSL_kRSA,
-     SSL_aRSA, SSL_3DES, SSL_SHA1, SSL_SSLV3, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 112, 168,
-    },
-
-
-    /* New AES ciphersuites */
-
-    /* Cipher 2F */
-    {
-     TLS1_TXT_RSA_WITH_AES_128_SHA, TLS1_CK_RSA_WITH_AES_128_SHA, SSL_kRSA,
-     SSL_aRSA, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher 33 */
-    {
-     TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
-     SSL_kDHE, SSL_aRSA, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher 35 */
-    {
-     TLS1_TXT_RSA_WITH_AES_256_SHA, TLS1_CK_RSA_WITH_AES_256_SHA, SSL_kRSA,
-     SSL_aRSA, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
-    },
-
-    /* Cipher 39 */
-    {
-     TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
-     SSL_kDHE, SSL_aRSA, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
-    },
-
-
-    /* TLS v1.2 ciphersuites */
-
-    /* Cipher 3C */
-    {
-     TLS1_TXT_RSA_WITH_AES_128_SHA256, TLS1_CK_RSA_WITH_AES_128_SHA256,
-     SSL_kRSA, SSL_aRSA, SSL_AES128, SSL_SHA256, SSL_TLSV1_2,
-     SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_SHA256, 128, 128,
-    },
-
-    /* Cipher 3D */
-    {
-     TLS1_TXT_RSA_WITH_AES_256_SHA256, TLS1_CK_RSA_WITH_AES_256_SHA256,
-     SSL_kRSA, SSL_aRSA, SSL_AES256, SSL_SHA256, SSL_TLSV1_2,
-     SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_SHA256, 256, 256,
-    },
-
-    /* Cipher 67 */
-    {
-     TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
-     TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, SSL_kDHE, SSL_aRSA, SSL_AES128,
-     SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256, 128, 128,
-    },
-
-    /* Cipher 6B */
-    {
-     TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
-     TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, SSL_kDHE, SSL_aRSA, SSL_AES256,
-     SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256, 256, 256,
-    },
-
-    /* Cipher 8A */
-    {
-     TLS1_TXT_PSK_WITH_RC4_128_SHA, TLS1_CK_PSK_WITH_RC4_128_SHA, SSL_kPSK,
-     SSL_aPSK, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher 8C */
-    {
-     TLS1_TXT_PSK_WITH_AES_128_CBC_SHA, TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
-     SSL_kPSK, SSL_aPSK, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher 8D */
-    {
-     TLS1_TXT_PSK_WITH_AES_256_CBC_SHA, TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
-     SSL_kPSK, SSL_aPSK, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
-    },
-
-
-    /* GCM ciphersuites from RFC5288 */
-
-    /* Cipher 9C */
-    {
-     TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
-     TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, SSL_kRSA, SSL_aRSA, SSL_AES128GCM,
-     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     128, 128,
-    },
-
-    /* Cipher 9D */
-    {
-     TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
-     TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, SSL_kRSA, SSL_aRSA, SSL_AES256GCM,
-     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA384 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     256, 256,
-    },
-
-    /* Cipher 9E */
-    {
-     TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
-     TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kDHE, SSL_aRSA, SSL_AES128GCM,
-     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     128, 128,
-    },
-
-    /* Cipher 9F */
-    {
-     TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
-     TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kDHE, SSL_aRSA, SSL_AES256GCM,
-     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA384 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     256, 256,
-    },
-
-    /* Cipher C007 */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
-     TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_kECDHE, SSL_aECDSA, SSL_RC4,
-     SSL_SHA1, SSL_TLSV1, SSL_MEDIUM, SSL_HANDSHAKE_MAC_DEFAULT, 128,
-     128,
-    },
-
-    /* Cipher C009 */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-     TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_kECDHE, SSL_aECDSA,
-     SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher C00A */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
-     TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_kECDHE, SSL_aECDSA,
-     SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
-    },
-
-    /* Cipher C011 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
-     SSL_kECDHE, SSL_aRSA, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher C013 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-     TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_kECDHE, SSL_aRSA, SSL_AES128,
-     SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
-    },
-
-    /* Cipher C014 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
-     TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_kECDHE, SSL_aRSA, SSL_AES256,
-     SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
-    },
-
-
-    /* HMAC based TLS v1.2 ciphersuites from RFC5289 */
-
-    /* Cipher C023 */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
-     TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, SSL_kECDHE, SSL_aECDSA,
-     SSL_AES128, SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256, 128, 128,
-    },
-
-    /* Cipher C024 */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
-     TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, SSL_kECDHE, SSL_aECDSA,
-     SSL_AES256, SSL_SHA384, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA384, 256, 256,
-    },
-
-    /* Cipher C027 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256,
-     TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, SSL_kECDHE, SSL_aRSA, SSL_AES128,
-     SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256, 128, 128,
-    },
-
-    /* Cipher C028 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
-     TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, SSL_kECDHE, SSL_aRSA, SSL_AES256,
-     SSL_SHA384, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA384, 256, 256,
-    },
-
-
-    /* GCM based TLS v1.2 ciphersuites from RFC5289 */
-
-    /* Cipher C02B */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-     TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_kECDHE, SSL_aECDSA,
-     SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     128, 128,
-    },
-
-    /* Cipher C02C */
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-     TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_kECDHE, SSL_aECDSA,
-     SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA384 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     256, 256,
-    },
-
-    /* Cipher C02F */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-     TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kECDHE, SSL_aRSA,
-     SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     128, 128,
-    },
-
-    /* Cipher C030 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-     TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kECDHE, SSL_aRSA,
-     SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
-     SSL_HANDSHAKE_MAC_SHA384 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     256, 256,
-    },
-
-
-    /* ECDH PSK ciphersuites */
-
-    /* Cipher CAFE */
-    {
-     TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
-     TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256, SSL_kECDHE, SSL_aPSK,
-     SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256 |
-         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
-     128, 128,
-    },
-
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
-     TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, SSL_kECDHE, SSL_aRSA,
-     SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256,
-     256, 0,
-    },
-
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
-     TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, SSL_kECDHE, SSL_aECDSA,
-     SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256,
-     256, 0,
-    },
-
-    {
-     TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
-     TLS1_CK_DHE_RSA_CHACHA20_POLY1305, SSL_kDHE, SSL_aRSA,
-     SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256,
-     256, 0,
-    },
-};
-
 const SSL3_ENC_METHOD SSLv3_enc_data = {
     ssl3_prf,
     tls1_setup_key_block,
@@ -491,14 +174,8 @@
     0,
 };
 
-size_t ssl3_num_ciphers(void) { return SSL3_NUM_CIPHERS; }
-
-const SSL_CIPHER *ssl3_get_cipher(size_t i) {
-  if (i >= SSL3_NUM_CIPHERS) {
-    return NULL;
-  }
-
-  return &ssl3_ciphers[SSL3_NUM_CIPHERS - 1 - i];
+int ssl3_supports_cipher(const SSL_CIPHER *cipher) {
+  return 1;
 }
 
 int ssl3_set_handshake_header(SSL *s, int htype, unsigned long len) {
@@ -935,27 +612,6 @@
   return 1;
 }
 
-/* ssl3_get_cipher_by_value returns the SSL_CIPHER with value |value| or NULL
- * if none exists.
- *
- * This function needs to check if the ciphers required are actually
- * available. */
-const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value) {
-  SSL_CIPHER c;
-
-  c.id = 0x03000000L | value;
-  return bsearch(&c, ssl3_ciphers, SSL3_NUM_CIPHERS, sizeof(SSL_CIPHER),
-                 ssl_cipher_id_cmp);
-}
-
-/* ssl3_get_cipher_by_value returns the cipher value of |c|. */
-uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c) {
-  uint32_t id = c->id;
-  /* All ciphers are SSLv3 now. */
-  assert((id & 0xff000000) == 0x03000000);
-  return id & 0xffff;
-}
-
 struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *s) {
   if (s->cipher_list != NULL) {
     return s->cipher_list;
diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c
index b69dc97..66bbb29 100644
--- a/ssl/s3_meth.c
+++ b/ssl/s3_meth.c
@@ -70,8 +70,7 @@
     ssl3_dispatch_alert,
     ssl3_ctrl,
     ssl3_ctx_ctrl,
-    ssl3_num_ciphers,
-    ssl3_get_cipher,
+    ssl3_supports_cipher,
     SSL3_HM_HEADER_LENGTH,
     ssl3_set_handshake_header,
     ssl3_handshake_write,
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index df46d3d..1723828 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1167,7 +1167,7 @@
     p += sl;
 
     /* put the cipher */
-    s2n(ssl3_get_cipher_value(s->s3->tmp.new_cipher), p);
+    s2n(ssl_cipher_get_value(s->s3->tmp.new_cipher), p);
 
     /* put the compression method */
     *(p++) = 0;
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 21492dc..d1ac1b6 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -502,7 +502,7 @@
     OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
     goto err;
   }
-  ret->cipher = ssl3_get_cipher_by_value(cipher_value);
+  ret->cipher = SSL_get_cipher_by_value(cipher_value);
   if (ret->cipher == NULL) {
     OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_UNSUPPORTED_CIPHER);
     goto err;
diff --git a/ssl/ssl_cipher.c b/ssl/ssl_cipher.c
index face003..ac6f90f 100644
--- a/ssl/ssl_cipher.c
+++ b/ssl/ssl_cipher.c
@@ -152,6 +152,323 @@
 #include "internal.h"
 
 
+/* kCiphers is an array of all supported ciphers, sorted by id. */
+const SSL_CIPHER kCiphers[] = {
+    /* The RSA ciphers */
+    /* Cipher 04 */
+    {
+     SSL3_TXT_RSA_RC4_128_MD5, SSL3_CK_RSA_RC4_128_MD5, SSL_kRSA, SSL_aRSA,
+     SSL_RC4, SSL_MD5, SSL_SSLV3, SSL_MEDIUM,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher 05 */
+    {
+     SSL3_TXT_RSA_RC4_128_SHA, SSL3_CK_RSA_RC4_128_SHA, SSL_kRSA, SSL_aRSA,
+     SSL_RC4, SSL_SHA1, SSL_SSLV3, SSL_MEDIUM,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher 0A */
+    {
+     SSL3_TXT_RSA_DES_192_CBC3_SHA, SSL3_CK_RSA_DES_192_CBC3_SHA, SSL_kRSA,
+     SSL_aRSA, SSL_3DES, SSL_SHA1, SSL_SSLV3, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 112, 168,
+    },
+
+
+    /* New AES ciphersuites */
+
+    /* Cipher 2F */
+    {
+     TLS1_TXT_RSA_WITH_AES_128_SHA, TLS1_CK_RSA_WITH_AES_128_SHA, SSL_kRSA,
+     SSL_aRSA, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher 33 */
+    {
+     TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
+     SSL_kDHE, SSL_aRSA, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher 35 */
+    {
+     TLS1_TXT_RSA_WITH_AES_256_SHA, TLS1_CK_RSA_WITH_AES_256_SHA, SSL_kRSA,
+     SSL_aRSA, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
+    },
+
+    /* Cipher 39 */
+    {
+     TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
+     SSL_kDHE, SSL_aRSA, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
+    },
+
+
+    /* TLS v1.2 ciphersuites */
+
+    /* Cipher 3C */
+    {
+     TLS1_TXT_RSA_WITH_AES_128_SHA256, TLS1_CK_RSA_WITH_AES_128_SHA256,
+     SSL_kRSA, SSL_aRSA, SSL_AES128, SSL_SHA256, SSL_TLSV1_2,
+     SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_SHA256, 128, 128,
+    },
+
+    /* Cipher 3D */
+    {
+     TLS1_TXT_RSA_WITH_AES_256_SHA256, TLS1_CK_RSA_WITH_AES_256_SHA256,
+     SSL_kRSA, SSL_aRSA, SSL_AES256, SSL_SHA256, SSL_TLSV1_2,
+     SSL_HIGH | SSL_FIPS, SSL_HANDSHAKE_MAC_SHA256, 256, 256,
+    },
+
+    /* Cipher 67 */
+    {
+     TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
+     TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, SSL_kDHE, SSL_aRSA, SSL_AES128,
+     SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256, 128, 128,
+    },
+
+    /* Cipher 6B */
+    {
+     TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
+     TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, SSL_kDHE, SSL_aRSA, SSL_AES256,
+     SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256, 256, 256,
+    },
+
+    /* Cipher 8A */
+    {
+     TLS1_TXT_PSK_WITH_RC4_128_SHA, TLS1_CK_PSK_WITH_RC4_128_SHA, SSL_kPSK,
+     SSL_aPSK, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher 8C */
+    {
+     TLS1_TXT_PSK_WITH_AES_128_CBC_SHA, TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
+     SSL_kPSK, SSL_aPSK, SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher 8D */
+    {
+     TLS1_TXT_PSK_WITH_AES_256_CBC_SHA, TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+     SSL_kPSK, SSL_aPSK, SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
+    },
+
+
+    /* GCM ciphersuites from RFC5288 */
+
+    /* Cipher 9C */
+    {
+     TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, SSL_kRSA, SSL_aRSA, SSL_AES128GCM,
+     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     128, 128,
+    },
+
+    /* Cipher 9D */
+    {
+     TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, SSL_kRSA, SSL_aRSA, SSL_AES256GCM,
+     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     256, 256,
+    },
+
+    /* Cipher 9E */
+    {
+     TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kDHE, SSL_aRSA, SSL_AES128GCM,
+     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     128, 128,
+    },
+
+    /* Cipher 9F */
+    {
+     TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kDHE, SSL_aRSA, SSL_AES256GCM,
+     SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     256, 256,
+    },
+
+    /* Cipher C007 */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
+     TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_kECDHE, SSL_aECDSA, SSL_RC4,
+     SSL_SHA1, SSL_TLSV1, SSL_MEDIUM, SSL_HANDSHAKE_MAC_DEFAULT, 128,
+     128,
+    },
+
+    /* Cipher C009 */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+     TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_kECDHE, SSL_aECDSA,
+     SSL_AES128, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher C00A */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+     TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_kECDHE, SSL_aECDSA,
+     SSL_AES256, SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
+    },
+
+    /* Cipher C011 */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
+     SSL_kECDHE, SSL_aRSA, SSL_RC4, SSL_SHA1, SSL_TLSV1, SSL_MEDIUM,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher C013 */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+     TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_kECDHE, SSL_aRSA, SSL_AES128,
+     SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 128, 128,
+    },
+
+    /* Cipher C014 */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+     TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_kECDHE, SSL_aRSA, SSL_AES256,
+     SSL_SHA1, SSL_TLSV1, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT, 256, 256,
+    },
+
+
+    /* HMAC based TLS v1.2 ciphersuites from RFC5289 */
+
+    /* Cipher C023 */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
+     TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, SSL_kECDHE, SSL_aECDSA,
+     SSL_AES128, SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256, 128, 128,
+    },
+
+    /* Cipher C024 */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
+     TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, SSL_kECDHE, SSL_aECDSA,
+     SSL_AES256, SSL_SHA384, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384, 256, 256,
+    },
+
+    /* Cipher C027 */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256,
+     TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, SSL_kECDHE, SSL_aRSA, SSL_AES128,
+     SSL_SHA256, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256, 128, 128,
+    },
+
+    /* Cipher C028 */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
+     TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, SSL_kECDHE, SSL_aRSA, SSL_AES256,
+     SSL_SHA384, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384, 256, 256,
+    },
+
+
+    /* GCM based TLS v1.2 ciphersuites from RFC5289 */
+
+    /* Cipher C02B */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_kECDHE, SSL_aECDSA,
+     SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     128, 128,
+    },
+
+    /* Cipher C02C */
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_kECDHE, SSL_aECDSA,
+     SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     256, 256,
+    },
+
+    /* Cipher C02F */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kECDHE, SSL_aRSA,
+     SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     128, 128,
+    },
+
+    /* Cipher C030 */
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kECDHE, SSL_aRSA,
+     SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     256, 256,
+    },
+
+
+    /* ECDH PSK ciphersuites */
+
+    /* Cipher CAFE */
+    {
+     TLS1_TXT_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256, SSL_kECDHE, SSL_aPSK,
+     SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 |
+         SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
+     128, 128,
+    },
+
+    {
+     TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, SSL_kECDHE, SSL_aRSA,
+     SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256,
+     256, 0,
+    },
+
+    {
+     TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, SSL_kECDHE, SSL_aECDSA,
+     SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256,
+     256, 0,
+    },
+
+    {
+     TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_DHE_RSA_CHACHA20_POLY1305, SSL_kDHE, SSL_aRSA,
+     SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256,
+     256, 0,
+    },
+};
+
+static const size_t kCiphersLen = sizeof(kCiphers) / sizeof(kCiphers[0]);
+
 struct handshake_digest {
   uint32_t mask;
   const EVP_MD *(*md_func)(void);
@@ -193,71 +510,96 @@
   uint32_t algo_strength;
 } CIPHER_ALIAS;
 
-static const CIPHER_ALIAS kCipherAliases[] =
-    {
-     {SSL_TXT_ALL, ~0u, ~0u, ~0u, ~0u, ~0u, ~0u},
+static const CIPHER_ALIAS kCipherAliases[] = {
+    {SSL_TXT_ALL, ~0u, ~0u, ~0u, ~0u, ~0u, ~0u},
 
-     /* The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing. */
+    /* The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing. */
 
-     /* key exchange aliases
-      * (some of those using only a single bit here combine
-      * multiple key exchange algs according to the RFCs,
-      * e.g. kEDH combines DHE_DSS and DHE_RSA) */
-     {SSL_TXT_kRSA, SSL_kRSA, ~0u, ~0u, ~0u, ~0u, ~0u},
+    /* key exchange aliases
+     * (some of those using only a single bit here combine
+     * multiple key exchange algs according to the RFCs,
+     * e.g. kEDH combines DHE_DSS and DHE_RSA) */
+    {SSL_TXT_kRSA, SSL_kRSA, ~0u, ~0u, ~0u, ~0u, ~0u},
 
-     {SSL_TXT_kDHE, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_kEDH, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_DH, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_kDHE, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_kEDH, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_DH, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
 
-     {SSL_TXT_kECDHE, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_kEECDH, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_ECDH, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_kECDHE, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_kEECDH, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_ECDH, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
 
-     {SSL_TXT_kPSK, SSL_kPSK, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_kPSK, SSL_kPSK, ~0u, ~0u, ~0u, ~0u, ~0u},
 
-     /* server authentication aliases */
-     {SSL_TXT_aRSA, ~0u, SSL_aRSA, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_aECDSA, ~0u, SSL_aECDSA, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_ECDSA, ~0u, SSL_aECDSA, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_aPSK, ~0u, SSL_aPSK, ~0u, ~0u, ~0u, ~0u},
+    /* server authentication aliases */
+    {SSL_TXT_aRSA, ~0u, SSL_aRSA, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_aECDSA, ~0u, SSL_aECDSA, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_ECDSA, ~0u, SSL_aECDSA, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_aPSK, ~0u, SSL_aPSK, ~0u, ~0u, ~0u, ~0u},
 
-     /* aliases combining key exchange and server authentication */
-     {SSL_TXT_DHE, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_EDH, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_ECDHE, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_EECDH, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_RSA, SSL_kRSA, SSL_aRSA, ~0u, ~0u, ~0u, ~0u},
-     {SSL_TXT_PSK, SSL_kPSK, SSL_aPSK, ~0u, ~0u, ~0u, ~0u},
+    /* aliases combining key exchange and server authentication */
+    {SSL_TXT_DHE, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_EDH, SSL_kDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_ECDHE, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_EECDH, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_RSA, SSL_kRSA, SSL_aRSA, ~0u, ~0u, ~0u, ~0u},
+    {SSL_TXT_PSK, SSL_kPSK, SSL_aPSK, ~0u, ~0u, ~0u, ~0u},
 
-     /* symmetric encryption aliases */
-     {SSL_TXT_3DES, ~0u, ~0u, SSL_3DES, ~0u, ~0u, ~0u},
-     {SSL_TXT_RC4, ~0u, ~0u, SSL_RC4, ~0u, ~0u, ~0u},
-     {SSL_TXT_AES128, ~0u, ~0u, SSL_AES128 | SSL_AES128GCM, ~0u, ~0u, ~0u},
-     {SSL_TXT_AES256, ~0u, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, ~0u, ~0u},
-     {SSL_TXT_AES, ~0u, ~0u, SSL_AES, ~0u, ~0u, ~0u},
-     {SSL_TXT_AES_GCM, ~0u, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, ~0u, ~0u},
-     {SSL_TXT_CHACHA20, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, ~0u, ~0u},
+    /* symmetric encryption aliases */
+    {SSL_TXT_3DES, ~0u, ~0u, SSL_3DES, ~0u, ~0u, ~0u},
+    {SSL_TXT_RC4, ~0u, ~0u, SSL_RC4, ~0u, ~0u, ~0u},
+    {SSL_TXT_AES128, ~0u, ~0u, SSL_AES128 | SSL_AES128GCM, ~0u, ~0u, ~0u},
+    {SSL_TXT_AES256, ~0u, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, ~0u, ~0u},
+    {SSL_TXT_AES, ~0u, ~0u, SSL_AES, ~0u, ~0u, ~0u},
+    {SSL_TXT_AES_GCM, ~0u, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, ~0u, ~0u},
+    {SSL_TXT_CHACHA20, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, ~0u, ~0u},
 
-     /* MAC aliases */
-     {SSL_TXT_MD5, ~0u, ~0u, ~0u, SSL_MD5, ~0u, ~0u},
-     {SSL_TXT_SHA1, ~0u, ~0u, ~0u, SSL_SHA1, ~0u, ~0u},
-     {SSL_TXT_SHA, ~0u, ~0u, ~0u, SSL_SHA1, ~0u, ~0u},
-     {SSL_TXT_SHA256, ~0u, ~0u, ~0u, SSL_SHA256, ~0u, ~0u},
-     {SSL_TXT_SHA384, ~0u, ~0u, ~0u, SSL_SHA384, ~0u, ~0u},
+    /* MAC aliases */
+    {SSL_TXT_MD5, ~0u, ~0u, ~0u, SSL_MD5, ~0u, ~0u},
+    {SSL_TXT_SHA1, ~0u, ~0u, ~0u, SSL_SHA1, ~0u, ~0u},
+    {SSL_TXT_SHA, ~0u, ~0u, ~0u, SSL_SHA1, ~0u, ~0u},
+    {SSL_TXT_SHA256, ~0u, ~0u, ~0u, SSL_SHA256, ~0u, ~0u},
+    {SSL_TXT_SHA384, ~0u, ~0u, ~0u, SSL_SHA384, ~0u, ~0u},
 
-     /* protocol version aliases */
-     {SSL_TXT_SSLV3, ~0u, ~0u, ~0u, ~0u, SSL_SSLV3, ~0u},
-     {SSL_TXT_TLSV1, ~0u, ~0u, ~0u, ~0u, SSL_TLSV1, ~0u},
-     {SSL_TXT_TLSV1_2, ~0u, ~0u, ~0u, ~0u, SSL_TLSV1_2, ~0u},
+    /* protocol version aliases */
+    {SSL_TXT_SSLV3, ~0u, ~0u, ~0u, ~0u, SSL_SSLV3, ~0u},
+    {SSL_TXT_TLSV1, ~0u, ~0u, ~0u, ~0u, SSL_TLSV1, ~0u},
+    {SSL_TXT_TLSV1_2, ~0u, ~0u, ~0u, ~0u, SSL_TLSV1_2, ~0u},
 
-     /* strength classes */
-     {SSL_TXT_MEDIUM, ~0u, ~0u, ~0u, ~0u, ~0u, SSL_MEDIUM},
-     {SSL_TXT_HIGH, ~0u, ~0u, ~0u, ~0u, ~0u, SSL_HIGH},
-     /* FIPS 140-2 approved ciphersuite */
-     {SSL_TXT_FIPS, ~0u, ~0u, ~0u, ~0u, ~0u, SSL_FIPS},
+    /* strength classes */
+    {SSL_TXT_MEDIUM, ~0u, ~0u, ~0u, ~0u, ~0u, SSL_MEDIUM},
+    {SSL_TXT_HIGH, ~0u, ~0u, ~0u, ~0u, ~0u, SSL_HIGH},
+    /* FIPS 140-2 approved ciphersuite */
+    {SSL_TXT_FIPS, ~0u, ~0u, ~0u, ~0u, ~0u, SSL_FIPS},
 };
 
-#define NUM_CIPHER_ALIASES (sizeof(kCipherAliases) / sizeof(kCipherAliases[0]))
+static const size_t kCipherAliasesLen =
+    sizeof(kCipherAliases) / sizeof(kCipherAliases[0]);
+
+static int ssl_cipher_id_cmp(const void *in_a, const void *in_b) {
+  const SSL_CIPHER *a = in_a;
+  const SSL_CIPHER *b = in_b;
+
+  if (a->id > b->id) {
+    return 1;
+  } else if (a->id < b->id) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+static int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **a, const SSL_CIPHER **b) {
+  return ssl_cipher_id_cmp(*a, *b);
+}
+
+const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
+  SSL_CIPHER c;
+
+  c.id = 0x03000000L | value;
+  return bsearch(&c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER),
+                 ssl_cipher_id_cmp);
+}
 
 int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
                             size_t *out_mac_secret_len,
@@ -437,22 +779,17 @@
 }
 
 static void ssl_cipher_collect_ciphers(const SSL_PROTOCOL_METHOD *ssl_method,
-                                       size_t num_of_ciphers,
                                        CIPHER_ORDER *co_list,
                                        CIPHER_ORDER **head_p,
                                        CIPHER_ORDER **tail_p) {
-  size_t i, co_list_num;
-
-  /* We have num_of_ciphers descriptions compiled in, depending on the method
-   * selected (SSLv2 and/or SSLv3, TLSv1 etc). These will later be sorted in a
-   * linked list with at most num entries. */
-
-  /* Get the initial list of ciphers */
-  co_list_num = 0; /* actual count of ciphers */
-  for (i = 0; i < num_of_ciphers; i++) {
-    const SSL_CIPHER *c = ssl_method->get_cipher(i);
-    if (c != NULL) {
-      co_list[co_list_num].cipher = c;
+  /* The set of ciphers is static, but some subset may be unsupported by
+   * |ssl_method|, so the list may be smaller. */
+  size_t co_list_num = 0;
+  size_t i;
+  for (i = 0; i < kCiphersLen; i++) {
+    const SSL_CIPHER *cipher = &kCiphers[i];
+    if (ssl_method->supports_cipher(cipher)) {
+      co_list[co_list_num].cipher = cipher;
       co_list[co_list_num].next = NULL;
       co_list[co_list_num].prev = NULL;
       co_list[co_list_num].active = 0;
@@ -775,10 +1112,9 @@
       /* Look for a matching exact cipher. These aren't allowed in multipart
        * rules. */
       if (!multi && ch != '+') {
-        size_t num_ciphers = ssl_method->num_ciphers();
-        for (j = 0; j < num_ciphers; j++) {
-          const SSL_CIPHER *cipher = ssl_method->get_cipher(j);
-          if (cipher != NULL && rule_equals(cipher->name, buf, buf_len)) {
+        for (j = 0; j < kCiphersLen; j++) {
+          const SSL_CIPHER *cipher = &kCiphers[j];
+          if (rule_equals(cipher->name, buf, buf_len)) {
             cipher_id = cipher->id;
             break;
           }
@@ -786,7 +1122,7 @@
       }
       if (cipher_id == 0) {
         /* If not an exact cipher, look for a matching cipher alias. */
-        for (j = 0; j < NUM_CIPHER_ALIASES; j++) {
+        for (j = 0; j < kCipherAliasesLen; j++) {
           if (rule_equals(kCipherAliases[j].name, buf, buf_len)) {
             alg_mkey &= kCipherAliases[j].algorithm_mkey;
             alg_auth &= kCipherAliases[j].algorithm_auth;
@@ -797,7 +1133,7 @@
             break;
           }
         }
-        if (j == NUM_CIPHER_ALIASES) {
+        if (j == kCipherAliasesLen) {
           alg_mkey = alg_auth = alg_enc = alg_mac = alg_ssl = algo_strength = 0;
         }
       }
@@ -851,7 +1187,6 @@
                        STACK_OF(SSL_CIPHER) **out_cipher_list_by_id,
                        const char *rule_str) {
   int ok;
-  size_t num_of_ciphers;
   STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
   const char *rule_p;
   CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
@@ -867,23 +1202,21 @@
   /* Now we have to collect the available ciphers from the compiled in ciphers.
    * We cannot get more than the number compiled in, so it is used for
    * allocation. */
-  num_of_ciphers = ssl_method->num_ciphers();
-  co_list =
-      (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
+  co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * kCiphersLen);
   if (co_list == NULL) {
     OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, co_list, &head, &tail);
+  ssl_cipher_collect_ciphers(ssl_method, co_list, &head, &tail);
 
   /* Now arrange all ciphers by preference:
    * TODO(davidben): Compute this order once and copy it. */
 
   /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other
    * key exchange mechanisms */
- ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, ~0u, ~0u,
-                       CIPHER_ADD, -1, 0, &head, &tail);
+  ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, ~0u, ~0u,
+                        CIPHER_ADD, -1, 0, &head, &tail);
   ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u, CIPHER_ADD, -1,
                         0, &head, &tail);
   ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, ~0u, ~0u, CIPHER_DEL, -1,
@@ -961,7 +1294,7 @@
     goto err;
   }
 
-  in_group_flags = OPENSSL_malloc(num_of_ciphers);
+  in_group_flags = OPENSSL_malloc(kCiphersLen);
   if (!in_group_flags) {
     goto err;
   }
@@ -1030,6 +1363,13 @@
 
 uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
 
+uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher) {
+  uint32_t id = cipher->id;
+  /* All ciphers are SSLv3. */
+  assert((id & 0xff000000) == 0x03000000);
+  return id & 0xffff;
+}
+
 int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_enc & SSL_AES) != 0;
 }
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 7149861..f20813b 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1122,34 +1122,6 @@
   return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg);
 }
 
-int ssl_cipher_id_cmp(const void *in_a, const void *in_b) {
-  long l;
-  const SSL_CIPHER *a = in_a;
-  const SSL_CIPHER *b = in_b;
-  const long a_id = a->id;
-  const long b_id = b->id;
-
-  l = a_id - b_id;
-  if (l == 0L) {
-    return 0;
-  } else {
-    return (l > 0) ? 1 : -1;
-  }
-}
-
-int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp) {
-  long l;
-  const long a_id = (*ap)->id;
-  const long b_id = (*bp)->id;
-
-  l = a_id - b_id;
-  if (l == 0) {
-    return 0;
-  } else {
-    return (l > 0) ? 1 : -1;
-  }
-}
-
 /* return a STACK of the ciphers available for the SSL and in order of
  * preference */
 STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) {
@@ -1288,7 +1260,7 @@
         c->algorithm_auth & ct->mask_a) {
       continue;
     }
-    s2n(ssl3_get_cipher_value(c), p);
+    s2n(ssl_cipher_get_value(c), p);
   }
 
   /* If all ciphers were disabled, return the error to the caller. */
@@ -1363,7 +1335,7 @@
       continue;
     }
 
-    c = ssl3_get_cipher_by_value(cipher_suite);
+    c = SSL_get_cipher_by_value(cipher_suite);
     if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) {
       OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE);
       goto err;
@@ -2943,10 +2915,6 @@
   s->accept_peer_renegotiations = !reject;
 }
 
-const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
-  return ssl3_get_cipher_by_value(value);
-}
-
 int SSL_get_rc4_state(const SSL *ssl, const RC4_KEY **read_key,
                       const RC4_KEY **write_key) {
   if (ssl->aead_read_ctx == NULL || ssl->aead_write_ctx == NULL) {