Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 6553:2014ed60f17f
SSL: support for multiple curves (ticket #885).
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.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 19 May 2016 14:46:32 +0300 |
parents | addd98357629 |
children | 1aa9650a8154 |
comparison
equal
deleted
inserted
replaced
6552:addd98357629 | 6553:2014ed60f17f |
---|---|
1061 ngx_int_t | 1061 ngx_int_t |
1062 ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) | 1062 ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) |
1063 { | 1063 { |
1064 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL | 1064 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL |
1065 #ifndef OPENSSL_NO_ECDH | 1065 #ifndef OPENSSL_NO_ECDH |
1066 int nid; | |
1067 EC_KEY *ecdh; | |
1068 | 1066 |
1069 /* | 1067 /* |
1070 * Elliptic-Curve Diffie-Hellman parameters are either "named curves" | 1068 * Elliptic-Curve Diffie-Hellman parameters are either "named curves" |
1071 * from RFC 4492 section 5.1.1, or explicitly described curves over | 1069 * from RFC 4492 section 5.1.1, or explicitly described curves over |
1072 * binary fields. OpenSSL only supports the "named curves", which provide | 1070 * binary fields. OpenSSL only supports the "named curves", which provide |
1073 * maximum interoperability. | 1071 * maximum interoperability. |
1074 */ | 1072 */ |
1075 | 1073 |
1076 nid = OBJ_sn2nid((char *) name->data); | 1074 #ifdef SSL_CTRL_SET_CURVES_LIST |
1075 | |
1076 /* | |
1077 * OpenSSL 1.0.2+ allows configuring a curve list instead of a single | |
1078 * curve previously supported. By default an internal list is used, | |
1079 * with prime256v1 being preferred by server in OpenSSL 1.0.2b+ | |
1080 * and X25519 in OpenSSL 1.1.0+. | |
1081 * | |
1082 * By default a curve preferred by the client will be used for | |
1083 * key exchange. The SSL_OP_CIPHER_SERVER_PREFERENCE option can | |
1084 * be used to prefer server curves instead, similar to what it | |
1085 * does for ciphers. | |
1086 */ | |
1087 | |
1088 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE); | |
1089 | |
1090 #if SSL_CTRL_SET_ECDH_AUTO | |
1091 /* not needed in OpenSSL 1.1.0+ */ | |
1092 SSL_CTX_set_ecdh_auto(ssl->ctx, 1); | |
1093 #endif | |
1094 | |
1095 if (ngx_strcmp(name->data, "auto") == 0) { | |
1096 return NGX_OK; | |
1097 } | |
1098 | |
1099 if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) { | |
1100 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1101 "SSL_CTX_set1_curves_list(\"%s\") failed", name->data); | |
1102 return NGX_ERROR; | |
1103 } | |
1104 | |
1105 #else | |
1106 | |
1107 int nid; | |
1108 char *curve; | |
1109 EC_KEY *ecdh; | |
1110 | |
1111 if (ngx_strcmp(name->data, "auto") == 0) { | |
1112 curve = "prime256v1"; | |
1113 | |
1114 } else { | |
1115 curve = (char *) name->data; | |
1116 } | |
1117 | |
1118 nid = OBJ_sn2nid(curve); | |
1077 if (nid == 0) { | 1119 if (nid == 0) { |
1078 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 1120 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
1079 "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); | 1121 "OBJ_sn2nid(\"%s\") failed: unknown curve", curve); |
1080 return NGX_ERROR; | 1122 return NGX_ERROR; |
1081 } | 1123 } |
1082 | 1124 |
1083 ecdh = EC_KEY_new_by_curve_name(nid); | 1125 ecdh = EC_KEY_new_by_curve_name(nid); |
1084 if (ecdh == NULL) { | 1126 if (ecdh == NULL) { |
1085 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 1127 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
1086 "EC_KEY_new_by_curve_name(\"%s\") failed", name->data); | 1128 "EC_KEY_new_by_curve_name(\"%s\") failed", curve); |
1087 return NGX_ERROR; | 1129 return NGX_ERROR; |
1088 } | 1130 } |
1089 | 1131 |
1090 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE); | 1132 SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE); |
1091 | 1133 |
1092 SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh); | 1134 SSL_CTX_set_tmp_ecdh(ssl->ctx, ecdh); |
1093 | 1135 |
1094 EC_KEY_free(ecdh); | 1136 EC_KEY_free(ecdh); |
1137 #endif | |
1095 #endif | 1138 #endif |
1096 #endif | 1139 #endif |
1097 | 1140 |
1098 return NGX_OK; | 1141 return NGX_OK; |
1099 } | 1142 } |