// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC // ssl_test_ticket_aead_failure_mode enumerates the possible ways in which the // test |SSL_TICKET_AEAD_METHOD| can fail. #include #include "../crypto/test/file_util.h" #include "../crypto/test/test_util.h" #include "internal.h" #include "ssl_common_test.h" BSSL_NAMESPACE_BEGIN struct ExpectedCipher { unsigned long id; int in_group_flag; }; struct CipherTest { // The rule string to apply. const char *rule; // The list of expected ciphers, in order. std::vector expected; // True if this cipher list should fail in strict mode. bool strict_fail; }; struct CurveTest { // The rule string to apply. const char *rule; // The list of expected curves, in order. std::vector expected; }; static const CipherTest kCipherTests[] = { // Selecting individual ciphers should work. { "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // + reorders selected ciphers to the end, keeping their relative order. { "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256:" "+aRSA", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // ! banishes ciphers from future selections. { "!aRSA:" "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // Multiple masks can be ANDed in a single rule. { "kRSA+AESGCM+AES128", { {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // - removes selected ciphers, but preserves their order for future // selections. Select AES_128_GCM, but order the key exchanges RSA, // ECDHE_RSA. { "ALL:-kECDHE:" "-kRSA:-ALL:" "AESGCM+AES128+aRSA", { {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // Unknown selectors are no-ops, except in strict mode. { "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256:" "BOGUS1", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, true, }, // Unknown selectors are no-ops, except in strict mode. { "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256:" "-BOGUS2:+BOGUS3:!BOGUS4", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, true, }, // Square brackets specify equi-preference groups. { "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:" "[ECDHE-RSA-CHACHA20-POLY1305]:" "ECDHE-RSA-AES128-GCM-SHA256", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // Standard names may be used instead of OpenSSL names. { "[TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256|" "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256]:" "[TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256]:" "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", { {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // @STRENGTH performs a stable strength-sort of the selected ciphers and // only the selected ciphers. { // To simplify things, banish all but {ECDHE_RSA,RSA} x // {CHACHA20,AES_256_CBC,AES_128_CBC} x SHA1. "!AESGCM:!3DES:" // Order some ciphers backwards by strength. "ALL:-CHACHA20:-AES256:-AES128:-ALL:" // Select ECDHE ones and sort them by strength. Ties should resolve // based on the order above. "kECDHE:@STRENGTH:-ALL:" // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted // by strength. Then RSA, backwards by strength. "aRSA", { {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, 0}, {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, {TLS1_CK_RSA_WITH_AES_128_SHA256, 0}, {TLS1_CK_RSA_WITH_AES_256_SHA, 0}, }, false, }, // Additional masks after @STRENGTH get silently discarded. // // TODO(davidben): Make this an error. If not silently discarded, they get // interpreted as + opcodes which are very different. { "ECDHE-RSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES256-GCM-SHA384:" "@STRENGTH+AES256", { {TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, { "ECDHE-RSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES256-GCM-SHA384:" "@STRENGTH+AES256:" "ECDHE-RSA-CHACHA20-POLY1305", { {TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0}, }, false, }, // Exact ciphers may not be used in multi-part rules; they are treated // as unknown aliases. { "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256:" "!ECDHE-RSA-AES128-GCM-SHA256+RSA:" "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256", { {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, true, }, // SSLv3 matches everything that existed before TLS 1.2. { "AES128-SHA:AES128-SHA256:ECDHE-RSA-AES128-GCM-SHA256:!SSLv3", { {TLS1_CK_RSA_WITH_AES_128_SHA256, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // TLSv1.2 matches everything added in TLS 1.2. { "AES128-SHA:AES128-SHA256:ECDHE-RSA-AES128-GCM-SHA256:!TLSv1.2", { {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, }, false, }, // The two directives have no intersection. But each component is valid, so // even in strict mode it is accepted. { "AES128-SHA:ECDHE-RSA-AES128-GCM-SHA256:!TLSv1.2+SSLv3", { {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, }, false, }, // Spaces, semi-colons and commas are separators. { "AES128-SHA: ECDHE-RSA-AES128-GCM-SHA256 AES256-SHA " ",ECDHE-ECDSA-AES128-GCM-SHA256 ; AES128-GCM-SHA256", { {TLS1_CK_RSA_WITH_AES_128_SHA, 0}, {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_RSA_WITH_AES_256_SHA, 0}, {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0}, }, // …but not in strict mode. true, }, }; // In kTLSv13RuleOnly, |rule| of each CipherTest can only match TLSv1.3 ciphers. // e.g. kTLSv13RuleOnly does not have rule "AESGCM+AES128", which can match // some TLSv1.2 ciphers. static const CipherTest kTLSv13RuleOnly[] = { // Selecting individual ciphers should work. { "TLS_AES_256_GCM_SHA384:" "TLS_CHACHA20_POLY1305_SHA256:" "TLS_AES_128_GCM_SHA256", { {TLS1_CK_AES_256_GCM_SHA384, 0}, {TLS1_CK_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_AES_128_GCM_SHA256, 0}, }, false, }, // + reorders selected ciphers to the end, keeping their relative order. { "TLS_AES_256_GCM_SHA384:" "TLS_CHACHA20_POLY1305_SHA256:" "TLS_AES_128_GCM_SHA256:" "+AES", { {TLS1_CK_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_AES_256_GCM_SHA384, 0}, {TLS1_CK_AES_128_GCM_SHA256, 0}, }, false, }, // ! banishes ciphers from future selections. { "!CHACHA20:" "TLS_AES_256_GCM_SHA384:" "TLS_CHACHA20_POLY1305_SHA256:" "TLS_AES_128_GCM_SHA256:" "TLS_CHACHA20_POLY1305_SHA256", { {TLS1_CK_AES_256_GCM_SHA384, 0}, {TLS1_CK_AES_128_GCM_SHA256, 0}, }, false, }, // Square brackets specify equi-preference groups. { "[TLS_AES_128_GCM_SHA256|TLS_AES_256_GCM_SHA384]:" "TLS_CHACHA20_POLY1305_SHA256", { {TLS1_CK_AES_128_GCM_SHA256, 1}, {TLS1_CK_AES_256_GCM_SHA384, 0}, {TLS1_CK_CHACHA20_POLY1305_SHA256, 0}, }, false, }, // Spaces, semi-colons and commas are separators. { "TLS_AES_256_GCM_SHA384 ; " "TLS_CHACHA20_POLY1305_SHA256 , " "TLS_AES_128_GCM_SHA256", { {TLS1_CK_AES_256_GCM_SHA384, 0}, {TLS1_CK_CHACHA20_POLY1305_SHA256, 0}, {TLS1_CK_AES_128_GCM_SHA256, 0}, }, false, }, }; // Besides kTLSv13RuleOnly, additional rules can match TLSv1.3 ciphers. static const CipherTest kTLSv13CipherTests[] = { // Multiple masks can be ANDed in a single rule. { "AESGCM+AES128", { {TLS1_CK_AES_128_GCM_SHA256, 0}, }, false, }, // - removes selected ciphers, but preserves their order for future // selections. Select AES_128_GCM, but order the key exchanges RSA, // ECDHE_RSA. { "ALL:-AES", { {TLS1_CK_CHACHA20_POLY1305_SHA256, 0}, }, false, }, // Unknown selectors or TLSv1.2 ciphers are no-ops. { "TLS_CHACHA20_POLY1305_SHA256:" "ECDHE-RSA-CHACHA20-POLY1305:" "BOGUS1", { {TLS1_CK_CHACHA20_POLY1305_SHA256, 0}, }, true, }, }; static const char *kBadRules[] = { // Invalid brackets. "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256", "RSA]", "[[RSA]]", // Operators inside brackets. "[+RSA]", // Unknown directive. "@BOGUS", "BOGUS", // COMPLEMENTOFDEFAULT is empty. "COMPLEMENTOFDEFAULT", // Invalid command. "?BAR", // Special operators are not allowed if equi-preference groups are used. "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO", "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO", "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO", "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH", // Opcode supplied, but missing selector. "+", // Spaces are forbidden in equal-preference groups. "[AES128-SHA | AES128-SHA256]", }; static const char *kMustNotIncludeNull[] = { "ALL", "DEFAULT", "HIGH", "FIPS", "SHA", "SHA1", "RSA", "SSLv3", "TLSv1", "TLSv1.2", }; static const char *kTLSv13MustNotIncludeNull[] = { "ALL", "DEFAULT", "HIGH", "FIPS", }; static const char *kMustNotInclude3DES[] = { "ALL", "DEFAULT", "HIGH", "FIPS", "SSLv3", "TLSv1", "TLSv1.2", }; static const CurveTest kCurveTests[] = { { "P-256", {SSL_GROUP_SECP256R1}, }, { "P-256:P-384:P-521:X25519", { SSL_GROUP_SECP256R1, SSL_GROUP_SECP384R1, SSL_GROUP_SECP521R1, SSL_GROUP_X25519, }, }, { "prime256v1:secp384r1:secp521r1:x25519", { SSL_GROUP_SECP256R1, SSL_GROUP_SECP384R1, SSL_GROUP_SECP521R1, SSL_GROUP_X25519, }, }, { "SecP256r1MLKEM768:prime256v1:secp384r1:secp521r1:x25519", { SSL_GROUP_SECP256R1_MLKEM768, SSL_GROUP_SECP256R1, SSL_GROUP_SECP384R1, SSL_GROUP_SECP521R1, SSL_GROUP_X25519, }, }, { "X25519MLKEM768:prime256v1:secp384r1", { SSL_GROUP_X25519_MLKEM768, SSL_GROUP_SECP256R1, SSL_GROUP_SECP384R1, }, }, { "X25519:X25519MLKEM768", { SSL_GROUP_X25519, SSL_GROUP_X25519_MLKEM768, }, }, { "X25519:SecP256r1MLKEM768:prime256v1", { SSL_GROUP_X25519, SSL_GROUP_SECP256R1_MLKEM768, SSL_GROUP_SECP256R1, }, }, { "SecP384r1MLKEM1024:X25519MLKEM768:SecP256r1MLKEM768", { SSL_GROUP_SECP384R1_MLKEM1024, SSL_GROUP_X25519_MLKEM768, SSL_GROUP_SECP256R1_MLKEM768, }, }, { "MLKEM512:MLKEM768:MLKEM1024", { SSL_GROUP_MLKEM512, SSL_GROUP_MLKEM768, SSL_GROUP_MLKEM1024, }, }, { "ML-KEM-512:ML-KEM-768:ML-KEM-1024", { SSL_GROUP_MLKEM512, SSL_GROUP_MLKEM768, SSL_GROUP_MLKEM1024, }, }, }; static const char *kBadCurvesLists[] = { "", ":", "::", "P-256::X25519", "RSA:P-256", "P-256:RSA", "X25519:P-256:", ":X25519:P-256", "mlkem768", "x25519_mlkem768:prime256v1", }; static STACK_OF(SSL_CIPHER) *tls13_ciphers(const SSL_CTX *ctx) { return ctx->tls13_cipher_list->ciphers.get(); } static std::string CipherListToString(SSL_CTX *ctx, bool tlsv13_ciphers) { bool in_group = false; std::string ret; const STACK_OF(SSL_CIPHER) *ciphers = tlsv13_ciphers ? tls13_ciphers(ctx) : SSL_CTX_get_ciphers(ctx); for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i); if (!in_group && SSL_CTX_cipher_in_group(ctx, i)) { ret += "\t[\n"; in_group = true; } ret += "\t"; if (in_group) { ret += " "; } ret += SSL_CIPHER_get_name(cipher); ret += "\n"; if (in_group && !SSL_CTX_cipher_in_group(ctx, i)) { ret += "\t]\n"; in_group = false; } } return ret; } static bool CipherListsEqual(SSL_CTX *ctx, const std::vector &expected, bool tlsv13_ciphers) { STACK_OF(SSL_CIPHER) *ciphers = tlsv13_ciphers ? tls13_ciphers(ctx) : SSL_CTX_get_ciphers(ctx); if (sk_SSL_CIPHER_num(ciphers) != expected.size()) { return false; } for (size_t i = 0; i < expected.size(); i++) { const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i); if (expected[i].id != SSL_CIPHER_get_id(cipher) || expected[i].in_group_flag != !!SSL_CTX_cipher_in_group(ctx, i)) { return false; } } return true; } TEST(SSLTest, CipherRules) { for (const CipherTest &t : kCipherTests) { SCOPED_TRACE(t.rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); // We configure default TLS 1.3 ciphersuites in |SSL_CTX| which pollute // |ctx->cipher_list|. Set it to an empty list so we can test TLS 1.2 // configurations. ASSERT_TRUE(SSL_CTX_set_ciphersuites(ctx.get(), "")); // Test lax mode. ASSERT_TRUE(SSL_CTX_set_cipher_list(ctx.get(), t.rule)); EXPECT_TRUE( CipherListsEqual(ctx.get(), t.expected, false /* not TLSv1.3 only */)) << "Cipher rule evaluated to:\n" << CipherListToString(ctx.get(), false /* not TLSv1.3 only */); // Test strict mode. if (t.strict_fail) { EXPECT_FALSE(SSL_CTX_set_strict_cipher_list(ctx.get(), t.rule)); } else { ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), t.rule)); EXPECT_TRUE( CipherListsEqual(ctx.get(), t.expected, false /* not TLSv1.3 only */)) << "Cipher rule evaluated to:\n" << CipherListToString(ctx.get(), false /* not TLSv1.3 only */); } } for (const char *rule : kBadRules) { SCOPED_TRACE(rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); EXPECT_FALSE(SSL_CTX_set_cipher_list(ctx.get(), rule)); ERR_clear_error(); } // kTLSv13RuleOnly are valid test cases for |SSL_CTX_set_ciphersuites|, // which configures only TLSv1.3 ciphers. // |SSL_CTX_set_cipher_list| only supports TLSv1.2 and below ciphers // configuration. Accordingly, kTLSv13RuleOnly result in // |SSL_R_NO_CIPHER_MATCH|. for (const CipherTest &t : kTLSv13RuleOnly) { SCOPED_TRACE(t.rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); // We configure default TLS 1.3 ciphersuites in |SSL_CTX| which pollute // |ctx->cipher_list|. Set it to an empty list so we can test TLS 1.2 // configurations. ASSERT_TRUE(SSL_CTX_set_ciphersuites(ctx.get(), "")); EXPECT_FALSE(SSL_CTX_set_cipher_list(ctx.get(), t.rule)); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_CIPHER_MATCH); ERR_clear_error(); } for (const char *rule : kMustNotIncludeNull) { SCOPED_TRACE(rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), rule)); for (const SSL_CIPHER *cipher : SSL_CTX_get_ciphers(ctx.get())) { EXPECT_NE(NID_undef, SSL_CIPHER_get_cipher_nid(cipher)); } } for (const char *rule : kMustNotInclude3DES) { SCOPED_TRACE(rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), rule)); for (const SSL_CIPHER *cipher : SSL_CTX_get_ciphers(ctx.get())) { EXPECT_NE(NID_des_ede3_cbc, SSL_CIPHER_get_cipher_nid(cipher)); } } } static std::vector combine_tests(const CipherTest *c1, size_t size_1, const CipherTest *c2, size_t size_2) { std::vector ret(size_1 + size_2); size_t j = 0; for (size_t i = 0; i < size_1; i++) { ret[j++] = c1[i]; } for (size_t i = 0; i < size_2; i++) { ret[j++] = c2[i]; } return ret; } TEST(SSLTest, TLSv13CipherRules) { std::vector cipherRules = combine_tests(kTLSv13RuleOnly, OPENSSL_ARRAY_SIZE(kTLSv13RuleOnly), kTLSv13CipherTests, OPENSSL_ARRAY_SIZE(kTLSv13CipherTests)); for (const CipherTest &t : cipherRules) { SCOPED_TRACE(t.rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); bssl::UniquePtr ssl(SSL_new(ctx.get())); ASSERT_TRUE(ssl); // Test lax mode. ASSERT_TRUE(SSL_CTX_set_ciphersuites(ctx.get(), t.rule)); ASSERT_TRUE(SSL_set_ciphersuites(ssl.get(), t.rule)); EXPECT_TRUE( CipherListsEqual(ctx.get(), t.expected, true /* TLSv1.3 only */)) << "Cipher rule evaluated to:\n" << CipherListToString(ctx.get(), true /* TLSv1.3 only */); // TODO: add |SSL_CTX_set_strict_ciphersuites| and test strict mode. } for (const char *rule : kBadRules) { SCOPED_TRACE(rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); bssl::UniquePtr ssl(SSL_new(ctx.get())); ASSERT_TRUE(ssl); EXPECT_FALSE(SSL_CTX_set_ciphersuites(ctx.get(), rule)); EXPECT_FALSE(SSL_set_ciphersuites(ssl.get(), rule)); ERR_clear_error(); } for (const char *rule : kTLSv13MustNotIncludeNull) { SCOPED_TRACE(rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); bssl::UniquePtr ssl(SSL_new(ctx.get())); ASSERT_TRUE(ssl); ASSERT_TRUE(SSL_CTX_set_ciphersuites(ctx.get(), rule)); ASSERT_TRUE(SSL_set_ciphersuites(ssl.get(), rule)); // Currenly, only three TLSv1.3 ciphers are supported. EXPECT_EQ(3u, sk_SSL_CIPHER_num(tls13_ciphers(ctx.get()))); for (const SSL_CIPHER *cipher : tls13_ciphers(ctx.get())) { EXPECT_NE(NID_undef, SSL_CIPHER_get_cipher_nid(cipher)); } } // kCipherTests are valid test cases for |SSL_CTX_set_cipher_list|, // which configures only TLSv1.2 and below ciphers. // |SSL_CTX_set_ciphersuites| only supports TLSv1.3 ciphers configuration. // Accordingly, kCipherTests result in |SSL_R_NO_CIPHER_MATCH|. // If kCipherTests starts to include rules that can match TLSv1.3 ciphers, // kCipherTests should get splitted. for (const CipherTest &t : kCipherTests) { SCOPED_TRACE(t.rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); bssl::UniquePtr ssl(SSL_new(ctx.get())); ASSERT_TRUE(ssl); EXPECT_FALSE(SSL_CTX_set_ciphersuites(ctx.get(), t.rule)); EXPECT_FALSE(SSL_set_ciphersuites(ssl.get(), t.rule)); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_CIPHER_MATCH); ERR_clear_error(); } } TEST(SSLTest, CurveRules) { for (const CurveTest &t : kCurveTests) { SCOPED_TRACE(t.rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); ASSERT_TRUE(SSL_CTX_set1_groups_list(ctx.get(), t.rule)); ASSERT_EQ(t.expected.size(), ctx->supported_group_list.size()); for (size_t i = 0; i < t.expected.size(); i++) { EXPECT_EQ(t.expected[i], ctx->supported_group_list[i]); } } for (const char *rule : kBadCurvesLists) { SCOPED_TRACE(rule); bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(ctx); EXPECT_FALSE(SSL_CTX_set1_groups_list(ctx.get(), rule)); ERR_clear_error(); } } static void ExpectDefaultVersion(uint16_t min_version, uint16_t max_version, const SSL_METHOD *(*method)(void)) { bssl::UniquePtr ctx(SSL_CTX_new(method())); ASSERT_TRUE(ctx); bssl::UniquePtr ssl(SSL_new(ctx.get())); ASSERT_TRUE(ssl); EXPECT_EQ(0, SSL_CTX_get_min_proto_version(ctx.get())); EXPECT_EQ(0, SSL_CTX_get_max_proto_version(ctx.get())); EXPECT_EQ(0, SSL_get_min_proto_version(ssl.get())); EXPECT_EQ(0, SSL_get_max_proto_version(ssl.get())); EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), min_version)); EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), max_version)); EXPECT_EQ(min_version, SSL_CTX_get_min_proto_version(ctx.get())); EXPECT_EQ(max_version, SSL_CTX_get_max_proto_version(ctx.get())); EXPECT_TRUE(SSL_set_min_proto_version(ssl.get(), min_version)); EXPECT_TRUE(SSL_set_max_proto_version(ssl.get(), max_version)); EXPECT_EQ(min_version, SSL_get_min_proto_version(ssl.get())); EXPECT_EQ(max_version, SSL_get_max_proto_version(ssl.get())); } TEST(SSLTest, DefaultVersion) { ExpectDefaultVersion(TLS1_VERSION, TLS1_3_VERSION, &TLS_method); ExpectDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method); ExpectDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method); ExpectDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method); ExpectDefaultVersion(DTLS1_VERSION, DTLS1_2_VERSION, &DTLS_method); ExpectDefaultVersion(DTLS1_VERSION, DTLS1_VERSION, &DTLSv1_method); ExpectDefaultVersion(DTLS1_2_VERSION, DTLS1_2_VERSION, &DTLSv1_2_method); } TEST(SSLTest, CipherProperties) { static const struct { int id; const char *standard_name; int cipher_nid; int digest_nid; int kx_nid; int auth_nid; int prf_nid; } kTests[] = { { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", NID_des_ede3_cbc, NID_sha1, NID_kx_rsa, NID_auth_rsa, NID_md5_sha1, }, { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA", NID_aes_128_cbc, NID_sha1, NID_kx_rsa, NID_auth_rsa, NID_md5_sha1, }, { TLS1_CK_RSA_WITH_AES_128_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256", NID_aes_128_cbc, NID_sha256, NID_kx_rsa, NID_auth_rsa, NID_sha256, }, { TLS1_CK_PSK_WITH_AES_256_CBC_SHA, "TLS_PSK_WITH_AES_256_CBC_SHA", NID_aes_256_cbc, NID_sha1, NID_kx_psk, NID_auth_psk, NID_md5_sha1, }, { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", NID_aes_128_cbc, NID_sha1, NID_kx_ecdhe, NID_auth_rsa, NID_md5_sha1, }, { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", NID_aes_128_cbc, NID_sha256, NID_kx_ecdhe, NID_auth_rsa, NID_sha256, }, { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", NID_aes_256_cbc, NID_sha1, NID_kx_ecdhe, NID_auth_rsa, NID_md5_sha1, }, { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", NID_aes_128_gcm, NID_undef, NID_kx_ecdhe, NID_auth_rsa, NID_sha256, }, { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", NID_aes_128_gcm, NID_undef, NID_kx_ecdhe, NID_auth_ecdsa, NID_sha256, }, { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", NID_aes_256_gcm, NID_undef, NID_kx_ecdhe, NID_auth_ecdsa, NID_sha384, }, { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", NID_aes_128_cbc, NID_sha1, NID_kx_ecdhe, NID_auth_psk, NID_md5_sha1, }, { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", NID_chacha20_poly1305, NID_undef, NID_kx_ecdhe, NID_auth_rsa, NID_sha256, }, { TLS1_3_CK_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384", NID_aes_256_gcm, NID_undef, NID_kx_any, NID_auth_any, NID_sha384, }, { TLS1_3_CK_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256", NID_aes_128_gcm, NID_undef, NID_kx_any, NID_auth_any, NID_sha256, }, { TLS1_3_CK_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256", NID_chacha20_poly1305, NID_undef, NID_kx_any, NID_auth_any, NID_sha256, }, }; for (const auto &t : kTests) { SCOPED_TRACE(t.standard_name); const SSL_CIPHER *cipher = SSL_get_cipher_by_value(t.id & 0xffff); ASSERT_TRUE(cipher); EXPECT_STREQ(t.standard_name, SSL_CIPHER_standard_name(cipher)); EXPECT_EQ(t.cipher_nid, SSL_CIPHER_get_cipher_nid(cipher)); EXPECT_EQ(t.digest_nid, SSL_CIPHER_get_digest_nid(cipher)); EXPECT_EQ(t.kx_nid, SSL_CIPHER_get_kx_nid(cipher)); EXPECT_EQ(t.auth_nid, SSL_CIPHER_get_auth_nid(cipher)); const EVP_MD *md = SSL_CIPHER_get_handshake_digest(cipher); ASSERT_TRUE(md); EXPECT_EQ(t.prf_nid, EVP_MD_nid(md)); EXPECT_EQ(t.prf_nid, SSL_CIPHER_get_prf_nid(cipher)); } } // Correct ID and name #define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") #define TLS13_CHACHA20_POLY1305_SHA256_BYTES ((const unsigned char *)"\x13\x03") // Invalid ID #define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x13") TEST(SSLTest, FindingCipher) { bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); // Configure only TLS 1.3. ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); bssl::UniquePtr client, server; ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); SCOPED_TRACE("TLS_AES_128_GCM_SHA256"); const SSL_CIPHER *cipher1 = SSL_CIPHER_find(server.get(), TLS13_AES_128_GCM_SHA256_BYTES); ASSERT_TRUE(cipher1); EXPECT_STREQ("TLS_AES_128_GCM_SHA256", SSL_CIPHER_standard_name(cipher1)); SCOPED_TRACE("TLS_CHACHA20_POLY1305_SHA256"); const SSL_CIPHER *cipher2 = SSL_CIPHER_find(server.get(), TLS13_CHACHA20_POLY1305_SHA256_BYTES); ASSERT_TRUE(cipher2); EXPECT_STREQ("TLS_CHACHA20_POLY1305_SHA256", SSL_CIPHER_standard_name(cipher2)); SCOPED_TRACE("TLS_AES_256_GCM_SHA384"); const SSL_CIPHER *cipher3 = SSL_CIPHER_find(client.get(), TLS13_AES_256_GCM_SHA384_BYTES); ASSERT_FALSE(cipher3); } TEST(SSLTest, CheckSSLCipherInheritance) { // This configures SSL_CTX objects with default TLS 1.2 and 1.3 ciphersuites bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE( SSL_CTX_set_ciphersuites(client_ctx.get(), "TLS_AES_128_GCM_SHA256")); ASSERT_TRUE( SSL_CTX_set_ciphersuites(server_ctx.get(), "TLS_AES_128_GCM_SHA256")); ASSERT_TRUE(SSL_CTX_set_cipher_list(client_ctx.get(), "TLS_RSA_WITH_AES_128_CBC_SHA")); ASSERT_TRUE(SSL_CTX_set_cipher_list(server_ctx.get(), "TLS_RSA_WITH_AES_128_CBC_SHA")); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); // Modify CTX ciphersuites ASSERT_TRUE( SSL_CTX_set_ciphersuites(client_ctx.get(), "TLS_AES_256_GCM_SHA384")); ASSERT_TRUE( SSL_CTX_set_ciphersuites(server_ctx.get(), "TLS_AES_256_GCM_SHA384")); ASSERT_TRUE(SSL_CTX_set_cipher_list(client_ctx.get(), "TLS_RSA_WITH_AES_256_CBC_SHA")); ASSERT_TRUE(SSL_CTX_set_cipher_list(server_ctx.get(), "TLS_RSA_WITH_AES_256_CBC_SHA")); // Ensure SSL object inherits initial CTX cipher suites STACK_OF(SSL_CIPHER) *client_ciphers = SSL_get_ciphers(client.get()); STACK_OF(SSL_CIPHER) *server_ciphers = SSL_get_ciphers(server.get()); ASSERT_TRUE(client_ciphers); ASSERT_TRUE(server_ciphers); ASSERT_EQ(sk_SSL_CIPHER_num(client_ciphers), 2u); ASSERT_EQ(sk_SSL_CIPHER_num(server_ciphers), 2u); const SSL_CIPHER *tls13_cipher = SSL_get_cipher_by_value(TLS1_3_CK_AES_128_GCM_SHA256 & 0xFFFF); const SSL_CIPHER *tls12_cipher = SSL_get_cipher_by_value(TLS1_CK_RSA_WITH_AES_128_SHA & 0xFFFF); ASSERT_TRUE(tls13_cipher); ASSERT_TRUE(tls12_cipher); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, tls12_cipher)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, tls13_cipher)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, tls12_cipher)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, tls13_cipher)); SSL_set_shed_handshake_config(client.get(), 1); SSL_set_shed_handshake_config(server.get(), 1); ASSERT_TRUE(CompleteHandshakes(client.get(), server.get())); // Ensure we fall back to ctx once config is shed client_ciphers = SSL_get_ciphers(client.get()); server_ciphers = SSL_get_ciphers(server.get()); tls13_cipher = SSL_get_cipher_by_value(TLS1_3_CK_AES_256_GCM_SHA384 & 0xFFFF); tls12_cipher = SSL_get_cipher_by_value(TLS1_CK_RSA_WITH_AES_256_SHA & 0xFFFF); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, tls13_cipher)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, tls12_cipher)); } TEST(SSLTest, SSLGetCiphersReturnsTLS13Default) { bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); // Configure only TLS 1.3. ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION)); bssl::UniquePtr client, server; // Have to ensure config is not shed per current implementation of // SSL_get_ciphers. ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), server_ctx.get(), ClientConfig(), false)); // Ensure default TLS 1.3 Ciphersuites are present const SSL_CIPHER *cipher1 = SSL_get_cipher_by_value(TLS1_3_CK_AES_128_GCM_SHA256 & 0xFFFF); ASSERT_TRUE(cipher1); const SSL_CIPHER *cipher2 = SSL_get_cipher_by_value(TLS1_3_CK_AES_256_GCM_SHA384 & 0xFFFF); ASSERT_TRUE(cipher2); const SSL_CIPHER *cipher3 = SSL_get_cipher_by_value(TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xFFFF); ASSERT_TRUE(cipher3); STACK_OF(SSL_CIPHER) *client_ciphers = SSL_get_ciphers(client.get()); STACK_OF(SSL_CIPHER) *server_ciphers = SSL_get_ciphers(server.get()); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, cipher1)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, cipher2)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, cipher3)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, cipher1)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, cipher2)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, cipher3)); } TEST(SSLTest, TLS13ConfigCiphers) { // This configures SSL_CTX objects with default TLS 1.2 and 1.3 ciphersuites bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION)); // Restrict TLS 1.3 ciphersuite ASSERT_TRUE(SSL_CTX_set_ciphersuites( client_ctx.get(), "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384")); ASSERT_TRUE(SSL_CTX_set_ciphersuites( server_ctx.get(), "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384")); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); // Modify ciphersuites on the SSL object, this modifies ssl->config ASSERT_TRUE(SSL_set_ciphersuites(client.get(), "TLS_AES_256_GCM_SHA384")); ASSERT_TRUE(SSL_set_ciphersuites(server.get(), "TLS_AES_128_GCM_SHA256")); // Handshake should fail as config objects have no shared cipher. ASSERT_FALSE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_SHARED_CIPHER); bssl::UniquePtr client2, server2; ASSERT_TRUE(CreateClientAndServer(&client2, &server2, client_ctx.get(), server_ctx.get())); // Modify ciphersuites on the SSL object, this modifies ssl->config ASSERT_TRUE( SSL_set_ciphersuites(client2.get(), "TLS_CHACHA20_POLY1305_SHA256")); ASSERT_TRUE( SSL_set_ciphersuites(server2.get(), "TLS_CHACHA20_POLY1305_SHA256")); ASSERT_TRUE(CompleteHandshakes(client2.get(), server2.get())); ASSERT_EQ(SSL_CIPHER_get_id(SSL_get_current_cipher(client2.get())), (uint32_t)TLS1_3_CK_CHACHA20_POLY1305_SHA256); ASSERT_EQ(SSL_CIPHER_get_id(SSL_get_current_cipher(server2.get())), (uint32_t)TLS1_3_CK_CHACHA20_POLY1305_SHA256); } TEST(SSLTest, TLS13ConfigCtxInteraction) { // This configures SSL_CTX objects with default TLS 1.2 and 1.3 ciphersuites bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION)); // Restrict TLS 1.3 ciphersuite on the SSL_CTX objects ASSERT_TRUE( SSL_CTX_set_ciphersuites(client_ctx.get(), "TLS_AES_128_GCM_SHA256")); ASSERT_TRUE( SSL_CTX_set_ciphersuites(server_ctx.get(), "TLS_AES_128_GCM_SHA256")); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); // Modify TLS 1.3 ciphersuites for client's SSL object, but not server ASSERT_TRUE(SSL_set_ciphersuites(client.get(), "TLS_AES_256_GCM_SHA384")); // Handshake should fail as client SSL config and server CTX objects have no // shared TLS 1.3 cipher. ASSERT_FALSE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_SHARED_CIPHER); ERR_clear_error(); bssl::UniquePtr client2, server2; ASSERT_TRUE(CreateClientAndServer(&client2, &server2, client_ctx.get(), server_ctx.get())); // Modify TLS 1.3 ciphersuites for server2 SSL object, but not client ASSERT_TRUE(SSL_set_ciphersuites(server2.get(), "TLS_AES_256_GCM_SHA384")); // Handshake should fail as server SSL config and client CTX objects have no // shared TLS 1.3 cipher. ASSERT_FALSE(CompleteHandshakes(client2.get(), server2.get())); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_SHARED_CIPHER); } TEST(SSLTest, TLS12ConfigCiphers) { // This configures SSL_CTX objects with default TLS 1.2 and 1.3 ciphersuites bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_2_VERSION)); // Restrict TLS 1.2 ciphersuite ASSERT_TRUE(SSL_CTX_set_cipher_list( client_ctx.get(), "TLS_RSA_WITH_AES_256_CBC_SHA:TLS_RSA_WITH_AES_256_GCM_SHA384")); ASSERT_TRUE(SSL_CTX_set_cipher_list( server_ctx.get(), "TLS_RSA_WITH_AES_256_CBC_SHA:TLS_RSA_WITH_AES_256_GCM_SHA384")); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); // Modify ciphersuites on the SSL object and introduce mismatch, this modifies // ssl->config ASSERT_TRUE( SSL_set_cipher_list(client.get(), "TLS_RSA_WITH_AES_256_CBC_SHA")); ASSERT_TRUE( SSL_set_cipher_list(server.get(), "TLS_RSA_WITH_AES_256_GCM_SHA384")); // Handshake should fail as config objects have no shared cipher. ASSERT_FALSE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_SHARED_CIPHER); ERR_clear_error(); bssl::UniquePtr client2, server2; ASSERT_TRUE(CreateClientAndServer(&client2, &server2, client_ctx.get(), server_ctx.get())); // Modify ciphersuites on the SSL object with a new third cipher, this // modifies ssl->config ASSERT_TRUE( SSL_set_cipher_list(client2.get(), "TLS_RSA_WITH_AES_128_CBC_SHA")); ASSERT_TRUE( SSL_set_cipher_list(server2.get(), "TLS_RSA_WITH_AES_128_CBC_SHA")); ASSERT_TRUE(CompleteHandshakes(client2.get(), server2.get())); ASSERT_EQ(SSL_CIPHER_get_id(SSL_get_current_cipher(client2.get())), (uint32_t)TLS1_CK_RSA_WITH_AES_128_SHA); ASSERT_EQ(SSL_CIPHER_get_id(SSL_get_current_cipher(server2.get())), (uint32_t)TLS1_CK_RSA_WITH_AES_128_SHA); } TEST(SSLTest, TLS12ConfigCtxInteraction) { // This configures SSL_CTX objects with default TLS 1.2 and 1.3 ciphersuites bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_2_VERSION)); // Restrict TLS 1.2 ciphersuites on the SSL_CTX objects ASSERT_TRUE(SSL_CTX_set_cipher_list(client_ctx.get(), "TLS_RSA_WITH_AES_256_CBC_SHA")); ASSERT_TRUE(SSL_CTX_set_cipher_list(server_ctx.get(), "TLS_RSA_WITH_AES_256_CBC_SHA")); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); // Modify TLS 1.2 ciphersuite for client's SSL object, but not server ASSERT_TRUE( SSL_set_cipher_list(client.get(), "TLS_RSA_WITH_AES_256_GCM_SHA384")); // Handshake should fail as client SSL config and server CTX objects have no // shared TLS 1.2 cipher. ASSERT_FALSE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_SHARED_CIPHER); ERR_clear_error(); bssl::UniquePtr client2, server2; ASSERT_TRUE(CreateClientAndServer(&client2, &server2, client_ctx.get(), server_ctx.get())); // Modify TLS 1.2 ciphersuites for server2 SSL object, but not client ASSERT_TRUE( SSL_set_cipher_list(server2.get(), "TLS_RSA_WITH_AES_256_GCM_SHA384")); // Handshake should fail as server SSL config and client CTX objects have no // shared TLS 1.2 cipher. ASSERT_FALSE(CompleteHandshakes(client2.get(), server2.get())); ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), SSL_R_NO_SHARED_CIPHER); } TEST(SSLTest, SSLGetCiphersReturnsTLS13Custom) { bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); // Configure custom TLS 1.3 Ciphersuites SSL_CTX_set_ciphersuites(server_ctx.get(), "TLS_AES_128_GCM_SHA256"); SSL_CTX_set_ciphersuites(client_ctx.get(), "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"); // Configure only TLS 1.3. ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION)); bssl::UniquePtr client, server; // Have to ensure config is not shed per current implementation of // SSL_get_ciphers. ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), server_ctx.get(), ClientConfig(), false)); ASSERT_TRUE(CompleteHandshakes(client.get(), server.get())); // Ensure default TLS 1.3 Ciphersuites are present const SSL_CIPHER *cipher1 = SSL_get_cipher_by_value(TLS1_3_CK_AES_128_GCM_SHA256 & 0xFFFF); ASSERT_TRUE(cipher1); const SSL_CIPHER *cipher2 = SSL_get_cipher_by_value(TLS1_3_CK_AES_256_GCM_SHA384 & 0xFFFF); ASSERT_TRUE(cipher2); const SSL_CIPHER *cipher3 = SSL_get_cipher_by_value(TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xFFFF); ASSERT_TRUE(cipher3); STACK_OF(SSL_CIPHER) *client_ciphers = SSL_get_ciphers(client.get()); STACK_OF(SSL_CIPHER) *server_ciphers = SSL_get_ciphers(server.get()); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, cipher1)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, cipher2)); ASSERT_FALSE(sk_SSL_CIPHER_find_awslc(client_ciphers, NULL, cipher3)); ASSERT_TRUE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, cipher1)); ASSERT_FALSE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, cipher2)); ASSERT_FALSE(sk_SSL_CIPHER_find_awslc(server_ciphers, NULL, cipher3)); } TEST(SSLTest, GetClientCiphersAfterHandshakeFailure1_3) { bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); // configure client to add fake ciphersuite SSL_CTX_set_grease_enabled(client_ctx.get(), 1); // There will be no cipher match, handshake will not succeed. ASSERT_TRUE(SSL_CTX_set_ciphersuites( client_ctx.get(), "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256")); ASSERT_TRUE( SSL_CTX_set_ciphersuites(server_ctx.get(), "TLS_AES_128_GCM_SHA256")); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); const unsigned char *tmp = nullptr; // Handshake not completed, getting ciphers should fail ASSERT_FALSE(SSL_client_hello_get0_ciphers(client.get(), &tmp)); ASSERT_FALSE(SSL_client_hello_get0_ciphers(server.get(), &tmp)); ASSERT_FALSE(tmp); // This should fail, but should be able to inspect client ciphers still ASSERT_FALSE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(SSL_client_hello_get0_ciphers(client.get(), nullptr), (size_t)0); const unsigned char expected_cipher_bytes[] = {0x13, 0x02, 0x13, 0x03}; const unsigned char *p = nullptr; // Expected size is 2 bytes more than |expected_cipher_bytes| to account for // grease value ASSERT_EQ(SSL_client_hello_get0_ciphers(server.get(), &p), sizeof(expected_cipher_bytes) + 2); // Grab the first 2 bytes and check grease value uint16_t grease_val = CRYPTO_load_u16_be(p); ASSERT_FALSE(SSL_get_cipher_by_value(grease_val)); // Sanity check for first cipher ID after grease value uint16_t cipher_val = CRYPTO_load_u16_be(p + 2); ASSERT_TRUE(SSL_get_cipher_by_value((cipher_val))); // Check order and validity of the rest of the client cipher suites, // excluding the grease value (2nd byte onwards) ASSERT_EQ(Bytes(expected_cipher_bytes, sizeof(expected_cipher_bytes)), Bytes(p + 2, sizeof(expected_cipher_bytes))); // Parsed ciphersuite list should only have 2 valid ciphersuites as configured // (grease value should not be included). Even though the handshake fails, // client cipher data should be available through the server SSL object. ASSERT_TRUE(sk_SSL_CIPHER_num(server.get()->client_cipher_suites.get()) == 2); } TEST(SSLTest, GetClientCiphers1_3) { bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); // configure client to add fake ciphersuite SSL_CTX_set_grease_enabled(client_ctx.get(), 1); ASSERT_TRUE(SSL_CTX_set_ciphersuites(client_ctx.get(), "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_" "SHA384:TLS_CHACHA20_POLY1305_SHA256")); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION)); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); const unsigned char *tmp = nullptr; // Handshake not completed, getting ciphers should fail ASSERT_FALSE(SSL_client_hello_get0_ciphers(client.get(), &tmp)); ASSERT_FALSE(SSL_client_hello_get0_ciphers(server.get(), &tmp)); ASSERT_FALSE(tmp); ASSERT_TRUE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(SSL_client_hello_get0_ciphers(client.get(), nullptr), (size_t)0); const unsigned char expected_cipher_bytes[] = {0x13, 0x01, 0x13, 0x02, 0x13, 0x03}; const unsigned char *p = nullptr; // Expected size is 2 bytes more than |expected_cipher_bytes| to account for // grease value ASSERT_EQ(SSL_client_hello_get0_ciphers(server.get(), &p), sizeof(expected_cipher_bytes) + 2); // Grab the first 2 bytes and check grease value uint16_t grease_val = CRYPTO_load_u16_be(p); ASSERT_FALSE(SSL_get_cipher_by_value(grease_val)); // Sanity check for first cipher ID after grease value uint16_t cipher_val = CRYPTO_load_u16_be(p + 2); ASSERT_TRUE(SSL_get_cipher_by_value((cipher_val))); // Check order and validity of the rest of the client cipher suites, // excluding the grease value (2nd byte onwards) ASSERT_EQ(Bytes(expected_cipher_bytes, sizeof(expected_cipher_bytes)), Bytes(p + 2, sizeof(expected_cipher_bytes))); // Parsed ciphersuite list should only have 3 valid ciphersuites as configured // (grease value should not be included) ASSERT_TRUE(sk_SSL_CIPHER_num(server.get()->client_cipher_suites.get()) == 3); } TEST(SSLTest, GetClientCiphers1_2) { bssl::UniquePtr client_ctx(SSL_CTX_new(TLS_method())); bssl::UniquePtr server_ctx = CreateContextWithTestCertificate(TLS_method()); // configure client to add fake ciphersuite SSL_CTX_set_grease_enabled(client_ctx.get(), 1); ASSERT_TRUE(SSL_CTX_set_cipher_list(client_ctx.get(), "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:" "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")); ASSERT_TRUE(client_ctx); ASSERT_TRUE(server_ctx); ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_2_VERSION)); ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_2_VERSION)); bssl::UniquePtr client, server; ASSERT_TRUE(CreateClientAndServer(&client, &server, client_ctx.get(), server_ctx.get())); const unsigned char *tmp = nullptr; // Handshake not completed, getting ciphers should fail ASSERT_FALSE(SSL_client_hello_get0_ciphers(client.get(), &tmp)); ASSERT_FALSE(SSL_client_hello_get0_ciphers(server.get(), &tmp)); ASSERT_FALSE(tmp); ASSERT_TRUE(CompleteHandshakes(client.get(), server.get())); ASSERT_EQ(SSL_client_hello_get0_ciphers(client.get(), nullptr), (size_t)0); const unsigned char expected_cipher_bytes[] = {0xC0, 0x2C, 0xC0, 0x13}; const unsigned char *p = nullptr; // Expected size is 2 bytes more than |expected_cipher_bytes| to account for // grease value ASSERT_EQ(SSL_client_hello_get0_ciphers(server.get(), &p), sizeof(expected_cipher_bytes) + 2); // Grab the first 2 bytes and check grease value uint16_t grease_val = CRYPTO_load_u16_be(p); ASSERT_FALSE(SSL_get_cipher_by_value(grease_val)); // Sanity check for first cipher ID after grease value uint16_t cipher_val = CRYPTO_load_u16_be(p + 2); ASSERT_TRUE(SSL_get_cipher_by_value((cipher_val))); // Check order and validity of the rest of the client cipher suites, // excluding the grease value (2nd byte onwards) ASSERT_EQ(Bytes(expected_cipher_bytes, sizeof(expected_cipher_bytes)), Bytes(p + 2, sizeof(expected_cipher_bytes))); // Parsed ciphersuite list should only have 2 valid ciphersuites as configured // (grease value should not be included) ASSERT_TRUE(sk_SSL_CIPHER_num(server.get()->client_cipher_suites.get()) == 2); } TEST(SSLTest, DISABLED_ApplyHandoffRemovesUnsupportedCiphers) { bssl::UniquePtr server_ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(server_ctx); bssl::UniquePtr server(SSL_new(server_ctx.get())); ASSERT_TRUE(server); // handoff is a handoff message that has been artificially modified to pretend // that only cipher 0x0A is supported. When it is applied to |server|, all // ciphers but that one should be removed. // // To make a new one of these, try sticking this in the |Handoff| test above: // // hexdump(stderr, "", handoff.data(), handoff.size()); // sed -e 's/\(..\)/0x\1, /g' // // and modify serialize_features() to emit only cipher 0x0A. uint8_t handoff[] = { 0x30, 0x81, 0x9a, 0x02, 0x01, 0x00, 0x04, 0x00, 0x04, 0x81, 0x82, 0x01, 0x00, 0x00, 0x7e, 0x03, 0x03, 0x30, 0x8e, 0x8f, 0x79, 0xd2, 0x87, 0x39, 0xc2, 0x23, 0x23, 0x13, 0xca, 0x3c, 0x80, 0x44, 0xfd, 0x80, 0x83, 0x62, 0x3c, 0xcc, 0xf8, 0x76, 0xd3, 0x62, 0xbb, 0x54, 0xe3, 0xc4, 0x39, 0x24, 0xa5, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x04, 0x02, 0x00, 0x0a, 0x04, 0x0a, 0x00, 0x15, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1d, }; EXPECT_EQ(22u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get()))); ASSERT_TRUE( SSL_apply_handoff(server.get(), {handoff, OPENSSL_ARRAY_SIZE(handoff)})); EXPECT_EQ(1u, sk_SSL_CIPHER_num(SSL_get_ciphers(server.get()))); } TEST(SSLTest, ApplyHandoffRemovesUnsupportedCurves) { bssl::UniquePtr server_ctx(SSL_CTX_new(TLS_method())); ASSERT_TRUE(server_ctx); bssl::UniquePtr server(SSL_new(server_ctx.get())); ASSERT_TRUE(server); // handoff is a handoff message that has been artificially modified to pretend // that only one ECDH group is supported. When it is applied to |server|, all // groups but that one should be removed. // // See |ApplyHandoffRemovesUnsupportedCiphers| for how to make a new one of // these. uint8_t handoff[] = { 0x30, 0x81, 0xc0, 0x02, 0x01, 0x00, 0x04, 0x00, 0x04, 0x81, 0x82, 0x01, 0x00, 0x00, 0x7e, 0x03, 0x03, 0x98, 0x30, 0xce, 0xd9, 0xb0, 0xdf, 0x5f, 0x82, 0x05, 0x4a, 0x43, 0x67, 0x7e, 0xdb, 0x6a, 0x4f, 0x21, 0x18, 0x4e, 0x0d, 0x94, 0x63, 0x18, 0x8b, 0x54, 0x89, 0xdb, 0x8b, 0x1d, 0x84, 0xbc, 0x09, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x04, 0x30, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x9c, 0x00, 0x9d, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x09, 0xc0, 0x0a, 0xc0, 0x13, 0xc0, 0x14, 0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x2f, 0xc0, 0x30, 0xc0, 0x35, 0xc0, 0x36, 0xcc, 0xa8, 0xcc, 0xa9, 0xcc, 0xac, 0x04, 0x02, 0x00, 0x17, }; // The zero length means that the default list of groups is used. EXPECT_EQ(0u, server->config->supported_group_list.size()); ASSERT_TRUE( SSL_apply_handoff(server.get(), {handoff, OPENSSL_ARRAY_SIZE(handoff)})); EXPECT_EQ(1u, server->config->supported_group_list.size()); } BSSL_NAMESPACE_END