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

02ade0
ITS#7595 Add Elliptic Curve support for OpenSSL
02ade0
02ade0
Cherry-picked upstream e631ce808ed56119e61321463d06db7999ba5a08
02ade0
Author:    Howard Chu <hyc@openldap.org>
02ade0
Date:      Sat Sep 7 09:47:19 2013 -0700
02ade0
02ade0
diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
02ade0
index 49a3959ae..9cd0a4dd1 100644
02ade0
--- a/doc/man/man5/slapd-config.5
02ade0
+++ b/doc/man/man5/slapd-config.5
02ade0
@@ -918,6 +918,13 @@ from the default, otherwise no certificate exchanges or verification will
02ade0
 be done. When using GnuTLS or Mozilla NSS these parameters are always generated randomly
02ade0
 so this directive is ignored.
02ade0
 .TP
02ade0
+.B olcTLSECName: <name>
02ade0
+Specify the name of a curve to use for Elliptic curve Diffie-Hellman
02ade0
+ephemeral key exchange.  This is required to enable ECDHE algorithms in
02ade0
+OpenSSL.  This option is not used with GnuTLS; the curves may be
02ade0
+chosen in the GnuTLS ciphersuite specification. This option is also
02ade0
+ignored for Mozilla NSS.
02ade0
+.TP
02ade0
 .B olcTLSProtocolMin: <major>[.<minor>]
02ade0
 Specifies minimum SSL/TLS protocol version that will be negotiated.
02ade0
 If the server doesn't support at least that version,
02ade0
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
02ade0
index e2344547e..4eb238162 100644
02ade0
--- a/doc/man/man5/slapd.conf.5
02ade0
+++ b/doc/man/man5/slapd.conf.5
02ade0
@@ -1149,6 +1149,13 @@ from the default, otherwise no certificate exchanges or verification will
02ade0
 be done. When using GnuTLS these parameters are always generated randomly so
02ade0
 this directive is ignored.  This directive is ignored when using Mozilla NSS.
02ade0
 .TP
02ade0
+.B TLSECName <name>
02ade0
+Specify the name of a curve to use for Elliptic curve Diffie-Hellman
02ade0
+ephemeral key exchange.  This is required to enable ECDHE algorithms in
02ade0
+OpenSSL.  This option is not used with GnuTLS; the curves may be
02ade0
+chosen in the GnuTLS ciphersuite specification. This option is also
02ade0
+ignored for Mozilla NSS.
02ade0
+.TP
02ade0
 .B TLSProtocolMin <major>[.<minor>]
02ade0
 Specifies minimum SSL/TLS protocol version that will be negotiated.
02ade0
 If the server doesn't support at least that version,
02ade0
diff --git a/include/ldap.h b/include/ldap.h
02ade0
index d4d10fa79..9922c9fa8 100644
02ade0
--- a/include/ldap.h
02ade0
+++ b/include/ldap.h
02ade0
@@ -158,6 +158,7 @@ LDAP_BEGIN_DECL
02ade0
 #define LDAP_OPT_X_TLS_NEWCTX		0x600f
02ade0
 #define LDAP_OPT_X_TLS_CRLFILE		0x6010	/* GNUtls only */
02ade0
 #define LDAP_OPT_X_TLS_PACKAGE		0x6011
02ade0
+#define LDAP_OPT_X_TLS_ECNAME		0x6012
02ade0
 #define LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY  0x6050
02ade0
 
02ade0
 #define LDAP_OPT_X_TLS_MOZNSS_COMPATIBILITY_DISABLED	0
02ade0
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
02ade0
index 1a26b3cb0..5fff785d8 100644
02ade0
--- a/libraries/libldap/ldap-int.h
02ade0
+++ b/libraries/libldap/ldap-int.h
02ade0
@@ -165,6 +165,7 @@ struct ldaptls {
02ade0
 	char		*lt_ciphersuite;
02ade0
 	char		*lt_crlfile;
02ade0
 	char		*lt_randfile;	/* OpenSSL only */
02ade0
+	char		*lt_ecname;		/* OpenSSL only */
02ade0
 	int		lt_protocol_min;
02ade0
 };
02ade0
 #endif
02ade0
@@ -250,6 +251,7 @@ struct ldapoptions {
02ade0
 #define ldo_tls_certfile	ldo_tls_info.lt_certfile
02ade0
 #define ldo_tls_keyfile	ldo_tls_info.lt_keyfile
02ade0
 #define ldo_tls_dhfile	ldo_tls_info.lt_dhfile
02ade0
+#define ldo_tls_ecname	ldo_tls_info.lt_ecname
02ade0
 #define ldo_tls_cacertfile	ldo_tls_info.lt_cacertfile
02ade0
 #define ldo_tls_cacertdir	ldo_tls_info.lt_cacertdir
02ade0
 #define ldo_tls_ciphersuite	ldo_tls_info.lt_ciphersuite
02ade0
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
02ade0
index a616133da..f39546450 100644
02ade0
--- a/libraries/libldap/tls2.c
02ade0
+++ b/libraries/libldap/tls2.c
02ade0
@@ -121,6 +121,10 @@ ldap_int_tls_destroy( struct ldapoptions *lo )
02ade0
 		LDAP_FREE( lo->ldo_tls_dhfile );
02ade0
 		lo->ldo_tls_dhfile = NULL;
02ade0
 	}
02ade0
+	if ( lo->ldo_tls_ecname ) {
02ade0
+		LDAP_FREE( lo->ldo_tls_ecname );
02ade0
+		lo->ldo_tls_ecname = NULL;
02ade0
+	}
02ade0
 	if ( lo->ldo_tls_cacertfile ) {
02ade0
 		LDAP_FREE( lo->ldo_tls_cacertfile );
02ade0
 		lo->ldo_tls_cacertfile = NULL;
02ade0
@@ -257,6 +261,10 @@ ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server )
02ade0
 		lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile );
02ade0
 		__atoe( lts.lt_dhfile );
02ade0
 	}
02ade0
+	if ( lts.lt_ecname ) {
02ade0
+		lts.lt_ecname = LDAP_STRDUP( lts.lt_ecname );
02ade0
+		__atoe( lts.lt_ecname );
02ade0
+	}
02ade0
 #endif
02ade0
 	lo->ldo_tls_ctx = ti->ti_ctx_new( lo );
02ade0
 	if ( lo->ldo_tls_ctx == NULL ) {
02ade0
@@ -282,6 +290,7 @@ error_exit:
02ade0
 	LDAP_FREE( lts.lt_crlfile );
02ade0
 	LDAP_FREE( lts.lt_cacertdir );
02ade0
 	LDAP_FREE( lts.lt_dhfile );
02ade0
+	LDAP_FREE( lts.lt_ecname );
02ade0
 #endif
02ade0
 	return rc;
02ade0
 }
02ade0
@@ -674,6 +683,10 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
02ade0
 		*(char **)arg = lo->ldo_tls_dhfile ?
02ade0
 			LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL;
02ade0
 		break;
02ade0
+	case LDAP_OPT_X_TLS_ECNAME:
02ade0
+		*(char **)arg = lo->ldo_tls_ecname ?
02ade0
+			LDAP_STRDUP( lo->ldo_tls_ecname ) : NULL;
02ade0
+		break;
02ade0
 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
02ade0
 		*(char **)arg = lo->ldo_tls_crlfile ?
02ade0
 			LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL;
02ade0
@@ -796,6 +809,10 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
02ade0
 		if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile );
02ade0
 		lo->ldo_tls_dhfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL;
02ade0
 		return 0;
02ade0
+	case LDAP_OPT_X_TLS_ECNAME:
02ade0
+		if ( lo->ldo_tls_ecname ) LDAP_FREE( lo->ldo_tls_ecname );
02ade0
+		lo->ldo_tls_ecname = arg ? LDAP_STRDUP( (char *) arg ) : NULL;
02ade0
+		return 0;
02ade0
 	case LDAP_OPT_X_TLS_CRLFILE:	/* GnuTLS only */
02ade0
 		if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile );
02ade0
 		lo->ldo_tls_crlfile = (arg && *(char *)arg) ? LDAP_STRDUP( (char *) arg ) : NULL;
02ade0
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
02ade0
index a2d9cd31f..1a81bc625 100644
02ade0
--- a/libraries/libldap/tls_o.c
02ade0
+++ b/libraries/libldap/tls_o.c
02ade0
@@ -296,10 +296,9 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
02ade0
 		return -1;
02ade0
 	}
02ade0
 
02ade0
-	if ( lo->ldo_tls_dhfile ) {
02ade0
-		DH *dh = NULL;
02ade0
+	if ( is_server && lo->ldo_tls_dhfile ) {
02ade0
+		DH *dh;
02ade0
 		BIO *bio;
02ade0
-		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
02ade0
 
02ade0
 		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
02ade0
 			Debug( LDAP_DEBUG_ANY,
02ade0
@@ -318,7 +317,35 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
02ade0
 		}
02ade0
 		BIO_free( bio );
02ade0
 		SSL_CTX_set_tmp_dh( ctx, dh );
02ade0
+		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
02ade0
+		DH_free( dh );
02ade0
+	}
02ade0
+
02ade0
+#ifdef SSL_OP_SINGLE_ECDH_USE
02ade0
+	if ( is_server && lo->ldo_tls_ecname ) {
02ade0
+		EC_KEY *ecdh;
02ade0
+
02ade0
+		int nid = OBJ_sn2nid( lt->lt_ecname );
02ade0
+		if ( nid == NID_undef ) {
02ade0
+			Debug( LDAP_DEBUG_ANY,
02ade0
+				"TLS: could not use EC name `%s'.\n",
02ade0
+				lo->ldo_tls_ecname,0,0);
02ade0
+			tlso_report_error();
02ade0
+			return -1;
02ade0
+		}
02ade0
+		ecdh = EC_KEY_new_by_curve_name( nid );
02ade0
+		if ( ecdh == NULL ) {
02ade0
+			Debug( LDAP_DEBUG_ANY,
02ade0
+				"TLS: could not generate key for EC name `%s'.\n",
02ade0
+				lo->ldo_tls_ecname,0,0);
02ade0
+			tlso_report_error();
02ade0
+			return -1;
02ade0
+		}
02ade0
+		SSL_CTX_set_tmp_ecdh( ctx, ecdh );
02ade0
+		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE );
02ade0
+		EC_KEY_free( ecdh );
02ade0
 	}
02ade0
+#endif
02ade0
 
02ade0
 	if ( tlso_opt_trace ) {
02ade0
 		SSL_CTX_set_info_callback( ctx, tlso_info_cb );
02ade0
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
02ade0
index 8ade0c3f2..5a3c67a72 100644
02ade0
--- a/servers/slapd/bconfig.c
02ade0
+++ b/servers/slapd/bconfig.c
02ade0
@@ -194,6 +194,7 @@ enum {
02ade0
 	CFG_ACL_ADD,
02ade0
 	CFG_SYNC_SUBENTRY,
02ade0
 	CFG_LTHREADS,
02ade0
+	CFG_TLS_ECNAME,
02ade0
 
02ade0
 	CFG_LAST
02ade0
 };
02ade0
@@ -738,6 +739,14 @@ static ConfigTable config_back_cf_table[] = {
02ade0
 #endif
02ade0
 		"( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' "
02ade0
 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
02ade0
+	{ "TLSECName", NULL, 2, 2, 0,
02ade0
+#ifdef HAVE_TLS
02ade0
+		CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, &config_tls_option,
02ade0
+#else
02ade0
+		ARG_IGNORED, NULL,
02ade0
+#endif
02ade0
+		"( OLcfgGlAt:96 NAME 'olcTLSECName' "
02ade0
+			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
02ade0
 	{ "TLSProtocolMin",	NULL, 2, 2, 0,
02ade0
 #ifdef HAVE_TLS
02ade0
 		CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config,
02ade0
@@ -819,7 +828,7 @@ static ConfigOCs cf_ocs[] = {
02ade0
 		 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
02ade0
 		 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
02ade0
 		 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
02ade0
-		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
02ade0
+		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ olcTLSECName $ "
02ade0
 		 "olcTLSCRLFile $ olcTLSProtocolMin $ olcToolThreads $ olcWriteTimeout $ "
02ade0
 		 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
02ade0
 		 "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
02ade0
@@ -3824,6 +3833,7 @@ config_tls_option(ConfigArgs *c) {
02ade0
 	case CFG_TLS_CA_PATH:	flag = LDAP_OPT_X_TLS_CACERTDIR;	break;
02ade0
 	case CFG_TLS_CA_FILE:	flag = LDAP_OPT_X_TLS_CACERTFILE;	break;
02ade0
 	case CFG_TLS_DH_FILE:	flag = LDAP_OPT_X_TLS_DHFILE;	break;
02ade0
+	case CFG_TLS_ECNAME:	flag = LDAP_OPT_X_TLS_ECNAME;	break;
02ade0
 #ifdef HAVE_GNUTLS
02ade0
 	case CFG_TLS_CRL_FILE:	flag = LDAP_OPT_X_TLS_CRLFILE;	break;
02ade0
 #endif