From: Juha Koho Date: Mon, 10 Oct 2016 22:13:49 +0000 (+0200) Subject: ssl: add ssl_curve_list setting for selecting ECHDE curves X-Git-Tag: 2.3.0.rc1~2287 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c4d66e8ccbb8440622f1a70791ed2a8f99659af1;p=thirdparty%2Fdovecot%2Fcore.git ssl: add ssl_curve_list setting for selecting ECHDE curves --- diff --git a/doc/example-config/conf.d/10-ssl.conf b/doc/example-config/conf.d/10-ssl.conf index a70cbdb4b1..cb77799e2c 100644 --- a/doc/example-config/conf.d/10-ssl.conf +++ b/doc/example-config/conf.d/10-ssl.conf @@ -57,6 +57,11 @@ ssl_key = + ], [ + SSL_CTX_set1_curves_list((void*)0, ""); + ], [ + i_cv_have_ssl_ctx_set1_curves_list=yes + ], [ + i_cv_have_ssl_ctx_set1_curves_list=no + ]) + LIBS=$old_LIBS + ]) + if test $i_cv_have_ssl_ctx_set1_curves_list = yes; then + AC_DEFINE(HAVE_SSL_CTX_SET1_CURVES_LIST,, [Define if you have SSL_CTX_set1_curves_list]) + fi + AC_CHECK_LIB(ssl, SSL_get_current_compression, [ AC_DEFINE(HAVE_SSL_COMPRESSION,, [Build with OpenSSL compression]) ],, $SSL_LIBS) diff --git a/src/lib-master/master-service-ssl-settings.c b/src/lib-master/master-service-ssl-settings.c index 65a972f310..fb6cd16cff 100644 --- a/src/lib-master/master-service-ssl-settings.c +++ b/src/lib-master/master-service-ssl-settings.c @@ -22,6 +22,7 @@ static const struct setting_define master_service_ssl_setting_defines[] = { DEF(SET_STR, ssl_key_password), DEF(SET_STR, ssl_dh), DEF(SET_STR, ssl_cipher_list), + DEF(SET_STR, ssl_curve_list), DEF(SET_STR, ssl_protocols), DEF(SET_STR, ssl_cert_username_field), DEF(SET_STR, ssl_crypto_device), @@ -46,6 +47,7 @@ static const struct master_service_ssl_settings master_service_ssl_default_setti .ssl_key_password = "", .ssl_dh = "", .ssl_cipher_list = "ALL:!LOW:!SSLv2:!EXP:!aNULL", + .ssl_curve_list = "", #ifdef SSL_TXT_SSLV2 .ssl_protocols = "!SSLv2 !SSLv3", #else @@ -131,6 +133,14 @@ master_service_ssl_settings_check(void *_set, pool_t pool ATTR_UNUSED, } } +#ifndef HAVE_SSL_CTX_SET1_CURVES_LIST + if (*set->ssl_curve_list != '\0') { + *error_r = "ssl_curve_list is set, but the linked openssl " + "version does not support it"; + return FALSE; + } +#endif + return TRUE; #endif } diff --git a/src/lib-master/master-service-ssl-settings.h b/src/lib-master/master-service-ssl-settings.h index 8cd3f063a4..484830ea67 100644 --- a/src/lib-master/master-service-ssl-settings.h +++ b/src/lib-master/master-service-ssl-settings.h @@ -11,6 +11,7 @@ struct master_service_ssl_settings { const char *ssl_key_password; const char *ssl_dh; const char *ssl_cipher_list; + const char *ssl_curve_list; const char *ssl_protocols; const char *ssl_cert_username_field; const char *ssl_crypto_device; diff --git a/src/lib-master/master-service-ssl.c b/src/lib-master/master-service-ssl.c index 93cd277baa..07e97d1d70 100644 --- a/src/lib-master/master-service-ssl.c +++ b/src/lib-master/master-service-ssl.c @@ -63,6 +63,7 @@ void master_service_ssl_ctx_init(struct master_service *service) i_zero(&ssl_set); ssl_set.protocols = set->ssl_protocols; ssl_set.cipher_list = set->ssl_cipher_list; + ssl_set.curve_list = set->ssl_curve_list; ssl_set.ca = set->ssl_ca; ssl_set.cert = set->ssl_cert; ssl_set.key = set->ssl_key; diff --git a/src/lib-ssl-iostream/iostream-openssl-context.c b/src/lib-ssl-iostream/iostream-openssl-context.c index 998a3463a7..10f44107f8 100644 --- a/src/lib-ssl-iostream/iostream-openssl-context.c +++ b/src/lib-ssl-iostream/iostream-openssl-context.c @@ -346,6 +346,14 @@ ssl_iostream_context_set(struct ssl_iostream_context *ctx, set->cipher_list, openssl_iostream_error()); return -1; } +#ifdef HAVE_SSL_CTX_SET1_CURVES_LIST + if (set->curve_list != NULL && strlen(set->curve_list) > 0 && + SSL_CTX_set1_curves_list(ctx->ssl_ctx, set->curve_list) == 0) { + *error_r = t_strdup_printf("Failed to set curve list to '%s'", + set->curve_list); + return -1; + } +#endif if (set->prefer_server_ciphers) { SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); diff --git a/src/lib-ssl-iostream/iostream-openssl.c b/src/lib-ssl-iostream/iostream-openssl.c index 17135aabb3..713128ad25 100644 --- a/src/lib-ssl-iostream/iostream-openssl.c +++ b/src/lib-ssl-iostream/iostream-openssl.c @@ -160,6 +160,17 @@ openssl_iostream_set(struct ssl_iostream *ssl_io, return -1; } } +#ifdef HAVE_SSL_CTX_SET1_CURVES_LIST + if (set->curve_list != NULL && strlen(set->curve_list) > 0 && + (ctx_set->curve_list == NULL || strcmp(ctx_set->curve_list, set->curve_list) != 0)) { + if (SSL_set1_curves_list(ssl_io->ssl, set->curve_list) == 0) { + *error_r = t_strdup_printf( + "Failed to set curve list to '%s'", + set->curve_list); + return -1; + } + } +#endif if (set->prefer_server_ciphers) SSL_set_options(ssl_io->ssl, SSL_OP_CIPHER_SERVER_PREFERENCE); if (set->protocols != NULL) { diff --git a/src/lib-ssl-iostream/iostream-ssl.c b/src/lib-ssl-iostream/iostream-ssl.c index 90e46a7c54..77ff2d81a0 100644 --- a/src/lib-ssl-iostream/iostream-ssl.c +++ b/src/lib-ssl-iostream/iostream-ssl.c @@ -219,6 +219,7 @@ ssl_iostream_settings_dup(pool_t pool, new_set->protocols = p_strdup(pool, old_set->protocols); new_set->cipher_list = p_strdup(pool, old_set->cipher_list); + new_set->curve_list = p_strdup(pool, old_set->curve_list); new_set->ca = p_strdup(pool, old_set->ca); new_set->ca_file = p_strdup(pool, old_set->ca_file); new_set->ca_dir = p_strdup(pool, old_set->ca_dir); diff --git a/src/lib-ssl-iostream/iostream-ssl.h b/src/lib-ssl-iostream/iostream-ssl.h index d4ca6cba2b..eeefa544f4 100644 --- a/src/lib-ssl-iostream/iostream-ssl.h +++ b/src/lib-ssl-iostream/iostream-ssl.h @@ -7,6 +7,7 @@ struct ssl_iostream_context; struct ssl_iostream_settings { const char *protocols; const char *cipher_list; + const char *curve_list; const char *ca, *ca_file, *ca_dir; /* context-only */ const char *cert; const char *key; diff --git a/src/login-common/ssl-proxy-openssl.c b/src/login-common/ssl-proxy-openssl.c index 8ec7b68422..ef72b3865d 100644 --- a/src/login-common/ssl-proxy-openssl.c +++ b/src/login-common/ssl-proxy-openssl.c @@ -91,6 +91,7 @@ struct ssl_server_context { const char *ca; const char *dh; const char *cipher_list; + const char *curve_list; const char *protocols; bool verify_client_cert; bool prefer_server_ciphers; @@ -158,6 +159,8 @@ static int ssl_server_context_cmp(const struct ssl_server_context *ctx1, return 1; if (null_strcmp(ctx1->cipher_list, ctx2->cipher_list) != 0) return 1; + if (null_strcmp(ctx1->curve_list, ctx2->curve_list) != 0) + return 1; if (null_strcmp(ctx1->protocols, ctx2->protocols) != 0) return 1; @@ -513,6 +516,7 @@ ssl_server_context_get(const struct login_settings *login_set, lookup_ctx.key = set->ssl_key; lookup_ctx.ca = set->ssl_ca; lookup_ctx.cipher_list = set->ssl_cipher_list; + lookup_ctx.curve_list = set->ssl_curve_list; lookup_ctx.protocols = set->ssl_protocols; lookup_ctx.verify_client_cert = set->ssl_verify_client_cert || login_set->auth_ssl_require_client_cert || @@ -1176,6 +1180,7 @@ ssl_server_context_init(const struct login_settings *login_set, ctx->ca = p_strdup(pool, ssl_set->ssl_ca); ctx->dh = p_strdup(pool, ssl_set->ssl_dh); ctx->cipher_list = p_strdup(pool, ssl_set->ssl_cipher_list); + ctx->curve_list = p_strdup(pool, ssl_set->ssl_curve_list); ctx->protocols = p_strdup(pool, ssl_set->ssl_protocols); ctx->verify_client_cert = ssl_set->ssl_verify_client_cert || login_set->auth_ssl_require_client_cert || @@ -1197,6 +1202,13 @@ ssl_server_context_init(const struct login_settings *login_set, SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); SSL_CTX_set_options(ssl_ctx, openssl_get_protocol_options(ctx->protocols)); +#ifdef HAVE_SSL_CTX_SET1_CURVES_LIST + if (ctx->curve_list != NULL && strlen(ctx->curve_list) > 0 && + SSL_CTX_set1_curves_list(ssl_ctx, ctx->curve_list) != 1) { + i_fatal("Failed to set curve list to '%s'", ctx->curve_list); + } +#endif + if (ssl_proxy_ctx_use_certificate_chain(ctx->ctx, ctx->cert) != 1) { i_fatal("Can't load ssl_cert: %s", openssl_iostream_use_certificate_error(ctx->cert, "ssl_cert"));