Blame SOURCES/openssl-1.0.1e-ecdh-auto.patch

83c29f
diff -up openssl-1.0.1e/apps/s_server.c.ecdh-auto openssl-1.0.1e/apps/s_server.c
83c29f
--- openssl-1.0.1e/apps/s_server.c.ecdh-auto	2014-09-17 15:52:01.659445244 +0200
83c29f
+++ openssl-1.0.1e/apps/s_server.c	2014-09-17 16:24:44.378754502 +0200
83c29f
@@ -1708,7 +1708,7 @@ bad:
83c29f
 		{
83c29f
 		EC_KEY *ecdh=NULL;
83c29f
 
83c29f
-		if (named_curve)
83c29f
+		if (named_curve && strcmp(named_curve, "auto"))
83c29f
 			{
83c29f
 			int nid = OBJ_sn2nid(named_curve);
83c29f
 
83c29f
@@ -1731,6 +1731,8 @@ bad:
83c29f
 			{
83c29f
 			BIO_printf(bio_s_out,"Setting temp ECDH parameters\n");
83c29f
 			}
83c29f
+		else if (named_curve)
83c29f
+			SSL_CTX_set_ecdh_auto(ctx, 1);
83c29f
 		else
83c29f
 			{
83c29f
 			BIO_printf(bio_s_out,"Using default temp ECDH parameters\n");
83c29f
diff -up openssl-1.0.1e/ssl/ssl_cert.c.ecdh-auto openssl-1.0.1e/ssl/ssl_cert.c
83c29f
--- openssl-1.0.1e/ssl/ssl_cert.c.ecdh-auto	2013-02-11 16:26:04.000000000 +0100
83c29f
+++ openssl-1.0.1e/ssl/ssl_cert.c	2014-09-17 16:20:24.355884360 +0200
83c29f
@@ -270,6 +270,7 @@ CERT *ssl_cert_dup(CERT *cert)
83c29f
 			}
83c29f
 		}
83c29f
 	ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
83c29f
+	ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
83c29f
 #endif
83c29f
 
83c29f
 	for (i = 0; i < SSL_PKEY_NUM; i++)
83c29f
diff -up openssl-1.0.1e/ssl/ssl.h.ecdh-auto openssl-1.0.1e/ssl/ssl.h
83c29f
--- openssl-1.0.1e/ssl/ssl.h.ecdh-auto	2014-09-17 16:20:24.354884336 +0200
83c29f
+++ openssl-1.0.1e/ssl/ssl.h	2014-09-17 16:49:29.135273514 +0200
83c29f
@@ -1563,6 +1563,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
83c29f
 #define SSL_CTRL_GET_EXTRA_CHAIN_CERTS		82
83c29f
 #define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS	83
83c29f
 
83c29f
+#define SSL_CTRL_SET_ECDH_AUTO			94
83c29f
 #define SSL_CTRL_GET_SERVER_TMP_KEY		109
83c29f
 
83c29f
 #define DTLSv1_get_timeout(ssl, arg) \
83c29f
@@ -1606,6 +1607,11 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
83c29f
 #define SSL_CTX_clear_extra_chain_certs(ctx) \
83c29f
 	SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
83c29f
 
83c29f
+#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
83c29f
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)
83c29f
+#define SSL_set_ecdh_auto(s, onoff) \
83c29f
+	SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)
83c29f
+
83c29f
 #define SSL_get_server_tmp_key(s, pk) \
83c29f
 	SSL_ctrl(s,SSL_CTRL_GET_SERVER_TMP_KEY,0,pk)
83c29f
 
83c29f
diff -up openssl-1.0.1e/ssl/ssl_lib.c.ecdh-auto openssl-1.0.1e/ssl/ssl_lib.c
83c29f
--- openssl-1.0.1e/ssl/ssl_lib.c.ecdh-auto	2014-09-17 15:52:01.616444274 +0200
83c29f
+++ openssl-1.0.1e/ssl/ssl_lib.c	2014-09-17 16:20:24.356884383 +0200
83c29f
@@ -2045,7 +2045,7 @@ void ssl_set_cert_masks(CERT *c, const S
83c29f
 #endif
83c29f
 
83c29f
 #ifndef OPENSSL_NO_ECDH
83c29f
-	have_ecdh_tmp=(c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL);
83c29f
+	have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
83c29f
 #endif
83c29f
 	cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
83c29f
 	rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL);
83c29f
diff -up openssl-1.0.1e/ssl/ssl_locl.h.ecdh-auto openssl-1.0.1e/ssl/ssl_locl.h
83c29f
--- openssl-1.0.1e/ssl/ssl_locl.h.ecdh-auto	2014-09-17 15:52:01.632444635 +0200
83c29f
+++ openssl-1.0.1e/ssl/ssl_locl.h	2014-09-17 17:26:29.764405189 +0200
83c29f
@@ -511,6 +511,8 @@ typedef struct cert_st
83c29f
 	EC_KEY *ecdh_tmp;
83c29f
 	/* Callback for generating ephemeral ECDH keys */
83c29f
 	EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
83c29f
+	/* Select ECDH parameters automatically */
83c29f
+	int ecdh_tmp_auto;
83c29f
 #endif
83c29f
 
83c29f
 	CERT_PKEY pkeys[SSL_PKEY_NUM];
83c29f
@@ -1091,6 +1093,7 @@ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_CO
83c29f
 #ifndef OPENSSL_NO_EC
83c29f
 int tls1_ec_curve_id2nid(int curve_id);
83c29f
 int tls1_ec_nid2curve_id(int nid);
83c29f
+int tls1_shared_curve(SSL *s, int nmatch);
83c29f
 #endif /* OPENSSL_NO_EC */
83c29f
 
83c29f
 #ifndef OPENSSL_NO_TLSEXT
83c29f
diff -up openssl-1.0.1e/ssl/s3_lib.c.ecdh-auto openssl-1.0.1e/ssl/s3_lib.c
83c29f
--- openssl-1.0.1e/ssl/s3_lib.c.ecdh-auto	2014-09-17 16:20:24.352884288 +0200
83c29f
+++ openssl-1.0.1e/ssl/s3_lib.c	2014-09-17 17:37:26.274226185 +0200
83c29f
@@ -3350,6 +3350,12 @@ long ssl3_ctrl(SSL *s, int cmd, long lar
83c29f
 #endif
83c29f
 
83c29f
 #endif /* !OPENSSL_NO_TLSEXT */
83c29f
+
83c29f
+#ifndef OPENSSL_NO_EC
83c29f
+	case SSL_CTRL_SET_ECDH_AUTO:
83c29f
+		s->cert->ecdh_tmp_auto = larg;
83c29f
+		return 1;
83c29f
+#endif
83c29f
 	case SSL_CTRL_GET_SERVER_TMP_KEY:
83c29f
 		if (s->server || !s->session || !s->session->sess_cert)
83c29f
 			return 0;
83c29f
@@ -3651,6 +3657,12 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd
83c29f
 		ctx->srp_ctx.strength=larg;
83c29f
 		break;
83c29f
 #endif
83c29f
+
83c29f
+#ifndef OPENSSL_NO_EC
83c29f
+	case SSL_CTRL_SET_ECDH_AUTO:
83c29f
+		ctx->cert->ecdh_tmp_auto = larg;
83c29f
+		return 1;
83c29f
+#endif
83c29f
 #endif /* !OPENSSL_NO_TLSEXT */
83c29f
 
83c29f
 	/* A Thawte special :-) */
83c29f
@@ -4003,6 +4015,14 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, S
83c29f
 		if (
83c29f
 			/* if we are considering an ECC cipher suite that uses an ephemeral EC key */
83c29f
 			(alg_k & SSL_kEECDH)
83c29f
+			&& (s->cert->ecdh_tmp_auto)
83c29f
+		)
83c29f
+			{
83c29f
+			ok = ok && tls1_shared_curve(s, 0);
83c29f
+			}
83c29f
+		else if (
83c29f
+			/* if we are considering an ECC cipher suite that uses an ephemeral EC key */
83c29f
+			(alg_k & SSL_kEECDH)
83c29f
 			/* and we have an ephemeral EC key */
83c29f
 			&& (s->cert->ecdh_tmp != NULL)
83c29f
 			/* and the client specified an EllipticCurves extension */
83c29f
diff -up openssl-1.0.1e/ssl/s3_srvr.c.ecdh-auto openssl-1.0.1e/ssl/s3_srvr.c
83c29f
--- openssl-1.0.1e/ssl/s3_srvr.c.ecdh-auto	2014-09-17 15:52:01.644444906 +0200
83c29f
+++ openssl-1.0.1e/ssl/s3_srvr.c	2014-09-17 16:20:24.353884312 +0200
83c29f
@@ -1693,7 +1693,14 @@ int ssl3_send_server_key_exchange(SSL *s
83c29f
 			const EC_GROUP *group;
83c29f
 
83c29f
 			ecdhp=cert->ecdh_tmp;
83c29f
-			if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
83c29f
+			if (s->cert->ecdh_tmp_auto)
83c29f
+				{
83c29f
+				/* Get NID of first shared curve */
83c29f
+				int nid = tls1_shared_curve(s, 0);
83c29f
+				if (nid != NID_undef)
83c29f
+					ecdhp = EC_KEY_new_by_curve_name(nid);
83c29f
+				}
83c29f
+			else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb)
83c29f
 				{
83c29f
 				ecdhp=s->cert->ecdh_tmp_cb(s,
83c29f
 				      SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
83c29f
@@ -1718,7 +1725,9 @@ int ssl3_send_server_key_exchange(SSL *s
83c29f
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
83c29f
 				goto err;
83c29f
 				}
83c29f
-			if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
83c29f
+			if (s->cert->ecdh_tmp_auto)
83c29f
+				ecdh = ecdhp;
83c29f
+			else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
83c29f
 				{
83c29f
 				SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
83c29f
 				goto err;
83c29f
diff -up openssl-1.0.1e/ssl/t1_lib.c.ecdh-auto openssl-1.0.1e/ssl/t1_lib.c
83c29f
--- openssl-1.0.1e/ssl/t1_lib.c.ecdh-auto	2014-09-17 16:20:24.358884427 +0200
83c29f
+++ openssl-1.0.1e/ssl/t1_lib.c	2014-09-17 17:32:04.054951942 +0200
83c29f
@@ -202,6 +202,13 @@ static int nid_list[] =
83c29f
 		NID_secp521r1  /* secp521r1 (25) */	
83c29f
 	};
83c29f
 
83c29f
+static const unsigned char eccurves_default[] =
83c29f
+	{
83c29f
+		0,23, /* secp256r1 (23) */ 
83c29f
+		0,24, /* secp384r1 (24) */
83c29f
+		0,25, /* secp521r1 (25) */	
83c29f
+	};
83c29f
+
83c29f
 static int pref_list[] =
83c29f
 	{
83c29f
 		NID_secp521r1, /* secp521r1 (25) */	
83c29f
@@ -277,6 +284,69 @@ int tls1_ec_nid2curve_id(int nid)
83c29f
 		return 0;
83c29f
 		}
83c29f
 	}
83c29f
+/* Get curves list, if "sess" is set return client curves otherwise
83c29f
+ * preferred list
83c29f
+ */
83c29f
+static void tls1_get_curvelist(SSL *s, int sess,
83c29f
+					const unsigned char **pcurves,
83c29f
+					size_t *pcurveslen)
83c29f
+	{
83c29f
+	if (sess)
83c29f
+		{
83c29f
+		*pcurves = s->session->tlsext_ellipticcurvelist;
83c29f
+		*pcurveslen = s->session->tlsext_ellipticcurvelist_length;
83c29f
+		}
83c29f
+	else
83c29f
+		{
83c29f
+		*pcurves = s->tlsext_ellipticcurvelist;
83c29f
+		*pcurveslen = s->tlsext_ellipticcurvelist_length;
83c29f
+		}
83c29f
+	if (!*pcurves)
83c29f
+		{
83c29f
+		*pcurves = eccurves_default;
83c29f
+		*pcurveslen = sizeof(eccurves_default);
83c29f
+		}
83c29f
+	}
83c29f
+/* Return nth shared curve. If nmatch == -1 return number of
83c29f
+ * matches.
83c29f
+ */
83c29f
+
83c29f
+int tls1_shared_curve(SSL *s, int nmatch)
83c29f
+	{
83c29f
+	const unsigned char *pref, *supp;
83c29f
+	size_t preflen, supplen, i, j;
83c29f
+	int k;
83c29f
+	/* Can't do anything on client side */
83c29f
+	if (s->server == 0)
83c29f
+		return -1;
83c29f
+	tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
83c29f
+				&supp, &supplen);
83c29f
+	tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
83c29f
+				&pref, &preflen);
83c29f
+	preflen /= 2;
83c29f
+	supplen /= 2;
83c29f
+	k = 0;
83c29f
+	for (i = 0; i < preflen; i++, pref+=2)
83c29f
+		{
83c29f
+		const unsigned char *tsupp = supp;
83c29f
+		for (j = 0; j < supplen; j++, tsupp+=2)
83c29f
+			{
83c29f
+			if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
83c29f
+				{
83c29f
+				if (nmatch == k)
83c29f
+					{
83c29f
+					int id = (pref[0] << 8) | pref[1];
83c29f
+					return tls1_ec_curve_id2nid(id);
83c29f
+					}
83c29f
+				k++;
83c29f
+				}
83c29f
+			}
83c29f
+		}
83c29f
+	if (nmatch == -1)
83c29f
+		return k;
83c29f
+	return 0;
83c29f
+	}
83c29f
+
83c29f
 #endif /* OPENSSL_NO_EC */
83c29f
 
83c29f
 #ifndef OPENSSL_NO_TLSEXT