MINOR: ssl: add elliptic curve Diffie-Hellman support for ssl key generation

Add 'ecdhe' on 'bind' statement: to set named curve used to generate ECDHE keys
(ex: ecdhe secp521r1)
diff --git a/include/types/listener.h b/include/types/listener.h
index 82f23f1..a6b81f4 100644
--- a/include/types/listener.h
+++ b/include/types/listener.h
@@ -97,6 +97,7 @@
 struct bind_conf {
 #ifdef USE_OPENSSL
 	char *ciphers;             /* cipher suite to use if non-null */
+	char *ecdhe;               /* named curve to use for ECDHE */
 	int nosslv3;               /* disable SSLv3 */
 	int notlsv1;               /* disable TLSv1 */
 	int prefer_server_ciphers; /* Prefer server ciphers */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 8a04499..2afd5e7 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6600,6 +6600,7 @@
 #ifdef USE_OPENSSL
 			ssl_sock_free_all_ctx(bind_conf);
 			free(bind_conf->ciphers);
+			free(bind_conf->ecdhe);
 #endif /* USE_OPENSSL */
 		}
 
diff --git a/src/haproxy.c b/src/haproxy.c
index 767ac2e..8b06743 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -1038,6 +1038,7 @@
 #ifdef USE_OPENSSL
 			ssl_sock_free_all_ctx(bind_conf);
 			free(bind_conf->ciphers);
+			free(bind_conf->ecdhe);
 #endif /* USE_OPENSSL */
 			free(bind_conf->file);
 			free(bind_conf->arg);
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 5a7f01d..abaef02 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -389,12 +389,18 @@
 #ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   /* needs OpenSSL >= 0.9.7 */
 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
 #endif
+#ifndef SSL_OP_SINGLE_ECDH_USE                          /* needs OpenSSL >= 0.9.8 */
+#define SSL_OP_SINGLE_ECDH_USE 0
+#endif
 #ifndef SSL_OP_NO_COMPRESSION                           /* needs OpenSSL >= 0.9.9 */
 #define SSL_OP_NO_COMPRESSION 0
 #endif
 #ifndef SSL_OP_SINGLE_DH_USE                            /* needs OpenSSL >= 0.9.6 */
 #define SSL_OP_SINGLE_DH_USE 0
 #endif
+#ifndef SSL_OP_SINGLE_ECDH_USE                            /* needs OpenSSL >= 1.0.0 */
+#define SSL_OP_SINGLE_ECDH_USE 0
+#endif
 #ifndef SSL_MODE_RELEASE_BUFFERS                        /* needs OpenSSL >= 1.0.0 */
 #define SSL_MODE_RELEASE_BUFFERS 0
 #endif
@@ -406,6 +412,7 @@
 		SSL_OP_NO_SSLv2 |
 		SSL_OP_NO_COMPRESSION |
 		SSL_OP_SINGLE_DH_USE |
+		SSL_OP_SINGLE_ECDH_USE |
 		SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
 	int sslmode =
 		SSL_MODE_ENABLE_PARTIAL_WRITE |
@@ -436,6 +443,24 @@
 	SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
 	SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
 #endif
+#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
+	if (bind_conf->ecdhe) {
+		int i;
+		EC_KEY  *ecdh;
+
+		i = OBJ_sn2nid(bind_conf->ecdhe);
+		if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
+			Alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
+			      curproxy->id, bind_conf->ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
+			cfgerr++;
+		}
+		else {
+			SSL_CTX_set_tmp_ecdh(ctx, ecdh);
+			EC_KEY_free(ecdh);
+		}
+	}
+#endif
+
 	return cfgerr;
 }
 
@@ -884,8 +909,32 @@
 
 	if (ssl_sock_load_cert(args[cur_arg + 1], conf, px, err) > 0)
 		return ERR_ALERT | ERR_FATAL;
+
+	return 0;
+}
+
+/* parse the "ecdhe" bind keyword keywords */
+static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
+{
+#if OPENSSL_VERSION_NUMBER < 0x0090800fL
+	if (err)
+		memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
+	return ERR_ALERT | ERR_FATAL;
+#elif defined(OPENSSL_NO_ECDH)
+	if (err)
+		memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
+	return ERR_ALERT | ERR_FATAL;
+#else
+	if (!*args[cur_arg + 1]) {
+		if (err)
+			memprintf(err, "'%s' : missing named curve", args[cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	conf->ecdhe = strdup(args[cur_arg + 1]);
 
 	return 0;
+#endif
 }
 
 /* parse the "nosslv3" bind keyword */
@@ -951,12 +1000,13 @@
  * not enabled.
  */
 static struct bind_kw_list bind_kws = { "SSL", { }, {
-	{ "ciphers",               bind_parse_ciphers, 1 }, /* set SSL cipher suite */
-	{ "crt",                   bind_parse_crt,     1 }, /* load SSL certificates from this location */
-	{ "nosslv3",               bind_parse_nosslv3, 0 }, /* disable SSLv3 */
-	{ "notlsv1",               bind_parse_notlsv1, 0 }, /* disable TLSv1 */
-	{ "prefer-server-ciphers", bind_parse_psc,     0 }, /* prefer server ciphers */
-	{ "ssl",                   bind_parse_ssl,     0 }, /* enable SSL processing */
+	{ "ciphers",               bind_parse_ciphers,       1 }, /* set SSL cipher suite */
+	{ "crt",                   bind_parse_crt,           1 }, /* load SSL certificates from this location */
+	{ "ecdhe",                 bind_parse_ecdhe,         1 }, /* defines named curve for elliptic curve Diffie-Hellman */
+	{ "nosslv3",               bind_parse_nosslv3,       0 }, /* disable SSLv3 */
+	{ "notlsv1",               bind_parse_notlsv1,       0 }, /* disable TLSv1 */
+	{ "prefer-server-ciphers", bind_parse_psc,           0 }, /* prefer server ciphers */
+	{ "ssl",                   bind_parse_ssl,           0 }, /* enable SSL processing */
 	{ NULL, NULL, 0 },
 }};