Use SSL_get_cipher_by_value to disable cipher suites.

The old logic was rather messy due to OpenSSL being unable to look up ciphers
by ID. BoringSSL, however, has a perfectly reasonable function to look up
cipher suites by value. Clean up the logic to not rely on SSL_get_ciphers. This
fixes a bug where TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 was not blacklistable
by command-line; at the time the blacklist code ran,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 is not in the list.

BUG=542322

Review URL: https://codereview.chromium.org/1395393002

Cr-Commit-Position: refs/heads/master@{#353566}
diff --git a/net/socket/ssl_server_socket_openssl.cc b/net/socket/ssl_server_socket_openssl.cc
index 5a61eeb..e8cbf5b 100644
--- a/net/socket/ssl_server_socket_openssl.cc
+++ b/net/socket/ssl_server_socket_openssl.cc
@@ -681,38 +681,21 @@
   SSL_set_mode(ssl_, mode.set_mask);
   SSL_clear_mode(ssl_, mode.clear_mask);
 
-  // Removing ciphers by ID from OpenSSL is a bit involved as we must use the
-  // textual name with SSL_set_cipher_list because there is no public API to
-  // directly remove a cipher by ID.
-  STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_);
-  DCHECK(ciphers);
   // See SSLConfig::disabled_cipher_suites for description of the suites
   // disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256
   // and HMAC-SHA384 cipher suites, not GCM cipher suites with SHA256 or SHA384
   // as the handshake hash.
   std::string command("DEFAULT:!SHA256:!SHA384:!AESGCM+AES256:!aPSK");
-  // Walk through all the installed ciphers, seeing if any need to be
-  // appended to the cipher removal |command|.
-  for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
-    const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
-    const uint16_t id = static_cast<uint16_t>(SSL_CIPHER_get_id(cipher));
 
-    bool disable = false;
-    if (ssl_config_.require_ecdhe) {
-      base::StringPiece kx_name(SSL_CIPHER_get_kx_name(cipher));
-      disable = kx_name != "ECDHE_RSA" && kx_name != "ECDHE_ECDSA";
-    }
-    if (!disable) {
-      disable = std::find(ssl_config_.disabled_cipher_suites.begin(),
-                          ssl_config_.disabled_cipher_suites.end(),
-                          id) != ssl_config_.disabled_cipher_suites.end();
-    }
-    if (disable) {
-      const char* name = SSL_CIPHER_get_name(cipher);
-      DVLOG(3) << "Found cipher to remove: '" << name << "', ID: " << id
-               << " strength: " << SSL_CIPHER_get_bits(cipher, NULL);
+  if (ssl_config_.require_ecdhe)
+    command.append(":!kRSA:!kDHE");
+
+  // Remove any disabled ciphers.
+  for (uint16_t id : ssl_config_.disabled_cipher_suites) {
+    const SSL_CIPHER* cipher = SSL_get_cipher_by_value(id);
+    if (cipher) {
       command.append(":!");
-      command.append(name);
+      command.append(SSL_CIPHER_get_name(cipher));
     }
   }