src: Enable TLSv1.3 if OpenSSL supports it
If OpenSSL supports TLSv1.3, enable it by default for all applications under src. BoringSSL can work at the moment although it does not unlock all the features nghttpx offers. OpenSSL's TLSv1.3 support is still WIP at the time of writing.
This commit is contained in:
parent
6ecfac6954
commit
9e8d9d658a
|
@ -2122,6 +2122,13 @@ int HttpServer::run() {
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
|
||||||
|
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
|
||||||
|
ssl_ctx, nghttp2::ssl::NGHTTP2_TLS_MIN_VERSION,
|
||||||
|
nghttp2::ssl::NGHTTP2_TLS_MAX_VERSION) != 0) {
|
||||||
|
std::cerr << "Could not set TLS versions" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) {
|
if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) {
|
||||||
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
|
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -2242,6 +2242,13 @@ int main(int argc, char **argv) {
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
|
||||||
|
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
|
||||||
|
ssl_ctx, nghttp2::ssl::NGHTTP2_TLS_MIN_VERSION,
|
||||||
|
nghttp2::ssl::NGHTTP2_TLS_MAX_VERSION) != 0) {
|
||||||
|
std::cerr << "Could not set TLS versions" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
if (SSL_CTX_set_cipher_list(ssl_ctx, config.ciphers.c_str()) == 0) {
|
if (SSL_CTX_set_cipher_list(ssl_ctx, config.ciphers.c_str()) == 0) {
|
||||||
std::cerr << "SSL_CTX_set_cipher_list with " << config.ciphers
|
std::cerr << "SSL_CTX_set_cipher_list with " << config.ciphers
|
||||||
<< " failed: " << ERR_error_string(ERR_get_error(), nullptr)
|
<< " failed: " << ERR_error_string(ERR_get_error(), nullptr)
|
||||||
|
|
|
@ -2246,6 +2246,15 @@ int communicate(
|
||||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
|
||||||
|
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
|
||||||
|
ssl_ctx, nghttp2::ssl::NGHTTP2_TLS_MIN_VERSION,
|
||||||
|
nghttp2::ssl::NGHTTP2_TLS_MAX_VERSION) != 0) {
|
||||||
|
std::cerr << "[ERROR] Could not set TLS versions" << std::endl;
|
||||||
|
result = -1;
|
||||||
|
goto fin;
|
||||||
|
}
|
||||||
|
|
||||||
if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) {
|
if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) {
|
||||||
std::cerr << "[ERROR] " << ERR_error_string(ERR_get_error(), nullptr)
|
std::cerr << "[ERROR] " << ERR_error_string(ERR_get_error(), nullptr)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
42
src/shrpx.cc
42
src/shrpx.cc
|
@ -1369,7 +1369,11 @@ constexpr auto DEFAULT_NPN_LIST = StringRef::from_lit("h2,h2-16,h2-14,"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr auto DEFAULT_TLS_MIN_PROTO_VERSION = StringRef::from_lit("TLSv1.1");
|
constexpr auto DEFAULT_TLS_MIN_PROTO_VERSION = StringRef::from_lit("TLSv1.1");
|
||||||
|
#ifdef TLS1_3_VERSION
|
||||||
|
constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.3");
|
||||||
|
#else // !TLS1_3_VERSION
|
||||||
constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.2");
|
constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.2");
|
||||||
|
#endif // !TLS1_3_VERSION
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -2060,23 +2064,33 @@ SSL/TLS:
|
||||||
Path to file that contains client certificate used in
|
Path to file that contains client certificate used in
|
||||||
backend client authentication.
|
backend client authentication.
|
||||||
--tls-min-proto-version=<VER>
|
--tls-min-proto-version=<VER>
|
||||||
Specify minimum SSL/TLS protocol. The following
|
Specify minimum SSL/TLS protocol. The name matching is
|
||||||
protocols are available: TLSv1.2, TLSv1.1 and TLSv1.0.
|
done in case-insensitive manner. The versions between
|
||||||
The name matching is done in case-insensitive manner.
|
--tls-min-proto-version and --tls-max-proto-version are
|
||||||
The versions between --tls-min-proto-version and
|
enabled. If the protocol list advertised by client does
|
||||||
--tls-max-proto-version are enabled. If the protocol
|
not overlap this range, you will receive the error
|
||||||
list advertised by client does not overlap this range,
|
message "unknown protocol". The available versions are:
|
||||||
you will receive the error message "unknown protocol".
|
)"
|
||||||
|
#ifdef TLS1_3_VERSION
|
||||||
|
"TLSv1.3, "
|
||||||
|
#endif // TLS1_3_VERSION
|
||||||
|
"TLSv1.2, TLSv1.1, and TLSv1.0"
|
||||||
|
R"(
|
||||||
Default: )"
|
Default: )"
|
||||||
<< DEFAULT_TLS_MIN_PROTO_VERSION << R"(
|
<< DEFAULT_TLS_MIN_PROTO_VERSION << R"(
|
||||||
--tls-max-proto-version=<VER>
|
--tls-max-proto-version=<VER>
|
||||||
Specify maximum SSL/TLS protocol. The following
|
Specify maximum SSL/TLS protocol. The name matching is
|
||||||
protocols are available: TLSv1.2, TLSv1.1 and TLSv1.0.
|
done in case-insensitive manner. The versions between
|
||||||
The name matching is done in case-insensitive manner.
|
--tls-min-proto-version and --tls-max-proto-version are
|
||||||
The versions between --tls-min-proto-version and
|
enabled. If the protocol list advertised by client does
|
||||||
--tls-max-proto-version are enabled. If the protocol
|
not overlap this range, you will receive the error
|
||||||
list advertised by client does not overlap this range,
|
message "unknown protocol". The available versions are:
|
||||||
you will receive the error message "unknown protocol".
|
)"
|
||||||
|
#ifdef TLS1_3_VERSION
|
||||||
|
"TLSv1.3, "
|
||||||
|
#endif // TLS1_3_VERSION
|
||||||
|
"TLSv1.2, TLSv1.1, and TLSv1.0"
|
||||||
|
R"(
|
||||||
Default: )"
|
Default: )"
|
||||||
<< DEFAULT_TLS_MAX_PROTO_VERSION << R"(
|
<< DEFAULT_TLS_MAX_PROTO_VERSION << R"(
|
||||||
--tls-ticket-key-file=<PATH>
|
--tls-ticket-key-file=<PATH>
|
||||||
|
|
|
@ -639,55 +639,6 @@ long int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OPENSSL_IS_BORINGSSL)
|
|
||||||
namespace {
|
|
||||||
int ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max) {
|
|
||||||
SSL_CTX_set_min_version(ssl_ctx, min);
|
|
||||||
SSL_CTX_set_max_version(ssl_ctx, max);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#elif OPENSSL_1_1_API
|
|
||||||
namespace {
|
|
||||||
int ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max) {
|
|
||||||
if (SSL_CTX_set_min_proto_version(ssl_ctx, min) != 1 ||
|
|
||||||
SSL_CTX_set_max_proto_version(ssl_ctx, max) != 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#else // !OPENSSL_1_1_API
|
|
||||||
namespace {
|
|
||||||
int ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max) {
|
|
||||||
long int opts = 0;
|
|
||||||
|
|
||||||
// TODO We depends on the ordering of protocol version macro in
|
|
||||||
// OpenSSL.
|
|
||||||
if (min > TLS1_VERSION) {
|
|
||||||
opts |= SSL_OP_NO_TLSv1;
|
|
||||||
}
|
|
||||||
if (min > TLS1_1_VERSION) {
|
|
||||||
opts |= SSL_OP_NO_TLSv1_1;
|
|
||||||
}
|
|
||||||
if (min > TLS1_2_VERSION) {
|
|
||||||
opts |= SSL_OP_NO_TLSv1_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max < TLS1_2_VERSION) {
|
|
||||||
opts |= SSL_OP_NO_TLSv1_2;
|
|
||||||
}
|
|
||||||
if (max < TLS1_1_VERSION) {
|
|
||||||
opts |= SSL_OP_NO_TLSv1_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx, opts);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#endif // !OPENSSL_1_1_API
|
|
||||||
|
|
||||||
SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
||||||
const std::vector<uint8_t> &sct_data
|
const std::vector<uint8_t> &sct_data
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
|
@ -712,10 +663,9 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
|
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
|
||||||
|
|
||||||
if (ssl_ctx_set_proto_versions(ssl_ctx, tlsconf.min_proto_version,
|
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
|
||||||
tlsconf.max_proto_version) != 0) {
|
ssl_ctx, tlsconf.min_proto_version, tlsconf.max_proto_version) != 0) {
|
||||||
LOG(FATAL) << "Could not set TLS protocol version: "
|
LOG(FATAL) << "Could not set TLS protocol version";
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -953,10 +903,9 @@ SSL_CTX *create_ssl_client_context(
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
|
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
|
||||||
|
|
||||||
if (ssl_ctx_set_proto_versions(ssl_ctx, tlsconf.min_proto_version,
|
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
|
||||||
tlsconf.max_proto_version) != 0) {
|
ssl_ctx, tlsconf.min_proto_version, tlsconf.max_proto_version) != 0) {
|
||||||
LOG(FATAL) << "Could not set TLS protocol version: "
|
LOG(FATAL) << "Could not set TLS protocol version";
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1742,6 +1691,11 @@ SSL_SESSION *reuse_tls_session(const TLSSessionCache &cache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int proto_version_from_string(const StringRef &v) {
|
int proto_version_from_string(const StringRef &v) {
|
||||||
|
#ifdef TLS1_3_VERSION
|
||||||
|
if (util::strieq_l("TLSv1.3", v)) {
|
||||||
|
return TLS1_3_VERSION;
|
||||||
|
}
|
||||||
|
#endif // TLS1_3_VERSION
|
||||||
if (util::strieq_l("TLSv1.2", v)) {
|
if (util::strieq_l("TLSv1.2", v)) {
|
||||||
return TLS1_2_VERSION;
|
return TLS1_2_VERSION;
|
||||||
}
|
}
|
||||||
|
|
43
src/ssl.cc
43
src/ssl.cc
|
@ -83,6 +83,10 @@ const char *get_tls_protocol(SSL *ssl) {
|
||||||
return "SSLv2";
|
return "SSLv2";
|
||||||
case SSL3_VERSION:
|
case SSL3_VERSION:
|
||||||
return "SSLv3";
|
return "SSLv3";
|
||||||
|
#ifdef TLS1_3_VERSION
|
||||||
|
case TLS1_3_VERSION:
|
||||||
|
return "TLSv1.3";
|
||||||
|
#endif // TLS1_3_VERSION
|
||||||
case TLS1_2_VERSION:
|
case TLS1_2_VERSION:
|
||||||
return "TLSv1.2";
|
return "TLSv1.2";
|
||||||
case TLS1_1_VERSION:
|
case TLS1_1_VERSION:
|
||||||
|
@ -159,6 +163,45 @@ void libssl_init() {
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max) {
|
||||||
|
#if OPENSSL_1_1_API
|
||||||
|
if (SSL_CTX_set_min_proto_version(ssl_ctx, min) != 1 ||
|
||||||
|
SSL_CTX_set_max_proto_version(ssl_ctx, max) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#elif defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
SSL_CTX_set_min_version(ssl_ctx, min);
|
||||||
|
SSL_CTX_set_max_version(ssl_ctx, max);
|
||||||
|
return 0;
|
||||||
|
#else // !defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
long int opts = 0;
|
||||||
|
|
||||||
|
// TODO We depends on the ordering of protocol version macro in
|
||||||
|
// OpenSSL.
|
||||||
|
if (min > TLS1_VERSION) {
|
||||||
|
opts |= SSL_OP_NO_TLSv1;
|
||||||
|
}
|
||||||
|
if (min > TLS1_1_VERSION) {
|
||||||
|
opts |= SSL_OP_NO_TLSv1_1;
|
||||||
|
}
|
||||||
|
if (min > TLS1_2_VERSION) {
|
||||||
|
opts |= SSL_OP_NO_TLSv1_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max < TLS1_2_VERSION) {
|
||||||
|
opts |= SSL_OP_NO_TLSv1_2;
|
||||||
|
}
|
||||||
|
if (max < TLS1_1_VERSION) {
|
||||||
|
opts |= SSL_OP_NO_TLSv1_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX_set_options(ssl_ctx, opts);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#endif // !defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
29
src/ssl.h
29
src/ssl.h
|
@ -49,7 +49,25 @@ public:
|
||||||
// suites by mozilla.
|
// suites by mozilla.
|
||||||
//
|
//
|
||||||
// https://wiki.mozilla.org/Security/Server_Side_TLS
|
// https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
|
//
|
||||||
|
// Plus TLSv1.3 cipher suites if defined.
|
||||||
constexpr char DEFAULT_CIPHER_LIST[] =
|
constexpr char DEFAULT_CIPHER_LIST[] =
|
||||||
|
#ifdef TLS1_3_TXT_AES_256_GCM_SHA384
|
||||||
|
TLS1_3_TXT_AES_256_GCM_SHA384
|
||||||
|
":"
|
||||||
|
#endif // TLS1_3_TXT_AES_256_GCM_SHA384
|
||||||
|
#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256
|
||||||
|
TLS1_3_TXT_CHACHA20_POLY1305_SHA256 ":"
|
||||||
|
#endif // TLS1_3_TXT_CHACHA20_POLY1305_SHA256
|
||||||
|
#ifdef TLS1_3_TXT_AES_128_GCM_SHA256
|
||||||
|
TLS1_3_TXT_AES_128_GCM_SHA256 ":"
|
||||||
|
#endif // TLS1_3_TXT_AES_128_GCM_SHA256
|
||||||
|
#ifdef TLS1_3_TXT_AES_128_CCM_SHA256
|
||||||
|
TLS1_3_TXT_AES_128_CCM_SHA256 ":"
|
||||||
|
#endif // TLS1_3_TXT_AES_128_CCM_SHA256
|
||||||
|
#ifdef TLS1_3_TXT_AES_128_CCM_8_SHA256
|
||||||
|
TLS1_3_TXT_AES_128_CCM_8_SHA256 ":"
|
||||||
|
#endif // TLS1_3_TXT_AES_128_CCM_8_SHA256
|
||||||
"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-"
|
"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-"
|
||||||
"AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-"
|
"AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-"
|
||||||
"SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-"
|
"SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-"
|
||||||
|
@ -61,6 +79,13 @@ constexpr char DEFAULT_CIPHER_LIST[] =
|
||||||
"SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-"
|
"SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-"
|
||||||
"SHA:DES-CBC3-SHA:!DSS";
|
"SHA:DES-CBC3-SHA:!DSS";
|
||||||
|
|
||||||
|
constexpr auto NGHTTP2_TLS_MIN_VERSION = TLS1_VERSION;
|
||||||
|
#ifdef TLS1_3_VERSION
|
||||||
|
constexpr auto NGHTTP2_TLS_MAX_VERSION = TLS1_3_VERSION;
|
||||||
|
#else // !TLS1_3_VERSION
|
||||||
|
constexpr auto NGHTTP2_TLS_MAX_VERSION = TLS1_2_VERSION;
|
||||||
|
#endif // !TLS1_3_VERSION
|
||||||
|
|
||||||
const char *get_tls_protocol(SSL *ssl);
|
const char *get_tls_protocol(SSL *ssl);
|
||||||
|
|
||||||
struct TLSSessionInfo {
|
struct TLSSessionInfo {
|
||||||
|
@ -91,6 +116,10 @@ bool check_http2_requirement(SSL *ssl);
|
||||||
// Initializes OpenSSL library
|
// Initializes OpenSSL library
|
||||||
void libssl_init();
|
void libssl_init();
|
||||||
|
|
||||||
|
// Sets TLS min and max versions to |ssl_ctx|. This function returns
|
||||||
|
// 0 if it succeeds, or -1.
|
||||||
|
int ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max);
|
||||||
|
|
||||||
} // namespace ssl
|
} // namespace ssl
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
Loading…
Reference in New Issue