[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#780398: Custom (EC)DHE parameters and Apache 2.2

I'd also like to see this issue fixed.  The relevant upstream changes
can be found at <https://svn.apache.org/r1527295>.

Changing the defaults has the potential to break old buggy clients,
such as those using Java 6.  So I would suggest that the Debian
package continue to use the old default behavior (with a maximum of
1024 bits for DH), but backport the option to override this by
specifying the parameters in the certificate file.

(Which, to be honest, seems more than a little bit kludgy to me, but
that is the approach upstream Apache is taking.)

I don't know much of anything about Apache internals (or about
OpenSSL, for that matter), but these changes look straightforward
enough, so here is a patch that ought to do the job.

I'm not sure how to check whether this patch is really working.
'openssl s_client' is my usual tool for testing such things, and it
doesn't seem to have the option of displaying the parameters used for
key exchange.  However, I can see that if I specify a 2048-bit DH
modulus in the certificate file, and use a DHE ciphersuite, the
ServerKeyExchange and ClientKeyExchange packets are correspondingly
larger.  Likewise if I specify a larger curve and an ECDHE suite.

Description: Allow custom DH and ECDH parameters.
 The parameters used for DH and ECDH are hard-coded by default, and
 the 1024-bit modulus used by default for DH may be too weak to
 provide effective forward secrecy for years to come.  Following the
 behavior of Apache 2.4.7, allow the administrator to specify custom
 parameters by including them in the SSLCertificateFile.
Origin: backport, subset of https://svn.apache.org/r1527295
Bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=49559
Bug-Debian: http://bugs.debian.org/780398

--- apache2-2.2.22.orig/modules/ssl/ssl_engine_init.c
+++ apache2-2.2.22/modules/ssl/ssl_engine_init.c
@@ -1040,10 +1040,14 @@ static void ssl_init_server_certs(server
     const char *rsa_id, *dsa_id;
 #ifndef OPENSSL_NO_EC
     const char *ecc_id;
+    EC_GROUP *ecparams;
+    int nid;
+    EC_KEY *eckey;
     const char *vhost_id = mctx->sc->vhost_id;
     int i;
     int have_rsa, have_dsa;
+    DH *dhparams;
 #ifndef OPENSSL_NO_EC
     int have_ecc;
@@ -1098,6 +1102,33 @@ static void ssl_init_server_certs(server
+    /*
+     * Try to read DH parameters from the (first) SSLCertificateFile
+     */
+    if ((mctx->pks->cert_files[0] != NULL) &&
+        (dhparams = ssl_dh_GetParamFromFile(mctx->pks->cert_files[0]))) {
+        SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                     "Custom DH parameters (%d bits) for %s loaded from %s",
+                     BN_num_bits(dhparams->p), vhost_id,
+                     mctx->pks->cert_files[0]);
+    }
+#ifndef OPENSSL_NO_EC
+    /*
+     * Similarly, try to read the ECDH curve name from SSLCertificateFile...
+     */
+    if ((mctx->pks->cert_files[0] != NULL) &&
+        (ecparams = ssl_ec_GetParamFromFile(mctx->pks->cert_files[0])) &&
+        (nid = EC_GROUP_get_curve_name(ecparams)) &&
+        (eckey = EC_KEY_new_by_curve_name(nid))) {
+        SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                     "ECDH curve %s for %s specified in %s",
+                     OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]);
+    }
 static void ssl_init_proxy_certs(server_rec *s,
--- apache2-2.2.22.orig/modules/ssl/ssl_private.h
+++ apache2-2.2.22/modules/ssl/ssl_private.h
@@ -705,6 +705,9 @@ void         ssl_pphrase_Handle(server_r
 /**  Diffie-Hellman Parameter Support  */
 DH           *ssl_dh_GetTmpParam(int);
 DH           *ssl_dh_GetParamFromFile(char *);
+#ifndef OPENSSL_NO_EC
+EC_GROUP     *ssl_ec_GetParamFromFile(const char *);
 unsigned char *ssl_asn1_table_set(apr_hash_t *table,
                                   const char *key,
--- apache2-2.2.22.orig/modules/ssl/ssl_util_ssl.c
+++ apache2-2.2.22/modules/ssl/ssl_util_ssl.c
@@ -451,6 +451,26 @@ BOOL SSL_X509_INFO_load_path(apr_pool_t
 /*  _________________________________________________________________
+**  Custom (EC)DH parameter support
+**  _________________________________________________________________
+#ifndef OPENSSL_NO_EC
+EC_GROUP *ssl_ec_GetParamFromFile(const char *file)
+    EC_GROUP *group = NULL;
+    BIO *bio;
+    if ((bio = BIO_new_file(file, "r")) == NULL)
+        return NULL;
+    group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL);
+    BIO_free(bio);
+    return (group);
+/*  _________________________________________________________________
 **  Extra Server Certificate Chain Support
 **  _________________________________________________________________
--- apache2-2.2.22.orig/docs/manual/mod/mod_ssl.html.en
+++ apache2-2.2.22/docs/manual/mod/mod_ssl.html.en
@@ -388,12 +388,19 @@ SSLCertificateChainFile /usr/local/apach
 <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_ssl</td></tr>
-This directive points to the PEM-encoded Certificate file for the server and
-optionally also to the corresponding RSA or DSA Private Key file for it
-(contained in the same file). If the contained Private Key is encrypted the
-Pass Phrase dialog is forced at startup time. This directive can be used up to
-two times (referencing different filenames) when both a RSA and a DSA based
-server certificate is used in parallel.</p>
+This directive points to the file with the PEM-encoded certificate,
+optionally also the corresponding private key, and - beginning with
+version 2.5.0-dev as of 2013-09-29 - DH parameters and/or an EC curve name
+for ephemeral keys (as generated by <code>openssl dhparam</code>
+and <code>openssl ecparam</code>, respectively). If the private key
+is encrypted, the pass phrase dialog is forced at startup time.
+This directive can be used up to three times (referencing different filenames)
+when both an RSA, a DSA, and an ECC based server certificate is used in
+parallel. Note that DH and ECDH parameters are only read from the first
+<directive>SSLCertificateFile</directive> directive.</p>
 <div class="example"><h3>Example</h3><p><code>
 SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server.crt

Reply to: