| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/ssl/ssl_cipher_suite_names.h" |
| |
| #include "base/notreached.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "net/ssl/ssl_connection_status_flags.h" |
| #include "third_party/boringssl/src/include/openssl/ssl.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| int ObsoleteSSLStatusForProtocol(int ssl_version) { |
| int obsolete_ssl = OBSOLETE_SSL_NONE; |
| if (ssl_version < SSL_CONNECTION_VERSION_TLS1_2) |
| obsolete_ssl |= OBSOLETE_SSL_MASK_PROTOCOL; |
| return obsolete_ssl; |
| } |
| |
| int ObsoleteSSLStatusForCipherSuite(uint16_t cipher_suite) { |
| int obsolete_ssl = OBSOLETE_SSL_NONE; |
| |
| const SSL_CIPHER* cipher = SSL_get_cipher_by_value(cipher_suite); |
| if (!cipher) { |
| // Cannot determine/unknown cipher suite. Err on the side of caution. |
| obsolete_ssl |= OBSOLETE_SSL_MASK_KEY_EXCHANGE; |
| obsolete_ssl |= OBSOLETE_SSL_MASK_CIPHER; |
| return obsolete_ssl; |
| } |
| |
| if (SSL_CIPHER_get_kx_nid(cipher) == NID_kx_rsa) { |
| obsolete_ssl |= OBSOLETE_SSL_MASK_KEY_EXCHANGE; |
| } |
| |
| if (!SSL_CIPHER_is_aead(cipher)) { |
| obsolete_ssl |= OBSOLETE_SSL_MASK_CIPHER; |
| } |
| |
| return obsolete_ssl; |
| } |
| |
| int ObsoleteSSLStatusForSignature(uint16_t signature_algorithm) { |
| switch (signature_algorithm) { |
| case SSL_SIGN_ECDSA_SHA1: |
| case SSL_SIGN_RSA_PKCS1_MD5_SHA1: |
| case SSL_SIGN_RSA_PKCS1_SHA1: |
| return OBSOLETE_SSL_MASK_SIGNATURE; |
| default: |
| return OBSOLETE_SSL_NONE; |
| } |
| } |
| |
| } // namespace |
| |
| void SSLCipherSuiteToStrings(const char** key_exchange_str, |
| const char** cipher_str, |
| const char** mac_str, |
| bool* is_aead, |
| bool* is_tls13, |
| uint16_t cipher_suite) { |
| *key_exchange_str = *cipher_str = *mac_str = "???"; |
| *is_aead = false; |
| *is_tls13 = false; |
| |
| const SSL_CIPHER* cipher = SSL_get_cipher_by_value(cipher_suite); |
| if (!cipher) |
| return; |
| |
| switch (SSL_CIPHER_get_kx_nid(cipher)) { |
| case NID_kx_any: |
| *key_exchange_str = nullptr; |
| *is_tls13 = true; |
| break; |
| case NID_kx_rsa: |
| *key_exchange_str = "RSA"; |
| break; |
| case NID_kx_ecdhe: |
| switch (SSL_CIPHER_get_auth_nid(cipher)) { |
| case NID_auth_rsa: |
| *key_exchange_str = "ECDHE_RSA"; |
| break; |
| case NID_auth_ecdsa: |
| *key_exchange_str = "ECDHE_ECDSA"; |
| break; |
| } |
| break; |
| } |
| |
| switch (SSL_CIPHER_get_cipher_nid(cipher)) { |
| case NID_aes_128_gcm: |
| *cipher_str = "AES_128_GCM"; |
| break; |
| case NID_aes_256_gcm: |
| *cipher_str = "AES_256_GCM"; |
| break; |
| case NID_chacha20_poly1305: |
| *cipher_str = "CHACHA20_POLY1305"; |
| break; |
| case NID_aes_128_cbc: |
| *cipher_str = "AES_128_CBC"; |
| break; |
| case NID_aes_256_cbc: |
| *cipher_str = "AES_256_CBC"; |
| break; |
| case NID_des_ede3_cbc: |
| *cipher_str = "3DES_EDE_CBC"; |
| break; |
| } |
| |
| if (SSL_CIPHER_is_aead(cipher)) { |
| *is_aead = true; |
| *mac_str = nullptr; |
| } else { |
| switch (SSL_CIPHER_get_digest_nid(cipher)) { |
| case NID_sha1: |
| *mac_str = "HMAC-SHA1"; |
| break; |
| case NID_sha256: |
| *mac_str = "HMAC-SHA256"; |
| break; |
| case NID_sha384: |
| *mac_str = "HMAC-SHA384"; |
| break; |
| } |
| } |
| } |
| |
| void SSLVersionToString(const char** name, int ssl_version) { |
| switch (ssl_version) { |
| case SSL_CONNECTION_VERSION_SSL2: |
| *name = "SSL 2.0"; |
| break; |
| case SSL_CONNECTION_VERSION_SSL3: |
| *name = "SSL 3.0"; |
| break; |
| case SSL_CONNECTION_VERSION_TLS1: |
| *name = "TLS 1.0"; |
| break; |
| case SSL_CONNECTION_VERSION_TLS1_1: |
| *name = "TLS 1.1"; |
| break; |
| case SSL_CONNECTION_VERSION_TLS1_2: |
| *name = "TLS 1.2"; |
| break; |
| case SSL_CONNECTION_VERSION_TLS1_3: |
| *name = "TLS 1.3"; |
| break; |
| case SSL_CONNECTION_VERSION_QUIC: |
| *name = "QUIC"; |
| break; |
| default: |
| NOTREACHED() << ssl_version; |
| *name = "???"; |
| break; |
| } |
| } |
| |
| bool ParseSSLCipherString(const std::string& cipher_string, |
| uint16_t* cipher_suite) { |
| int value = 0; |
| if (cipher_string.size() == 6 && |
| base::StartsWith(cipher_string, "0x", |
| base::CompareCase::INSENSITIVE_ASCII) && |
| base::HexStringToInt(cipher_string, &value)) { |
| *cipher_suite = static_cast<uint16_t>(value); |
| return true; |
| } |
| return false; |
| } |
| |
| int ObsoleteSSLStatus(int connection_status, uint16_t signature_algorithm) { |
| int obsolete_ssl = OBSOLETE_SSL_NONE; |
| |
| int ssl_version = SSLConnectionStatusToVersion(connection_status); |
| obsolete_ssl |= ObsoleteSSLStatusForProtocol(ssl_version); |
| |
| uint16_t cipher_suite = SSLConnectionStatusToCipherSuite(connection_status); |
| obsolete_ssl |= ObsoleteSSLStatusForCipherSuite(cipher_suite); |
| |
| obsolete_ssl |= ObsoleteSSLStatusForSignature(signature_algorithm); |
| |
| return obsolete_ssl; |
| } |
| |
| bool IsTLSCipherSuiteAllowedByHTTP2(uint16_t cipher_suite) { |
| return ObsoleteSSLStatusForCipherSuite(cipher_suite) == OBSOLETE_SSL_NONE; |
| } |
| |
| } // namespace net |