From e278893b645d69ddd59d1ddbf60ba4237d0d7443 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 21 Jan 2016 18:23:13 +0900 Subject: [PATCH] nghttpx: Add --curves option to specify supported elliptic curves --- gennghttpxfun.py | 3 ++- src/shrpx.cc | 12 ++++++++++++ src/shrpx_config.cc | 13 +++++++++++++ src/shrpx_config.h | 4 ++++ src/shrpx_ssl.cc | 27 +++++++++++++++++++++------ 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/gennghttpxfun.py b/gennghttpxfun.py index 496f1875..e7d7aa4a 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -107,7 +107,8 @@ OPTIONS = [ "add-forwarded", "strip-incoming-forwarded", "forwarded-by", - "forwarded-for" + "forwarded-for", + "curves" ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index 29440fb6..f1ee1107 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -933,6 +933,7 @@ void fill_default_config() { dyn_recconf.idle_timeout = 1_s; tlsconf.session_timeout = std::chrono::hours(12); + tlsconf.curves = "P-256"; } auto &httpconf = mod_config()->http; @@ -1437,6 +1438,12 @@ SSL/TLS: TLS HTTP/2 backends. Default: )" << util::duration_str(get_config()->tls.dyn_rec.idle_timeout) << R"( + --curves= + Specify supported elliptic curves in frontend TLS + connection. The must be a colon separated list + of curves. The curve name is either NIST name (e.g., + "P-256") or OpenSSL OID name (e.g., "prime256v1"). + Default: )" << get_config()->tls.curves << R"( HTTP/2 and SPDY: -c, --http2-max-concurrent-streams= @@ -2212,6 +2219,7 @@ int main(int argc, char **argv) { {SHRPX_OPT_STRIP_INCOMING_FORWARDED, no_argument, &flag, 98}, {SHRPX_OPT_FORWARDED_BY, required_argument, &flag, 99}, {SHRPX_OPT_FORWARDED_FOR, required_argument, &flag, 100}, + {SHRPX_OPT_CURVES, required_argument, &flag, 101}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -2641,6 +2649,10 @@ int main(int argc, char **argv) { // --forwarded-for cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_FOR, optarg); break; + case 101: + // --curves + cmdcfgs.emplace_back(SHRPX_OPT_CURVES, optarg); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index dcc7231e..54dd71c8 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -694,6 +694,7 @@ enum { SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE, SHRPX_OPTID_CLIENT_PROXY, SHRPX_OPTID_CONF, + SHRPX_OPTID_CURVES, SHRPX_OPTID_DAEMON, SHRPX_OPTID_DH_PARAM_FILE, SHRPX_OPTID_ERRORLOG_FILE, @@ -803,6 +804,11 @@ int option_lookup_token(const char *name, size_t namelen) { return SHRPX_OPTID_DAEMON; } break; + case 's': + if (util::strieq_l("curve", name, 5)) { + return SHRPX_OPTID_CURVES; + } + break; case 't': if (util::strieq_l("cacer", name, 5)) { return SHRPX_OPTID_CACERT; @@ -2152,6 +2158,13 @@ int parse_config(const char *opt, const char *optarg, return 0; } + case SHRPX_OPTID_CURVES: +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + mod_config()->tls.curves = optarg; +#else // OPENSSL_VERSION_NUMBER < 0x10002000L + LOG(WARN) << opt << ": this option requires OpenSSL >= 1.0.2."; +#endif // 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 41fd1714..4752be5c 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -196,6 +196,7 @@ constexpr char SHRPX_OPT_STRIP_INCOMING_FORWARDED[] = "strip-incoming-forwarded"; constexpr static char SHRPX_OPT_FORWARDED_BY[] = "forwarded-by"; constexpr char SHRPX_OPT_FORWARDED_FOR[] = "forwarded-for"; +constexpr char SHRPX_OPT_CURVES[] = "curves"; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -366,6 +367,9 @@ struct TLSConfig { // passed to SSL_CTX_set_options(). long int tls_proto_mask; std::string backend_sni_name; + // Supported elliptic curves, separated by colon (':'). This is + // directly passed to OpenSSL configuration function. + std::string curves; std::chrono::seconds session_timeout; std::unique_ptr private_key_file; std::unique_ptr private_key_passwd; diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc index bf7b5800..9d024194 100644 --- a/src/shrpx_ssl.cc +++ b/src/shrpx_ssl.cc @@ -506,13 +506,28 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file } #ifndef OPENSSL_NO_EC +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + auto conf_ctx = SSL_CONF_CTX_new(); - // Disabled SSL_CTX_set_ecdh_auto, because computational cost of - // chosen curve is much higher than P-256. + SSL_CONF_CTX_set_flags(conf_ctx, SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_FILE); + SSL_CONF_CTX_set_ssl_ctx(conf_ctx, ssl_ctx); - // #if OPENSSL_VERSION_NUMBER >= 0x10002000L - // SSL_CTX_set_ecdh_auto(ssl_ctx, 1); - // #else // OPENSSL_VERSION_NUBMER < 0x10002000L + if (!tlsconf.curves.empty()) { + if (SSL_CONF_cmd(conf_ctx, "Curves", tlsconf.curves.c_str()) != 2) { + LOG(FATAL) << "Setting named curves failed: " + << ERR_error_string(ERR_get_error(), nullptr); + DIE(); + } + } + + if (SSL_CONF_CTX_finish(conf_ctx) == 0) { + LOG(FATAL) << "Configuring SSL_CTX failed: " + << ERR_error_string(ERR_get_error(), nullptr); + DIE(); + } + + SSL_CONF_CTX_free(conf_ctx); +#else // 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); @@ -523,7 +538,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 // OPENSSL_VERSION_NUBMER < 0x10002000L #endif // OPENSSL_NO_EC