| // 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/stl_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "net/ssl/ssl_connection_status_flags.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/boringssl/src/include/openssl/ssl.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| int kObsoleteVersion = SSL_CONNECTION_VERSION_TLS1; |
| int kModernVersion = SSL_CONNECTION_VERSION_TLS1_2; |
| |
| uint16_t kModernCipherSuite = |
| 0xc02f; /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */ |
| |
| uint16_t kObsoleteCipherObsoleteKeyExchange = |
| 0x2f; /* TLS_RSA_WITH_AES_128_CBC_SHA */ |
| uint16_t kObsoleteCipherModernKeyExchange = |
| 0xc014; /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */ |
| uint16_t kModernCipherObsoleteKeyExchange = |
| 0x9c; /* TLS_RSA_WITH_AES_128_GCM_SHA256 */ |
| uint16_t kModernCipherModernKeyExchange = |
| 0xc02f; /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */ |
| |
| uint16_t kObsoleteSignature = SSL_SIGN_RSA_PKCS1_SHA1; |
| uint16_t kModernSignature = SSL_SIGN_RSA_PSS_RSAE_SHA256; |
| |
| int MakeConnectionStatus(int version, uint16_t cipher_suite) { |
| int connection_status = 0; |
| |
| SSLConnectionStatusSetVersion(version, &connection_status); |
| SSLConnectionStatusSetCipherSuite(cipher_suite, &connection_status); |
| |
| return connection_status; |
| } |
| |
| TEST(CipherSuiteNamesTest, Basic) { |
| const char *key_exchange, *cipher, *mac; |
| bool is_aead, is_tls13; |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0x000a); |
| EXPECT_STREQ("RSA", key_exchange); |
| EXPECT_STREQ("3DES_EDE_CBC", cipher); |
| EXPECT_STREQ("HMAC-SHA1", mac); |
| EXPECT_FALSE(is_aead); |
| EXPECT_FALSE(is_tls13); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0x002f); |
| EXPECT_STREQ("RSA", key_exchange); |
| EXPECT_STREQ("AES_128_CBC", cipher); |
| EXPECT_STREQ("HMAC-SHA1", mac); |
| EXPECT_FALSE(is_aead); |
| EXPECT_FALSE(is_tls13); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0xc030); |
| EXPECT_STREQ("ECDHE_RSA", key_exchange); |
| EXPECT_STREQ("AES_256_GCM", cipher); |
| EXPECT_TRUE(is_aead); |
| EXPECT_FALSE(is_tls13); |
| EXPECT_EQ(nullptr, mac); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0xcca9); |
| EXPECT_STREQ("ECDHE_ECDSA", key_exchange); |
| EXPECT_STREQ("CHACHA20_POLY1305", cipher); |
| EXPECT_TRUE(is_aead); |
| EXPECT_FALSE(is_tls13); |
| EXPECT_EQ(nullptr, mac); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0xff31); |
| EXPECT_STREQ("???", key_exchange); |
| EXPECT_STREQ("???", cipher); |
| EXPECT_STREQ("???", mac); |
| EXPECT_FALSE(is_aead); |
| EXPECT_FALSE(is_tls13); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0x1301); |
| EXPECT_STREQ("AES_128_GCM", cipher); |
| EXPECT_TRUE(is_aead); |
| EXPECT_TRUE(is_tls13); |
| EXPECT_EQ(nullptr, mac); |
| EXPECT_EQ(nullptr, key_exchange); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0x1302); |
| EXPECT_STREQ("AES_256_GCM", cipher); |
| EXPECT_TRUE(is_aead); |
| EXPECT_TRUE(is_tls13); |
| EXPECT_EQ(nullptr, mac); |
| EXPECT_EQ(nullptr, key_exchange); |
| |
| SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, |
| 0x1303); |
| EXPECT_STREQ("CHACHA20_POLY1305", cipher); |
| EXPECT_TRUE(is_aead); |
| EXPECT_TRUE(is_tls13); |
| EXPECT_EQ(nullptr, mac); |
| EXPECT_EQ(nullptr, key_exchange); |
| } |
| |
| TEST(CipherSuiteNamesTest, ParseSSLCipherString) { |
| uint16_t cipher_suite = 0; |
| EXPECT_TRUE(ParseSSLCipherString("0x0004", &cipher_suite)); |
| EXPECT_EQ(0x00004u, cipher_suite); |
| |
| EXPECT_TRUE(ParseSSLCipherString("0xBEEF", &cipher_suite)); |
| EXPECT_EQ(0xBEEFu, cipher_suite); |
| } |
| |
| TEST(CipherSuiteNamesTest, ParseSSLCipherStringFails) { |
| const char* const cipher_strings[] = { |
| "0004", |
| "0x004", |
| "0xBEEFY", |
| }; |
| |
| for (size_t i = 0; i < base::size(cipher_strings); ++i) { |
| uint16_t cipher_suite = 0; |
| EXPECT_FALSE(ParseSSLCipherString(cipher_strings[i], &cipher_suite)); |
| } |
| } |
| |
| TEST(CipherSuiteNamesTest, ObsoleteSSLStatusProtocol) { |
| // Obsolete |
| // Note all of these combinations are impossible; TLS 1.2 is necessary for |
| // kModernCipherSuite. |
| EXPECT_EQ(OBSOLETE_SSL_MASK_PROTOCOL, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_SSL2, |
| kModernCipherSuite), |
| kModernSignature)); |
| EXPECT_EQ(OBSOLETE_SSL_MASK_PROTOCOL, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_SSL3, |
| kModernCipherSuite), |
| kModernSignature)); |
| EXPECT_EQ(OBSOLETE_SSL_MASK_PROTOCOL, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_TLS1, |
| kModernCipherSuite), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_PROTOCOL, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_TLS1_1, |
| kModernCipherSuite), |
| kModernSignature)); |
| |
| // Modern |
| EXPECT_EQ( |
| OBSOLETE_SSL_NONE, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_TLS1_2, |
| kModernCipherSuite), |
| kModernSignature)); |
| EXPECT_EQ(OBSOLETE_SSL_NONE, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_QUIC, |
| kModernCipherSuite), |
| kModernSignature)); |
| } |
| |
| TEST(CipherSuiteNamesTest, ObsoleteSSLStatusProtocolAndCipherSuite) { |
| // Cartesian combos |
| // As above, some of these combinations can't happen in practice. |
| EXPECT_EQ(OBSOLETE_SSL_MASK_PROTOCOL | OBSOLETE_SSL_MASK_KEY_EXCHANGE | |
| OBSOLETE_SSL_MASK_CIPHER | OBSOLETE_SSL_MASK_SIGNATURE, |
| ObsoleteSSLStatus( |
| MakeConnectionStatus(kObsoleteVersion, |
| kObsoleteCipherObsoleteKeyExchange), |
| kObsoleteSignature)); |
| EXPECT_EQ(OBSOLETE_SSL_MASK_PROTOCOL | OBSOLETE_SSL_MASK_KEY_EXCHANGE | |
| OBSOLETE_SSL_MASK_CIPHER, |
| ObsoleteSSLStatus( |
| MakeConnectionStatus(kObsoleteVersion, |
| kObsoleteCipherObsoleteKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_PROTOCOL | OBSOLETE_SSL_MASK_KEY_EXCHANGE, |
| ObsoleteSSLStatus(MakeConnectionStatus(kObsoleteVersion, |
| kModernCipherObsoleteKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_PROTOCOL | OBSOLETE_SSL_MASK_CIPHER, |
| ObsoleteSSLStatus(MakeConnectionStatus(kObsoleteVersion, |
| kObsoleteCipherModernKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_PROTOCOL, |
| ObsoleteSSLStatus(MakeConnectionStatus(kObsoleteVersion, |
| kModernCipherModernKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_KEY_EXCHANGE | OBSOLETE_SSL_MASK_CIPHER, |
| ObsoleteSSLStatus(MakeConnectionStatus( |
| kModernVersion, kObsoleteCipherObsoleteKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_KEY_EXCHANGE, |
| ObsoleteSSLStatus(MakeConnectionStatus(kModernVersion, |
| kModernCipherObsoleteKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_CIPHER, |
| ObsoleteSSLStatus(MakeConnectionStatus(kModernVersion, |
| kObsoleteCipherModernKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_NONE, |
| ObsoleteSSLStatus( |
| MakeConnectionStatus(kModernVersion, kModernCipherModernKeyExchange), |
| kModernSignature)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_NONE, |
| ObsoleteSSLStatus(MakeConnectionStatus(SSL_CONNECTION_VERSION_TLS1_3, |
| 0x1301 /* AES_128_GCM_SHA256 */), |
| kModernSignature)); |
| |
| // Don't flag the signature as obsolete if not present. It may be an old cache |
| // entry or a key exchange that doesn't involve a signature. (Though, in the |
| // latter case, we would always flag a bad key exchange.) |
| EXPECT_EQ( |
| OBSOLETE_SSL_NONE, |
| ObsoleteSSLStatus( |
| MakeConnectionStatus(kModernVersion, kModernCipherModernKeyExchange), |
| 0)); |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_KEY_EXCHANGE, |
| ObsoleteSSLStatus(MakeConnectionStatus(kModernVersion, |
| kModernCipherObsoleteKeyExchange), |
| 0)); |
| |
| // Flag obsolete signatures. |
| EXPECT_EQ( |
| OBSOLETE_SSL_MASK_SIGNATURE, |
| ObsoleteSSLStatus( |
| MakeConnectionStatus(kModernVersion, kModernCipherModernKeyExchange), |
| kObsoleteSignature)); |
| } |
| |
| TEST(CipherSuiteNamesTest, HTTP2CipherSuites) { |
| // Picked some random cipher suites. |
| EXPECT_FALSE( |
| IsTLSCipherSuiteAllowedByHTTP2(0x0 /* TLS_NULL_WITH_NULL_NULL */)); |
| EXPECT_FALSE(IsTLSCipherSuiteAllowedByHTTP2( |
| 0xc014 /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */)); |
| EXPECT_FALSE(IsTLSCipherSuiteAllowedByHTTP2( |
| 0x9c /* TLS_RSA_WITH_AES_128_GCM_SHA256 */)); |
| |
| // Non-existent cipher suite. |
| EXPECT_FALSE(IsTLSCipherSuiteAllowedByHTTP2(0xffff)) << "Doesn't exist!"; |
| |
| // HTTP/2-compatible ones. |
| EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2( |
| 0xc02f /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */)); |
| EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2( |
| 0xcca8 /* ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */)); |
| EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2( |
| 0xcca9 /* ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */)); |
| EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(0x1301 /* AES_128_GCM_SHA256 */)); |
| EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(0x1302 /* AES_256_GCM_SHA384 */)); |
| EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(0x1303 /* CHACHA20_POLY1305 */)); |
| } |
| |
| } // anonymous namespace |
| |
| } // namespace net |