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

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