diff --git a/gennghttpxfun.py b/gennghttpxfun.py index d2f04143..0d29e790 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -146,6 +146,7 @@ OPTIONS = [ "frontend-http2-decoder-dynamic-table-size", "backend-http2-encoder-dynamic-table-size", "backend-http2-decoder-dynamic-table-size", + "ecdh-curves", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index 8438d2b0..fe470dcf 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -87,6 +87,7 @@ #include "ssl.h" #include "template.h" #include "allocator.h" +#include "ssl_compat.h" extern char **environ; @@ -1316,6 +1317,11 @@ void fill_default_config(Config *config) { } tlsconf.session_timeout = std::chrono::hours(12); +#if OPENSSL_1_1_API + tlsconf.ecdh_curves = StringRef::from_lit("X25519:P-256"); +#else // !OPENSSL_1_1_API + tlsconf.ecdh_curves = StringRef::from_lit("P-256"); +#endif // !OPENSSL_1_1_API auto &httpconf = config->http; httpconf.server_name = @@ -1822,6 +1828,13 @@ SSL/TLS: --ciphers= Set allowed cipher list. The format of the string is described in OpenSSL ciphers(1). + --ecdh-curves= + Set supported curve list for frontend connections. + is a colon separated list of curve NID or names + in the preference order. The supported curves depend on + the linked OpenSSL library. This function requires + OpenSSL >= 1.0.2. + Default: )" << get_config()->tls.ecdh_curves << R"( -k, --insecure Don't verify backend server's certificate if TLS is enabled for backend connections. @@ -2930,6 +2943,7 @@ int main(int argc, char **argv) { required_argument, &flag, 138}, {SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(), required_argument, &flag, 139}, + {SHRPX_OPT_ECDH_CURVES.c_str(), required_argument, &flag, 140}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -3590,6 +3604,10 @@ int main(int argc, char **argv) { cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE, StringRef{optarg}); break; + case 140: + // --ecdh-curves + cmdcfgs.emplace_back(SHRPX_OPT_ECDH_CURVES, StringRef{optarg}); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index fc603dc5..e41e35d4 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -56,6 +56,7 @@ #include "shrpx_http.h" #include "util.h" #include "base64.h" +#include "ssl_compat.h" namespace shrpx { @@ -1174,6 +1175,9 @@ int option_lookup_token(const char *name, size_t namelen) { if (util::strieq_l("backend-tl", name, 10)) { return SHRPX_OPTID_BACKEND_TLS; } + if (util::strieq_l("ecdh-curve", name, 10)) { + return SHRPX_OPTID_ECDH_CURVES; + } break; case 't': if (util::strieq_l("write-burs", name, 10)) { @@ -2864,6 +2868,13 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE: return parse_uint_with_unit( &config->http2.downstream.decoder_dynamic_table_size, opt, optarg); + case SHRPX_OPTID_ECDH_CURVES: +#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L + config->tls.ecdh_curves = make_string_ref(config->balloc, optarg); +#else // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L) + LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2"; +#endif // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L) + return 0; case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 527c13b6..f05f6de5 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -308,6 +308,7 @@ constexpr auto SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE = StringRef::from_lit("backend-http2-encoder-dynamic-table-size"); constexpr auto SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE = StringRef::from_lit("backend-http2-decoder-dynamic-table-size"); +constexpr auto SHRPX_OPT_ECDH_CURVES = StringRef::from_lit("ecdh-curves"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -540,6 +541,7 @@ struct TLSConfig { StringRef cert_file; StringRef dh_param_file; StringRef ciphers; + StringRef ecdh_curves; StringRef cacert; bool insecure; bool no_http2_cipher_black_list; @@ -871,6 +873,7 @@ enum { SHRPX_OPTID_CONF, SHRPX_OPTID_DAEMON, SHRPX_OPTID_DH_PARAM_FILE, + SHRPX_OPTID_ECDH_CURVES, SHRPX_OPTID_ERROR_PAGE, SHRPX_OPTID_ERRORLOG_FILE, SHRPX_OPTID_ERRORLOG_SYSLOG, diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc index 6eb243aa..8c50976b 100644 --- a/src/shrpx_ssl.cc +++ b/src/shrpx_ssl.cc @@ -560,13 +560,18 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file } #ifndef OPENSSL_NO_EC - - // Disabled SSL_CTX_set_ecdh_auto, because computational cost of - // chosen curve is much higher than P-256. - - // #if OPENSSL_VERSION_NUMBER >= 0x10002000L - // SSL_CTX_set_ecdh_auto(ssl_ctx, 1); - // #else // OPENSSL_VERSION_NUBMER < 0x10002000L +#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L + if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) { + LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves + << " failed"; + DIE(); + } +#if !OPENSSL_1_1_API + // It looks like we need this function call for OpenSSL 1.0.2. This + // function was deprecated in OpenSSL 1.1.0. + SSL_CTX_set_ecdh_auto(ssl_ctx, 1); +#endif // !OPENSSL_1_1_API +#else // LIBRESSL_IN_USE || OPENSSL_VERSION_NUBMER < 0x10002000L // Use P-256, which is sufficiently secure at the time of this // writing. auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); @@ -577,8 +582,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file } SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); EC_KEY_free(ecdh); -// #endif // OPENSSL_VERSION_NUBMER < 0x10002000L - +#endif // LIBRESSL_IN_USE || OPENSSL_VERSION_NUBMER < 0x10002000L #endif // OPENSSL_NO_EC if (!tlsconf.dh_param_file.empty()) {