dovecot-2.2: lib-ssl-iostream: Added support for ECDH/ECDHE ciph...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jul 10 08:58:48 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/dc99912e5047
changeset: 16590:dc99912e5047
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jul 10 08:58:36 2013 +0300
description:
lib-ssl-iostream: Added support for ECDH/ECDHE cipher suites
Based on the login-common patch by David Hicks.

diffstat:

 src/lib-ssl-iostream/iostream-openssl-context.c |  83 ++++++++++++++++++++++++-
 1 files changed, 80 insertions(+), 3 deletions(-)

diffs (100 lines):

diff -r ac0dd2fbdbf0 -r dc99912e5047 src/lib-ssl-iostream/iostream-openssl-context.c
--- a/src/lib-ssl-iostream/iostream-openssl-context.c	Wed Jul 10 08:47:49 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-openssl-context.c	Wed Jul 10 08:58:36 2013 +0300
@@ -406,6 +406,84 @@
 	return 0;
 }
 
+#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10002000L
+static int
+ssl_proxy_ctx_get_pkey_ec_curve_name(const struct ssl_iostream_settings *set,
+				     int *nid_r, const char **error_r)
+{
+	int nid = 0;
+	EVP_PKEY *pkey;
+	const char *password;
+	EC_KEY *eckey;
+	const EC_GROUP *ecgrp;
+
+	password = set->key_password[0] != '\0' ? set->key_password : NULL;
+	if (openssl_iostream_load_key(set, &pkey, error_r) < 0)
+		return -1;
+
+	if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) != NULL &&
+	    (ecgrp = EC_KEY_get0_group(eckey)) != NULL)
+		nid = EC_GROUP_get_curve_name(ecgrp);
+	EVP_PKEY_free(pkey);
+
+	*nid_r = nid;
+	return 0;
+}
+#endif
+
+static int
+ssl_proxy_ctx_set_crypto_params(SSL_CTX *ssl_ctx,
+				const struct ssl_iostream_settings *set,
+				const char **error_r)
+{
+#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10002000L
+	EC_KEY *ecdh;
+	int nid;
+	const char *curve_name;
+#endif
+	if (SSL_CTX_need_tmp_RSA(ssl_ctx))
+		SSL_CTX_set_tmp_rsa_callback(ssl_ctx, ssl_gen_rsa_key);
+	SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_tmp_dh_callback);
+#if !defined(OPENSSL_NO_ECDH)
+	/* In the non-recommended situation where ECDH cipher suites are being
+	   used instead of ECDHE, do not reuse the same ECDH key pair for
+	   different sessions. This option improves forward secrecy. */
+	SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
+#endif
+#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10002000L
+	/* OpenSSL >= 1.0.2 automatically handles ECDH temporary key parameter
+	   selection. */
+	SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
+#elif !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
+	/* For OpenSSL < 1.0.2, ECDH temporary key parameter selection must be
+	   performed manually. Attempt to select the same curve as that used
+	   in the server's private EC key file. Otherwise fall back to the
+	   NIST P-384 (secp384r1) curve to be compliant with RFC 6460 when
+	   AES-256 TLS cipher suites are in use. This fall back option does
+	   however make Dovecot non-compliant with RFC 6460 which requires
+	   curve NIST P-256 (prime256v1) be used when AES-128 TLS cipher
+	   suites are in use. At least the non-compliance is in the form of
+	   providing too much security rather than too little. */
+	if (ssl_proxy_ctx_get_pkey_ec_curve_name(set, &nid, error_r) < 0)
+		return -1;
+	ecdh = EC_KEY_new_by_curve_name(nid);
+	if (ecdh == NULL) {
+		/* Fall back option */
+		nid = NID_secp384r1;
+		ecdh = EC_KEY_new_by_curve_name(nid);
+	}
+	if ((curve_name = OBJ_nid2sn(nid)) != NULL && set->verbose) {
+		i_debug("SSL: elliptic curve %s will be used for ECDH and"
+			" ECDHE key exchanges", curve_name);
+	}
+	if (ecdh != NULL) {
+		SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
+		EC_KEY_free(ecdh);
+	}
+#endif
+	return 0;
+}
+
 static int
 ssl_iostream_context_init_common(struct ssl_iostream_context *ctx,
 				 const struct ssl_iostream_settings *set,
@@ -417,9 +495,8 @@
 	   makes SSL more vulnerable against attacks */
 	SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 |
 			    (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
-	if (SSL_CTX_need_tmp_RSA(ctx->ssl_ctx))
-		SSL_CTX_set_tmp_rsa_callback(ctx->ssl_ctx, ssl_gen_rsa_key);
-	SSL_CTX_set_tmp_dh_callback(ctx->ssl_ctx, ssl_tmp_dh_callback);
+	if (ssl_proxy_ctx_set_crypto_params(ctx->ssl_ctx, set, error_r) < 0)
+		return -1;
 
 	return ssl_iostream_context_set(ctx, set, error_r);
 }


More information about the dovecot-cvs mailing list