Blame SOURCES/openldap-openssl-ITS7595-Add-EC-support-1.patch

3b9fe0
ITS#7595 Add Elliptic Curve support for OpenSSL
3b9fe0
3b9fe0
Cherry-picked upstream e631ce808ed56119e61321463d06db7999ba5a08
3b9fe0
Author:    Howard Chu <hyc@openldap.org>
3b9fe0
Date:      Sat Sep 7 09:47:19 2013 -0700
3b9fe0
3b9fe0
diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
3b9fe0
index 9c72e8296..2311c3096 100644
3b9fe0
--- a/doc/man/man5/slapd-config.5
3b9fe0
+++ b/doc/man/man5/slapd-config.5
3b9fe0
@@ -922,6 +922,13 @@ are not used.
3b9fe0
 When using Mozilla NSS these parameters are always generated randomly
3b9fe0
 so this directive is ignored.
3b9fe0
 .TP
3b9fe0
+.B olcTLSECName: <name>
3b9fe0
+Specify the name of a curve to use for Elliptic curve Diffie-Hellman
3b9fe0
+ephemeral key exchange.  This is required to enable ECDHE algorithms in
3b9fe0
+OpenSSL.  This option is not used with GnuTLS; the curves may be
3b9fe0
+chosen in the GnuTLS ciphersuite specification. This option is also
3b9fe0
+ignored for Mozilla NSS.
3b9fe0
+.TP
3b9fe0
 .B olcTLSProtocolMin: <major>[.<minor>]
3b9fe0
 Specifies minimum SSL/TLS protocol version that will be negotiated.
3b9fe0
 If the server doesn't support at least that version,
3b9fe0
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
3b9fe0
index f504adcf9..ef03e0ad8 100644
3b9fe0
--- a/doc/man/man5/slapd.conf.5
3b9fe0
+++ b/doc/man/man5/slapd.conf.5
3b9fe0
@@ -1153,6 +1153,13 @@ are not used.
3b9fe0
 When using Mozilla NSS these parameters are always generated randomly
3b9fe0
 so this directive is ignored.
3b9fe0
 .TP
3b9fe0
+.B TLSECName <name>
3b9fe0
+Specify the name of a curve to use for Elliptic curve Diffie-Hellman
3b9fe0
+ephemeral key exchange.  This is required to enable ECDHE algorithms in
3b9fe0
+OpenSSL.  This option is not used with GnuTLS; the curves may be
3b9fe0
+chosen in the GnuTLS ciphersuite specification. This option is also
3b9fe0
+ignored for Mozilla NSS.
3b9fe0
+.TP
3b9fe0
 .B TLSProtocolMin <major>[.<minor>]
3b9fe0
 Specifies minimum SSL/TLS protocol version that will be negotiated.
3b9fe0
 If the server doesn't support at least that version,
3b9fe0
diff --git a/include/ldap.h b/include/ldap.h
3b9fe0
index c245651c2..0964a193e 100644
3b9fe0
--- a/include/ldap.h
3b9fe0
+++ b/include/ldap.h
3b9fe0
@@ -158,6 +158,7 @@ LDAP_BEGIN_DECL
3b9fe0
 #define LDAP_OPT_X_TLS_NEWCTX		0x600f
3b9fe0
 #define LDAP_OPT_X_TLS_CRLFILE		0x6010	/* GNUtls only */
3b9fe0
 #define LDAP_OPT_X_TLS_PACKAGE		0x6011
3b9fe0
+#define LDAP_OPT_X_TLS_ECNAME		0x6012
3b9fe0
 
3b9fe0
 #define LDAP_OPT_X_TLS_NEVER	0
3b9fe0
 #define LDAP_OPT_X_TLS_HARD		1
3b9fe0
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
3b9fe0
index 66e04ae80..db7193f4f 100644
3b9fe0
--- a/libraries/libldap/ldap-int.h
3b9fe0
+++ b/libraries/libldap/ldap-int.h
3b9fe0
@@ -165,6 +165,7 @@ struct ldaptls {
3b9fe0
 	char		*lt_ciphersuite;
3b9fe0
 	char		*lt_crlfile;
3b9fe0
 	char		*lt_randfile;	/* OpenSSL only */
3b9fe0
+	char		*lt_ecname;		/* OpenSSL only */
3b9fe0
 	int		lt_protocol_min;
3b9fe0
 };
3b9fe0
 #endif
3b9fe0
@@ -250,6 +251,7 @@ struct ldapoptions {
3b9fe0
 #define ldo_tls_certfile	ldo_tls_info.lt_certfile
3b9fe0
 #define ldo_tls_keyfile	ldo_tls_info.lt_keyfile
3b9fe0
 #define ldo_tls_dhfile	ldo_tls_info.lt_dhfile
3b9fe0
+#define ldo_tls_ecname	ldo_tls_info.lt_ecname
3b9fe0
 #define ldo_tls_cacertfile	ldo_tls_info.lt_cacertfile
3b9fe0
 #define ldo_tls_cacertdir	ldo_tls_info.lt_cacertdir
3b9fe0
 #define ldo_tls_ciphersuite	ldo_tls_info.lt_ciphersuite
3b9fe0
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
3b9fe0
index d25c190ea..0451b01af 100644
3b9fe0
--- a/libraries/libldap/tls2.c
3b9fe0
+++ b/libraries/libldap/tls2.c
3b9fe0
@@ -118,6 +118,10 @@ ldap_int_tls_destroy( struct ldapoptions *lo )
3b9fe0
 		LDAP_FREE( lo->ldo_tls_dhfile );
3b9fe0
 		lo->ldo_tls_dhfile = NULL;
3b9fe0
 	}
3b9fe0
+	if ( lo->ldo_tls_ecname ) {
3b9fe0
+		LDAP_FREE( lo->ldo_tls_ecname );
3b9fe0
+		lo->ldo_tls_ecname = NULL;
3b9fe0
+	}
3b9fe0
 	if ( lo->ldo_tls_cacertfile ) {
3b9fe0
 		LDAP_FREE( lo->ldo_tls_cacertfile );
3b9fe0
 		lo->ldo_tls_cacertfile = NULL;
3b9fe0
@@ -232,6 +236,10 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
3b9fe0
 		lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile );
3b9fe0
 		__atoe( lts.lt_dhfile );
3b9fe0
 	}
3b9fe0
+	if ( lts.lt_ecname ) {
3b9fe0
+		lts.lt_ecname = LDAP_STRDUP( lts.lt_ecname );
3b9fe0
+		__atoe( lts.lt_ecname );
3b9fe0
+	}
3b9fe0
 #endif
3b9fe0
 	lo->ldo_tls_ctx = ti->ti_ctx_new( lo );
3b9fe0
 	if ( lo->ldo_tls_ctx == NULL ) {
3b9fe0
@@ -257,6 +265,7 @@ error_exit:
3b9fe0
 	LDAP_FREE( lts.lt_crlfile );
3b9fe0
 	LDAP_FREE( lts.lt_cacertdir );
3b9fe0
 	LDAP_FREE( lts.lt_dhfile );
3b9fe0
+	LDAP_FREE( lts.lt_ecname );
3b9fe0
 #endif
3b9fe0
 	return rc;
3b9fe0
 }
3b9fe0
@@ -646,6 +655,10 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
3b9fe0
 		*(char **)arg = lo->ldo_tls_dhfile ?
3b9fe0
 			LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
3b9fe0
 		break;
3b9fe0
+	case LDAP_OPT_X_TLS_ECNAME:
3b9fe0
+		*(char **)arg = lo->ldo_tls_ecname ?
3b9fe0
+			LDAP_STRDUP( lo->ldo_tls_ecname ) : NULL;
3b9fe0
+		break;
3b9fe0
 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
3b9fe0
 		*(char **)arg = lo->ldo_tls_crlfile ?
3b9fe0
 			LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
3b9fe0
@@ -765,6 +778,10 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
3b9fe0
 		if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
3b9fe0
 		lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
3b9fe0
 		return 0;
3b9fe0
+	case LDAP_OPT_X_TLS_ECNAME:
3b9fe0
+		if ( lo->ldo_tls_ecname ) LDAP_FREE( lo->ldo_tls_ecname );
3b9fe0
+		lo->ldo_tls_ecname = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
3b9fe0
+		return 0;
3b9fe0
 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
3b9fe0
 		if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
3b9fe0
 		lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
3b9fe0
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
3b9fe0
index f24060b7e..1370923af 100644
3b9fe0
--- a/libraries/libldap/tls_o.c
3b9fe0
+++ b/libraries/libldap/tls_o.c
3b9fe0
@@ -373,10 +373,9 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
3b9fe0
 		return -1;
3b9fe0
 	}
3b9fe0
 
3b9fe0
-	if ( lo->ldo_tls_dhfile ) {
3b9fe0
-		DH *dh = NULL;
3b9fe0
+	if ( is_server && lo->ldo_tls_dhfile ) {
3b9fe0
+		DH *dh;
3b9fe0
 		BIO *bio;
3b9fe0
-		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
3b9fe0
 
3b9fe0
 		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
3b9fe0
 			Debug( LDAP_DEBUG_ANY,
3b9fe0
@@ -395,7 +394,35 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
3b9fe0
 		}
3b9fe0
 		BIO_free( bio );
3b9fe0
 		SSL_CTX_set_tmp_dh( ctx, dh );
3b9fe0
+		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
3b9fe0
+		DH_free( dh );
3b9fe0
+	}
3b9fe0
+
3b9fe0
+#ifdef SSL_OP_SINGLE_ECDH_USE
3b9fe0
+	if ( is_server && lo->ldo_tls_ecname ) {
3b9fe0
+		EC_KEY *ecdh;
3b9fe0
+
3b9fe0
+		int nid = OBJ_sn2nid( lt->lt_ecname );
3b9fe0
+		if ( nid == NID_undef ) {
3b9fe0
+			Debug( LDAP_DEBUG_ANY,
3b9fe0
+				"TLS: could not use EC name `%s'.\n",
3b9fe0
+				lo->ldo_tls_ecname,0,0);
3b9fe0
+			tlso_report_error();
3b9fe0
+			return -1;
3b9fe0
+		}
3b9fe0
+		ecdh = EC_KEY_new_by_curve_name( nid );
3b9fe0
+		if ( ecdh == NULL ) {
3b9fe0
+			Debug( LDAP_DEBUG_ANY,
3b9fe0
+				"TLS: could not generate key for EC name `%s'.\n",
3b9fe0
+				lo->ldo_tls_ecname,0,0);
3b9fe0
+			tlso_report_error();
3b9fe0
+			return -1;
3b9fe0
+		}
3b9fe0
+		SSL_CTX_set_tmp_ecdh( ctx, ecdh );
3b9fe0
+		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE );
3b9fe0
+		EC_KEY_free( ecdh );
3b9fe0
 	}
3b9fe0
+#endif
3b9fe0
 
3b9fe0
 	if ( tlso_opt_trace ) {
3b9fe0
 		SSL_CTX_set_info_callback( ctx, tlso_info_cb );
3b9fe0
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
3b9fe0
index 250f14100..8b1e4e582 100644
3b9fe0
--- a/servers/slapd/bconfig.c
3b9fe0
+++ b/servers/slapd/bconfig.c
3b9fe0
@@ -194,6 +194,7 @@ enum {
3b9fe0
 	CFG_ACL_ADD,
3b9fe0
 	CFG_SYNC_SUBENTRY,
3b9fe0
 	CFG_LTHREADS,
3b9fe0
+	CFG_TLS_ECNAME,
3b9fe0
 
3b9fe0
 	CFG_LAST
3b9fe0
 };
3b9fe0
@@ -738,6 +739,14 @@ static ConfigTable config_back_cf_table[] = {
3b9fe0
 #endif
3b9fe0
 		"( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' "
3b9fe0
 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
3b9fe0
+	{ "TLSECName", NULL, 2, 2, 0,
3b9fe0
+#ifdef HAVE_TLS
3b9fe0
+		CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, &config_tls_option,
3b9fe0
+#else
3b9fe0
+		ARG_IGNORED, NULL,
3b9fe0
+#endif
3b9fe0
+		"( OLcfgGlAt:96 NAME 'olcTLSECName' "
3b9fe0
+			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
3b9fe0
 	{ "TLSProtocolMin",	NULL, 2, 2, 0,
3b9fe0
 #ifdef HAVE_TLS
3b9fe0
 		CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config,
3b9fe0
@@ -819,7 +828,7 @@ static ConfigOCs cf_ocs[] = {
3b9fe0
 		 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
3b9fe0
 		 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
3b9fe0
 		 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
3b9fe0
-		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
3b9fe0
+		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ olcTLSECName $ "
3b9fe0
 		 "olcTLSCRLFile $ olcTLSProtocolMin $ olcToolThreads $ olcWriteTimeout $ "
3b9fe0
 		 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
3b9fe0
 		 "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
3b9fe0
@@ -3824,6 +3833,7 @@ config_tls_option(ConfigArgs *c) {
3b9fe0
 	case CFG_TLS_CA_PATH:	flag = LDAP_OPT_X_TLS_CACERTDIR;	break;
3b9fe0
 	case CFG_TLS_CA_FILE:	flag = LDAP_OPT_X_TLS_CACERTFILE;	break;
3b9fe0
 	case CFG_TLS_DH_FILE:	flag = LDAP_OPT_X_TLS_DHFILE;	break;
3b9fe0
+	case CFG_TLS_ECNAME:	flag = LDAP_OPT_X_TLS_ECNAME;	break;
3b9fe0
 #ifdef HAVE_GNUTLS
3b9fe0
 	case CFG_TLS_CRL_FILE:	flag = LDAP_OPT_X_TLS_CRLFILE;	break;
3b9fe0
 #endif