]> git.kaiwu.me - nginx.git/commitdiff
SSL: support for multiple curves (ticket #885).
authorMaxim Dounin <mdounin@mdounin.ru>
Thu, 19 May 2016 11:46:32 +0000 (14:46 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Thu, 19 May 2016 11:46:32 +0000 (14:46 +0300)
OpenSSL 1.0.2+ allows configuring a curve list instead of a single curve
previously supported.  This allows use of different curves depending on
what client supports (as available via the elliptic_curves extension),
and also allows use of different curves in an ECDHE key exchange and
in the ECDSA certificate.

The special value "auto" was introduced (now the default for ssl_ecdh_curve),
which means "use an internal list of curves as available in the OpenSSL
library used".  For versions prior to OpenSSL 1.0.2 it maps to "prime256v1"
as previously used.  The default in 1.0.2b+ prefers prime256v1 as well
(and X25519 in OpenSSL 1.1.0+).

As client vs. server preference of curves is controlled by the
same option as used for ciphers (SSL_OP_CIPHER_SERVER_PREFERENCE),
the ssl_prefer_server_ciphers directive now controls both.

src/event/ngx_event_openssl.c
src/http/modules/ngx_http_ssl_module.c
src/mail/ngx_mail_ssl_module.c
src/stream/ngx_stream_ssl_module.c

index 39d3b5bdccd0a36d9be906b07e8a248456e217b4..96c059be90772d230b4928983b2775493c3a1d71 100644 (file)
@@ -1063,8 +1063,6 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
 {
 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
 #ifndef OPENSSL_NO_ECDH
-    int      nid;
-    EC_KEY  *ecdh;
 
     /*
      * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
@@ -1073,17 +1071,61 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
      * maximum interoperability.
      */
 
-    nid = OBJ_sn2nid((char *) name->data);
+#ifdef SSL_CTRL_SET_CURVES_LIST
+
+    /*
+     * OpenSSL 1.0.2+ allows configuring a curve list instead of a single
+     * curve previously supported.  By default an internal list is used,
+     * with prime256v1 being preferred by server in OpenSSL 1.0.2b+
+     * and X25519 in OpenSSL 1.1.0+.
+     *
+     * By default a curve preferred by the client will be used for
+     * key exchange.  The SSL_OP_CIPHER_SERVER_PREFERENCE option can
+     * be used to prefer server curves instead, similar to what it
+     * does for ciphers.
+     */
+
+    SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE);
+
+#if SSL_CTRL_SET_ECDH_AUTO
+    /* not needed in OpenSSL 1.1.0+ */
+    SSL_CTX_set_ecdh_auto(ssl->ctx, 1);
+#endif
+
+    if (ngx_strcmp(name->data, "auto") == 0) {
+        return NGX_OK;
+    }
+
+    if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "SSL_CTX_set1_curves_list(\"%s\") failed", name->data);
+        return NGX_ERROR;
+    }
+
+#else
+
+    int      nid;
+    char    *curve;
+    EC_KEY  *ecdh;
+
+    if (ngx_strcmp(name->data, "auto") == 0) {
+        curve = "prime256v1";
+
+    } else {
+        curve = (char *) name->data;
+    }
+
+    nid = OBJ_sn2nid(curve);
     if (nid == 0) {
         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
-                      "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data);
+                      "OBJ_sn2nid(\"%s\") failed: unknown curve", curve);
         return NGX_ERROR;
     }
 
     ecdh = EC_KEY_new_by_curve_name(nid);
     if (ecdh == NULL) {
         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
-                      "EC_KEY_new_by_curve_name(\"%s\") failed", name->data);
+                      "EC_KEY_new_by_curve_name(\"%s\") failed", curve);
         return NGX_ERROR;
     }
 
@@ -1093,6 +1135,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
 
     EC_KEY_free(ecdh);
 #endif
+#endif
 #endif
 
     return NGX_OK;
index 26d7b00029042a922a1250f2e09c919a352a106a..7f23c86e317b255067f886463bf42c68793e2bc5 100644 (file)
@@ -15,7 +15,7 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
 
 
 #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
-#define NGX_DEFAULT_ECDH_CURVE  "prime256v1"
+#define NGX_DEFAULT_ECDH_CURVE  "auto"
 
 #define NGX_HTTP_NPN_ADVERTISE  "\x08http/1.1"
 
index 833c3e446e01854794e29c45946b34f7f3546a1a..83cffb83273869266c77ecb2919128ab97d67f78 100644 (file)
@@ -11,7 +11,7 @@
 
 
 #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
-#define NGX_DEFAULT_ECDH_CURVE  "prime256v1"
+#define NGX_DEFAULT_ECDH_CURVE  "auto"
 
 
 static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
index 677c393254d2fb888c971d3b57311cc98759f095..2d2f3ca020f87ae2c41691c9531af04db191ee56 100644 (file)
@@ -11,7 +11,7 @@
 
 
 #define NGX_DEFAULT_CIPHERS     "HIGH:!aNULL:!MD5"
-#define NGX_DEFAULT_ECDH_CURVE  "prime256v1"
+#define NGX_DEFAULT_ECDH_CURVE  "auto"
 
 
 static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf);