$NetBSD: patch-its7595,v 1.2 2017/06/02 08:29:56 adam Exp $

ECDH support from upstream

From e631ce808ed56119e61321463d06db7999ba5a08 Mon Sep 17 00:00:00 2001
From: Howard Chu <hyc@openldap.org>
Date: Sat, 7 Sep 2013 09:47:19 -0700
Subject: [PATCH] ITS#7595 Add Elliptic Curve support for OpenSSL

From 9562ad00bd7f965df721bc22ac905bc759298a27 Mon Sep 17 00:00:00 2001
From: Howard Chu <hyc@openldap.org>
Date: Sat, 7 Sep 2013 10:13:40 -0700
Subject: [PATCH] ITS#7595 more doc for elliptic curve

From 721e46fe6695077d63a3df6ea2e397920a72308d Mon Sep 17 00:00:00 2001
From: Howard Chu <hyc@openldap.org>
Date: Sun, 8 Sep 2013 06:32:23 -0700
Subject: [PATCH] ITS#7595 don't try to use EC if OpenSSL lacks it

--- doc/guide/admin/tls.sdf.orig
+++ doc/guide/admin/tls.sdf
@@ -203,6 +203,18 @@
 
 This directive is ignored with Mozilla NSS.
 
+H4: TLSECName <name>
+
+This directive specifies the curve to use for Elliptic Curve
+Diffie-Hellman ephemeral key exchange.  This is required in order
+to use ECDHE-based cipher suites in OpenSSL.  The names of supported
+curves may be shown using the following command
+
+>	openssl ecparam -list_curves
+
+This directive is not used for GnuTLS and is ignored with Mozilla NSS.
+For GnuTLS the curves may be specified in the ciphersuite.
+
 H4: TLSVerifyClient { never | allow | try | demand }
 
 This directive specifies what checks to perform on client certificates
--- doc/man/man5/slapd-config.5.orig
+++ doc/man/man5/slapd-config.5
@@ -922,6 +922,13 @@
 When using Mozilla NSS these parameters are always generated randomly
 so this directive is ignored.
 .TP
+.B olcTLSECName: <name>
+Specify the name of a curve to use for Elliptic curve Diffie-Hellman
+ephemeral key exchange.  This is required to enable ECDHE algorithms in
+OpenSSL.  This option is not used with GnuTLS; the curves may be
+chosen in the GnuTLS ciphersuite specification. This option is also
+ignored for Mozilla NSS.
+.TP
 .B olcTLSProtocolMin: <major>[.<minor>]
 Specifies minimum SSL/TLS protocol version that will be negotiated.
 If the server doesn't support at least that version,
--- doc/man/man5/slapd.conf.5.orig
+++ doc/man/man5/slapd.conf.5
@@ -1153,6 +1153,13 @@
 When using Mozilla NSS these parameters are always generated randomly
 so this directive is ignored.
 .TP
+.B TLSECName <name>
+Specify the name of a curve to use for Elliptic curve Diffie-Hellman
+ephemeral key exchange.  This is required to enable ECDHE algorithms in
+OpenSSL.  This option is not used with GnuTLS; the curves may be
+chosen in the GnuTLS ciphersuite specification. This option is also
+ignored for Mozilla NSS.
+.TP
 .B TLSProtocolMin <major>[.<minor>]
 Specifies minimum SSL/TLS protocol version that will be negotiated.
 If the server doesn't support at least that version,
--- include/ldap.h.orig
+++ include/ldap.h
@@ -158,6 +158,7 @@
 #define LDAP_OPT_X_TLS_NEWCTX		0x600f
 #define LDAP_OPT_X_TLS_CRLFILE		0x6010	/* GNUtls only */
 #define LDAP_OPT_X_TLS_PACKAGE		0x6011
+#define LDAP_OPT_X_TLS_ECNAME		0x6012
 
 #define LDAP_OPT_X_TLS_NEVER	0
 #define LDAP_OPT_X_TLS_HARD		1
--- libraries/libldap/ldap-int.h.orig
+++ libraries/libldap/ldap-int.h
@@ -165,6 +165,7 @@
 	char		*lt_ciphersuite;
 	char		*lt_crlfile;
 	char		*lt_randfile;	/* OpenSSL only */
+	char		*lt_ecname;		/* OpenSSL only */
 	int		lt_protocol_min;
 };
 #endif
@@ -250,6 +251,7 @@
 #define ldo_tls_certfile	ldo_tls_info.lt_certfile
 #define ldo_tls_keyfile	ldo_tls_info.lt_keyfile
 #define ldo_tls_dhfile	ldo_tls_info.lt_dhfile
+#define ldo_tls_ecname	ldo_tls_info.lt_ecname
 #define ldo_tls_cacertfile	ldo_tls_info.lt_cacertfile
 #define ldo_tls_cacertdir	ldo_tls_info.lt_cacertdir
 #define ldo_tls_ciphersuite	ldo_tls_info.lt_ciphersuite
--- libraries/libldap/tls2.c.orig
+++ libraries/libldap/tls2.c
@@ -118,6 +118,10 @@
 		LDAP_FREE( lo->ldo_tls_dhfile );
 		lo->ldo_tls_dhfile = NULL;
 	}
+	if ( lo->ldo_tls_ecname ) {
+		LDAP_FREE( lo->ldo_tls_ecname );
+		lo->ldo_tls_ecname = NULL;
+	}
 	if ( lo->ldo_tls_cacertfile ) {
 		LDAP_FREE( lo->ldo_tls_cacertfile );
 		lo->ldo_tls_cacertfile = NULL;
@@ -232,6 +236,10 @@
 		lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile );
 		__atoe( lts.lt_dhfile );
 	}
+	if ( lts.lt_ecname ) {
+		lts.lt_ecname = LDAP_STRDUP( lts.lt_ecname );
+		__atoe( lts.lt_ecname );
+	}
 #endif
 	lo->ldo_tls_ctx = ti->ti_ctx_new( lo );
 	if ( lo->ldo_tls_ctx == NULL ) {
@@ -257,6 +265,7 @@
 	LDAP_FREE( lts.lt_crlfile );
 	LDAP_FREE( lts.lt_cacertdir );
 	LDAP_FREE( lts.lt_dhfile );
+	LDAP_FREE( lts.lt_ecname );
 #endif
 	return rc;
 }
@@ -634,6 +643,10 @@
 		*(char **)arg = lo->ldo_tls_dhfile ?
 			LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
 		break;
+	case LDAP_OPT_X_TLS_ECNAME:
+		*(char **)arg = lo->ldo_tls_ecname ?
+			LDAP_STRDUP( lo->ldo_tls_ecname ) : NULL;
+		break;
 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
 		*(char **)arg = lo->ldo_tls_crlfile ?
 			LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
@@ -753,6 +766,10 @@
 		if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
 		lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
 		return 0;
+	case LDAP_OPT_X_TLS_ECNAME:
+		if ( lo->ldo_tls_ecname ) LDAP_FREE( lo->ldo_tls_ecname );
+		lo->ldo_tls_ecname = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
+		return 0;
 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
 		if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
 		lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
--- libraries/libldap/tls_o.c.orig
+++ libraries/libldap/tls_o.c
@@ -327,10 +327,9 @@
 		return -1;
 	}
 
-	if ( lo->ldo_tls_dhfile ) {
-		DH *dh = NULL;
+	if ( is_server && lo->ldo_tls_dhfile ) {
+		DH *dh;
 		BIO *bio;
-		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
 
 		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
 			Debug( LDAP_DEBUG_ANY,
@@ -349,6 +348,38 @@
 		}
 		BIO_free( bio );
 		SSL_CTX_set_tmp_dh( ctx, dh );
+		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
+		DH_free( dh );
+	}
+
+	if ( is_server && lo->ldo_tls_ecname ) {
+#ifdef OPENSSL_NO_EC
+		Debug( LDAP_DEBUG_ANY,
+			"TLS: Elliptic Curves not supported.\n", 0,0,0 );
+		return -1;
+#else
+		EC_KEY *ecdh;
+
+		int nid = OBJ_sn2nid( lt->lt_ecname );
+		if ( nid == NID_undef ) {
+			Debug( LDAP_DEBUG_ANY,
+				"TLS: could not use EC name `%s'.\n",
+				lo->ldo_tls_ecname,0,0);
+			tlso_report_error();
+			return -1;
+		}
+		ecdh = EC_KEY_new_by_curve_name( nid );
+		if ( ecdh == NULL ) {
+			Debug( LDAP_DEBUG_ANY,
+				"TLS: could not generate key for EC name `%s'.\n",
+				lo->ldo_tls_ecname,0,0);
+			tlso_report_error();
+			return -1;
+		}
+		SSL_CTX_set_tmp_ecdh( ctx, ecdh );
+		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE );
+		EC_KEY_free( ecdh );
+#endif
 	}
 
 	if ( tlso_opt_trace ) {
--- servers/slapd/bconfig.c.orig
+++ servers/slapd/bconfig.c
@@ -194,6 +194,7 @@
 	CFG_ACL_ADD,
 	CFG_SYNC_SUBENTRY,
 	CFG_LTHREADS,
+	CFG_TLS_ECNAME,
 
 	CFG_LAST
 };
@@ -738,6 +739,14 @@
 #endif
 		"( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' "
 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+	{ "TLSECName", NULL, 2, 2, 0,
+#ifdef HAVE_TLS
+		CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, &config_tls_option,
+#else
+		ARG_IGNORED, NULL,
+#endif
+		"( OLcfgGlAt:96 NAME 'olcTLSECName' "
+			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
 	{ "TLSProtocolMin",	NULL, 2, 2, 0,
 #ifdef HAVE_TLS
 		CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config,
@@ -819,7 +828,7 @@
 		 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
 		 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
 		 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
-		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
+		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ olcTLSECName $ "
 		 "olcTLSCRLFile $ olcTLSProtocolMin $ olcToolThreads $ olcWriteTimeout $ "
 		 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
 		 "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
@@ -3824,6 +3833,7 @@
 	case CFG_TLS_CA_PATH:	flag = LDAP_OPT_X_TLS_CACERTDIR;	break;
 	case CFG_TLS_CA_FILE:	flag = LDAP_OPT_X_TLS_CACERTFILE;	break;
 	case CFG_TLS_DH_FILE:	flag = LDAP_OPT_X_TLS_DHFILE;	break;
+	case CFG_TLS_ECNAME:	flag = LDAP_OPT_X_TLS_ECNAME;	break;
 #ifdef HAVE_GNUTLS
 	case CFG_TLS_CRL_FILE:	flag = LDAP_OPT_X_TLS_CRLFILE;	break;
 #endif
