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