]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
ssl: add ssl_curve_list setting for selecting ECHDE curves
authorJuha Koho <juha.koho@trineco.fi>
Mon, 10 Oct 2016 22:13:49 +0000 (00:13 +0200)
committerMartti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
Thu, 19 Jan 2017 15:17:53 +0000 (17:17 +0200)
doc/example-config/conf.d/10-ssl.conf
m4/ssl.m4
src/lib-master/master-service-ssl-settings.c
src/lib-master/master-service-ssl-settings.h
src/lib-master/master-service-ssl.c
src/lib-ssl-iostream/iostream-openssl-context.c
src/lib-ssl-iostream/iostream-openssl.c
src/lib-ssl-iostream/iostream-ssl.c
src/lib-ssl-iostream/iostream-ssl.h
src/login-common/ssl-proxy-openssl.c

index a70cbdb4b106ceaa2f4e37b3e3b6a71ec8e86d09..cb77799e2c386b4bd8b8dffb13bf9ab39eb42314 100644 (file)
@@ -57,6 +57,11 @@ ssl_key = </etc/ssl/private/dovecot.pem
 # SSL ciphers to use
 #ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL
 
+# Colon separated list of elliptic curves to use. Empty value (the default)
+# means use the defaults from the SSL library. P-521:P-384:P-256 would be an
+# example of a valid value.
+#ssl_curve_list =
+
 # Prefer the server's order of ciphers over client's.
 #ssl_prefer_server_ciphers = no
 
index cdddda0def2a8c1429de80d6abe3fbe5e68978df..6cd63291046088b7f3efc13ac3151623c9139d6a 100644 (file)
--- a/m4/ssl.m4
+++ b/m4/ssl.m4
@@ -60,6 +60,26 @@ AC_DEFUN([DOVECOT_SSL], [
       if test $i_cv_have_ssl_clear_options = yes; then
         AC_DEFINE(HAVE_SSL_CLEAR_OPTIONS,, [Define if you have SSL_clear_options])
       fi
+
+      # SSL_CTX_set1_curves_list is a macro so plain AC_CHECK_LIB fails here.
+      AC_CACHE_CHECK([whether SSL_CTX_set1_curves_list exists],i_cv_have_ssl_ctx_set1_curves_list,[
+        old_LIBS=$LIBS
+        LIBS="$LIBS -lssl"
+        AC_TRY_LINK([
+          #include <openssl/ssl.h>
+        ], [
+          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)
index 65a972f310cad571f3caa1685ee5442ffc3e19f5..fb6cd16cff187fa95ebc4a1300435b964b5d861d 100644 (file)
@@ -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
 }
index 8cd3f063a484a51694a0959e3240097ae74a97cc..484830ea6718c18d2e2f1f262e85653c890d00c3 100644 (file)
@@ -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;
index 93cd277baaede2c568c6d42f3c39b65384b1c060..07e97d1d70334a4ba841e9fbc9659ff40acd8aaa 100644 (file)
@@ -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;
index 998a3463a73f86561f0cd7341f4683b27673bcea..10f44107f828e197c3d3f96443e2a51c9fa9de73 100644 (file)
@@ -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);
index 17135aabb3bf06bf78433447ad3503b3e9060a48..713128ad25bffca42099e2d4c11aea935e75b346 100644 (file)
@@ -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) {
index 90e46a7c543ba52a42f8acfd0912c3e521ff5de8..77ff2d81a02206de22050e4ff68031ee6b955be9 100644 (file)
@@ -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);
index d4ca6cba2b98776855cd6520cd12f2320d9bea84..eeefa544f41b51abfb3ee168ca3b8d109d0d274e 100644 (file)
@@ -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;
index 8ec7b684224c3c0a3474d44da7ddd535b7ecb74b..ef72b3865d01e3585de1300dd738afcad0f0e3c8 100644 (file)
@@ -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"));