From 2386a11649132751fd972643789766b3906e11f6 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 20 Aug 2020 15:07:55 +0100 Subject: [PATCH] ITS#9054 Add support for multiple EECDH curves Requires OpenSSL 1.0.2 or newer --- doc/man/man3/ldap_get_option.3 | 2 +- doc/man/man5/ldap.conf.5 | 6 ++++++ doc/man/man5/slapd-config.5 | 6 +++--- doc/man/man5/slapd.conf.5 | 6 +++--- libraries/libldap/init.c | 1 + libraries/libldap/tls2.c | 3 ++- libraries/libldap/tls_o.c | 28 ++++++++++++---------------- 7 files changed, 28 insertions(+), 24 deletions(-) diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3 index 71bffd9cac..b10a5480f8 100644 --- a/doc/man/man3/ldap_get_option.3 +++ b/doc/man/man3/ldap_get_option.3 @@ -740,7 +740,7 @@ and its contents need to be freed by the caller using .BR ldap_memfree (3). .TP .B LDAP_OPT_X_TLS_ECNAME -Gets/sets the name of the curve used for +Gets/sets the name of the curve(s) used for elliptic curve key exchanges. .BR invalue must be diff --git a/doc/man/man5/ldap.conf.5 b/doc/man/man5/ldap.conf.5 index 1b8649496b..c0aee8f893 100644 --- a/doc/man/man5/ldap.conf.5 +++ b/doc/man/man5/ldap.conf.5 @@ -327,6 +327,12 @@ is always used before Specifies the file that contains the client certificate. .B This is a user-only option. .TP +.B TLS_ECNAME +Specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman +ephemeral key exchange. This option is only used for OpenSSL. +This option is not used with GnuTLS; the curves may be +chosen in the GnuTLS ciphersuite specification. +.TP .B TLS_KEY Specifies the file that contains the private key that matches the certificate stored in the diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5 index 1cb77421fd..6eca909ebb 100644 --- a/doc/man/man5/slapd-config.5 +++ b/doc/man/man5/slapd-config.5 @@ -908,9 +908,9 @@ You should append "!ADH" to your cipher suites to ensure that these suites are not used. .TP .B olcTLSECName: -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 +Specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman +ephemeral key exchange. This option is only used for OpenSSL. +This option is not used with GnuTLS; the curves may be chosen in the GnuTLS ciphersuite specification. .TP .B olcTLSProtocolMin: [.] diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 04b2fdd87b..c0957dd454 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -1139,9 +1139,9 @@ You should append "!ADH" to your cipher suites to ensure that these suites are not used. .TP .B TLSECName -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 +Specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman +ephemeral key exchange. This option is only used for OpenSSL. +This option is not used with GnuTLS; the curves may be chosen in the GnuTLS ciphersuite specification. .TP .B TLSProtocolMin [.] diff --git a/libraries/libldap/init.c b/libraries/libldap/init.c index dfe1ea9da4..52b44d16e0 100644 --- a/libraries/libldap/init.c +++ b/libraries/libldap/init.c @@ -123,6 +123,7 @@ static const struct ol_attribute { {0, ATTR_TLS, "TLS_CIPHER_SUITE", NULL, LDAP_OPT_X_TLS_CIPHER_SUITE}, {0, ATTR_TLS, "TLS_PROTOCOL_MIN", NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN}, {0, ATTR_TLS, "TLS_PEERKEY_HASH", NULL, LDAP_OPT_X_TLS_PEERKEY_HASH}, + {0, ATTR_TLS, "TLS_ECNAME", NULL, LDAP_OPT_X_TLS_ECNAME}, #ifdef HAVE_OPENSSL_CRL {0, ATTR_TLS, "TLS_CRLCHECK", NULL, LDAP_OPT_X_TLS_CRLCHECK}, diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c index 99f215ec1d..ecb292514f 100644 --- a/libraries/libldap/tls2.c +++ b/libraries/libldap/tls2.c @@ -342,7 +342,7 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn, const char *host ) Sockbuf *sb = conn->lconn_sb; int err; tls_session *ssl = NULL; - char *sni = host; + char *sni = (char *)host; if ( HAS_TLS( sb )) { ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); @@ -580,6 +580,7 @@ ldap_pvt_tls_config( LDAP *ld, int option, const char *arg ) case LDAP_OPT_X_TLS_CIPHER_SUITE: case LDAP_OPT_X_TLS_DHFILE: case LDAP_OPT_X_TLS_PEERKEY_HASH: + case LDAP_OPT_X_TLS_ECNAME: case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ return ldap_pvt_tls_set_option( ld, option, (void *) arg ); diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c index e6f83c795d..2c8c7e3fb2 100644 --- a/libraries/libldap/tls_o.c +++ b/libraries/libldap/tls_o.c @@ -453,34 +453,30 @@ tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) DH_free( dh ); } - if ( is_server && lo->ldo_tls_ecname ) { + if ( lo->ldo_tls_ecname ) { #ifdef OPENSSL_NO_EC Debug0( LDAP_DEBUG_ANY, "TLS: Elliptic Curves not supported.\n" ); return -1; #else - EC_KEY *ecdh; - - int nid = OBJ_sn2nid( lt->lt_ecname ); - if ( nid == NID_undef ) { + if ( SSL_CTX_set1_curves_list( ctx, lt->lt_ecname )) { Debug1( LDAP_DEBUG_ANY, - "TLS: could not use EC name `%s'.\n", + "TLS: could not set EC name `%s'.\n", lo->ldo_tls_ecname ); tlso_report_error(); return -1; } - ecdh = EC_KEY_new_by_curve_name( nid ); - if ( ecdh == NULL ) { - Debug1( LDAP_DEBUG_ANY, - "TLS: could not generate key for EC name `%s'.\n", - lo->ldo_tls_ecname ); - tlso_report_error(); - return -1; + /* + * This is a NOP in OpenSSL 1.1.0 and later, where curves are always + * auto-negotiated. + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000UL + if ( SSL_CTX_set_ecdh_auto( ctx, 1 ) <= 0 ) { + Debug0( LDAP_DEBUG_ANY, + "TLS: could not enable automatic EC negotiation.\n" ); } - SSL_CTX_set_tmp_ecdh( ctx, ecdh ); - SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE ); - EC_KEY_free( ecdh ); #endif +#endif /* OPENSSL_NO_EC */ } if ( tlso_opt_trace ) {