# 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
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)
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),
.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
}
}
+#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
}
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;
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;
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);
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) {
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);
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;
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;
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;
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 ||
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 ||
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"));