diff --git a/src/brpc/details/ssl_helper.cpp b/src/brpc/details/ssl_helper.cpp index 322b9cc3ff..0e31f14b30 100644 --- a/src/brpc/details/ssl_helper.cpp +++ b/src/brpc/details/ssl_helper.cpp @@ -86,6 +86,8 @@ static int ParseSSLProtocols(const std::string& str_protocol) { protocol_flag |= TLSv1_1; } else if (strncasecmp(protocol.data(), "TLSv1.2", protocol.size()) == 0) { protocol_flag |= TLSv1_2; + } else if (strncasecmp(protocol.data(), "TLSv1.3", protocol.size()) == 0) { + protocol_flag |= TLSv1_3; } else { LOG(ERROR) << "Unknown SSL protocol=" << protocol; return -1; @@ -443,6 +445,12 @@ static int SetSSLOptions(SSL_CTX* ctx, const std::string& ciphers, ssloptions |= SSL_OP_NO_TLSv1_2; } #endif // SSL_OP_NO_TLSv1_2 + +#ifdef SSL_OP_NO_TLSv1_3 + if (!(protocols & TLSv1_3)) { + ssloptions |= SSL_OP_NO_TLSv1_3; + } +#endif // SSL_OP_NO_TLSv1_3 SSL_CTX_set_options(ctx, ssloptions); long sslmode = SSL_MODE_ENABLE_PARTIAL_WRITE @@ -585,7 +593,7 @@ SSL_CTX* CreateServerSSLContext(const std::string& certificate, return NULL; } - int protocols = TLSv1 | TLSv1_1 | TLSv1_2; + int protocols = TLSv1 | TLSv1_1 | TLSv1_2 | TLSv1_3; if (!options.disable_ssl3) { protocols |= SSLv3; } diff --git a/src/brpc/details/ssl_helper.h b/src/brpc/details/ssl_helper.h index da126b3943..a9b8736bfa 100644 --- a/src/brpc/details/ssl_helper.h +++ b/src/brpc/details/ssl_helper.h @@ -53,6 +53,7 @@ enum SSLProtocol { TLSv1 = 1 << 1, TLSv1_1 = 1 << 2, TLSv1_2 = 1 << 3, + TLSv1_3 = 1 << 4, }; struct FreeSSLCTX { diff --git a/src/brpc/ssl_options.cpp b/src/brpc/ssl_options.cpp index 748749ae82..efeab5c43a 100644 --- a/src/brpc/ssl_options.cpp +++ b/src/brpc/ssl_options.cpp @@ -27,7 +27,7 @@ VerifyOptions::VerifyOptions() ChannelSSLOptions::ChannelSSLOptions() : ciphers("DEFAULT") - , protocols("TLSv1, TLSv1.1, TLSv1.2") + , protocols("TLSv1, TLSv1.1, TLSv1.2, TLSv1.3") {} ServerSSLOptions::ServerSSLOptions() diff --git a/src/brpc/ssl_options.h b/src/brpc/ssl_options.h index 8ddda248a6..3fdb1e85bb 100644 --- a/src/brpc/ssl_options.h +++ b/src/brpc/ssl_options.h @@ -79,8 +79,8 @@ struct ChannelSSLOptions { std::string ciphers; // SSL protocols used for SSL handshake, separated by comma. - // Available protocols: SSLv3, TLSv1, TLSv1.1, TLSv1.2 - // Default: TLSv1, TLSv1.1, TLSv1.2 + // Available protocols: SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3 + // Default: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3 std::string protocols; // When set, fill this into the SNI extension field during handshake, diff --git a/test/brpc_ssl_unittest.cpp b/test/brpc_ssl_unittest.cpp index a469a62386..00fe705edb 100644 --- a/test/brpc_ssl_unittest.cpp +++ b/test/brpc_ssl_unittest.cpp @@ -35,6 +35,7 @@ #include "brpc/channel.h" #include "brpc/socket_map.h" #include "brpc/controller.h" +#include "brpc/details/ssl_helper.h" #include "echo.pb.h" namespace brpc { @@ -497,3 +498,68 @@ TEST_F(SSLTest, ssl_perf) { close(clifd); close(servfd); } + + +#ifdef TLS1_3_VERSION + +void* tls13_do_handshake(void* arg) { + SSL* ssl = (SSL*)arg; + EXPECT_EQ(1, SSL_do_handshake(ssl)); + return NULL; +} + +TEST_F(SSLTest, tls13_protocol_string) { + // Same style as ssl_perf: direct SSL handshake, no SocketMap / socket internals. + const butil::EndPoint ep(butil::IP_ANY, 8613); + butil::fd_guard listenfd(butil::tcp_listen(ep)); + ASSERT_GT(listenfd, 0); + int clifd = tcp_connect(ep, NULL); + ASSERT_GT(clifd, 0); + int servfd = accept(listenfd, NULL, NULL); + ASSERT_GT(servfd, 0); + + brpc::ChannelSSLOptions opt; + opt.protocols = "TLSv1.3"; + SSL_CTX* cli_ctx = brpc::CreateClientSSLContext(opt); + ASSERT_NE(nullptr, cli_ctx); + SSL_CTX* serv_ctx = + brpc::CreateServerSSLContext("cert1.crt", "cert1.key", + brpc::SSLOptions(), NULL, NULL); + ASSERT_NE(nullptr, serv_ctx); + SSL* cli_ssl = brpc::CreateSSLSession(cli_ctx, 0, clifd, false); +#if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME) || defined(USE_MESALINK) + SSL_set_tlsext_host_name(cli_ssl, "localhost"); +#endif + SSL* serv_ssl = brpc::CreateSSLSession(serv_ctx, 0, servfd, true); + ASSERT_NE(nullptr, cli_ssl); + ASSERT_NE(nullptr, serv_ssl); + pthread_t cpid; + pthread_t spid; + ASSERT_EQ(0, pthread_create(&cpid, NULL, tls13_do_handshake, cli_ssl)); + ASSERT_EQ(0, pthread_create(&spid, NULL, tls13_do_handshake, serv_ssl)); + ASSERT_EQ(0, pthread_join(cpid, NULL)); + ASSERT_EQ(0, pthread_join(spid, NULL)); + + const char* version = SSL_get_version(cli_ssl); + ASSERT_TRUE(version != NULL); + EXPECT_STREQ("TLSv1.3", version) << "negotiated protocol=" << version; + + SSL_free(cli_ssl); + SSL_free(serv_ssl); + SSL_CTX_free(cli_ctx); + SSL_CTX_free(serv_ctx); + close(clifd); + close(servfd); +} + +#else // TLS1_3_VERSION + +TEST_F(SSLTest, tls13_protocol_string) { + brpc::ChannelSSLOptions opt; + opt.protocols = "TLSv1.3"; + SSL_CTX* ctx = brpc::CreateClientSSLContext(opt); + ASSERT_TRUE(ctx != NULL); + SSL_CTX_free(ctx); +} + +#endif // TLS1_3_VERSION