]> granicus.if.org Git - apache/commitdiff
Improve ephemeral key handling (companion to r1526168):
authorKaspar Brand <kbrand@apache.org>
Sun, 29 Sep 2013 10:35:46 +0000 (10:35 +0000)
committerKaspar Brand <kbrand@apache.org>
Sun, 29 Sep 2013 10:35:46 +0000 (10:35 +0000)
- allow to configure custom DHE or ECDHE parameters via the
  SSLCertificateFile directive, and adapt its documentation
  accordingly (addresses PR 49559)

- add standardized DH parameters from RFCs 2409 and 3526,
  use them based on the length of the certificate's RSA/DSA key,
  and add a FAQ entry for clients which limit DH support
  to 1024 bits (such as Java 7 and earlier)

- move ssl_dh_GetParamFromFile() from ssl_engine_dh.c to
  ssl_util_ssl.c, and add ssl_ec_GetParamFromFile()

- drop ssl_engine_dh.c from mod_ssl

For the standardized DH parameters, OpenSSL version 0.9.8a
or later is required, which was therefore made a new minimum
requirement in r1527294.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1527295 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
CHANGES
CMakeLists.txt
LAYOUT
docs/manual/mod/mod_ssl.xml
docs/manual/ssl/ssl_faq.xml
modules/ssl/config.m4
modules/ssl/mod_ssl.dsp
modules/ssl/ssl_engine_dh.c [deleted file]
modules/ssl/ssl_engine_init.c
modules/ssl/ssl_engine_kernel.c
modules/ssl/ssl_private.h
modules/ssl/ssl_util_ssl.c

diff --git a/CHANGES b/CHANGES
index 357ccb322ac772de893228b31d1943c2a04c0e5e..93bfe4bed6cf4d446c94970dee53b47eec5f84ae 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,12 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) mod_ssl: Improve handling of ephemeral DH and ECDH keys by
+     allowing custom parameters to be configured via SSLCertificateFile,
+     and by adding standardized DH parameters for 1024/2048/3072/4096 bits.
+     Unless custom parameters are configured, the standardized parameters
+     are applied based on the certificate's RSA/DSA key size.
+
   *) mod_ssl, configure: Require OpenSSL 0.9.8a or later. [Kaspar Brand]
 
   *) mod_lua: Let the Inter-VM get/set functions work with a global 
index d8c1cf0be51962ccbfc2f76f7124292c9b68b579..3965939785b4012234d10eb010242b72c6259a77 100644 (file)
@@ -417,7 +417,7 @@ IF(OPENSSL_FOUND)
   SET(mod_ssl_extra_libs               ${OPENSSL_LIBRARIES})
 ENDIF()
 SET(mod_ssl_extra_sources
-  modules/ssl/ssl_engine_config.c    modules/ssl/ssl_engine_dh.c
+  modules/ssl/ssl_engine_config.c
   modules/ssl/ssl_engine_init.c      modules/ssl/ssl_engine_io.c
   modules/ssl/ssl_engine_kernel.c    modules/ssl/ssl_engine_log.c
   modules/ssl/ssl_engine_mutex.c     modules/ssl/ssl_engine_ocsp.c
diff --git a/LAYOUT b/LAYOUT
index 9a630689c99de8d046a626d2bc6de898eaadb95e..b5faadb1320a9c4d7acd35c9402fd428d42c6259 100644 (file)
--- a/LAYOUT
+++ b/LAYOUT
@@ -108,7 +108,6 @@ modules/ ................ Manditory and Add-In Apache stock modules
     mod_ssl.c ............... main source file containing API structures
     mod_ssl.h ............... common header file of mod_ssl
     ssl_engine_config.c ..... module configuration handling
-    ssl_engine_dh.c ......... DSA/DH support
     ssl_engine_init.c ....... module initialization
     ssl_engine_io.c ......... I/O support
     ssl_engine_kernel.c ..... SSL engine kernel
index 62d1c3d64490dd3c98f6228590740939074692ca..6be654289bfc868604abd32f1f5a9fb52c82c5af 100644 (file)
@@ -808,12 +808,33 @@ SSLCipherSuite RSA:!EXP:!NULL:+HIGH:+MEDIUM:-LOW
 
 <usage>
 <p>
-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
-three times (referencing different filenames) when both a RSA, a DSA, and an
-ECC 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.
+</p>
+<p>
+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>
+
+<note>
+<title>DH parameter interoperability with primes > 1024 bit</title>
+<p>
+Beginning with version 2.5.0-dev as of 2013-09-29, mod_ssl makes use of
+standardized DH parameters with prime lengths of 2048, 3072 and 4096 bits
+(from <a href="http://www.ietf.org/rfc/rfc3526.txt">RFC 3526</a>), and hands
+them out to clients based on the length of the certificate's RSA/DSA key.
+With Java-based clients in particular (Java 7 or earlier), this may lead
+to handshake failures - see this
+<a href="../ssl/ssl_faq.html#javadh">FAQ answer</a> for working around
+such issues.
+</p>
+</note>
+
 <example><title>Example</title>
 <highlight language="config">
 SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server.crt
index 22aa7b32f063f8ea57d195726a862775d0e5792d..0e340a2f6ac05afa5dfc3a008046caf4539e9011 100644 (file)
@@ -519,6 +519,8 @@ Does this mean the username/password is being sent unencrypted?</a></li>
 <li><a href="#msie">Why do I get I/O errors when connecting via
 HTTPS to an Apache+mod_ssl server with Microsoft Internet Explorer
 (MSIE)?</a></li>
+<li><a href="#srp">How do I enable TLS-SRP?</a></li>
+<li><a href="#javadh">Why do I get handshake failures with Java-based clients when using a certificate with more than 1024 bits?</a></li>
 </ul>
 
 <section id="random"><title>Why do I get lots of random SSL protocol
@@ -740,6 +742,37 @@ SetEnvIf User-Agent "MSIE [2-5]" \
     </example>
 </section>
 
+<section id="javadh"><title>Why do I get handshake failures with Java-based clients when using a certificate with more than 1024 bits?</title>
+    <p>Beginning with version 2.5.0-dev as of 2013-09-29,
+    <module>mod_ssl</module> will use DH parameters which include primes
+    with lengths of more than 1024 bits. Java 7 and earlier limit their
+    support for DH prime sizes to a maximum of 1024 bits, however.</p>
+
+    <p>If your Java-based client aborts with exceptions such as
+    <code>java.lang.RuntimeException: Could not generate DH keypair</code> and
+    <code>java.security.InvalidAlgorithmParameterException: Prime size must be
+    multiple of 64, and can only range from 512 to 1024 (inclusive)</code>,
+    and httpd logs <code>tlsv1 alert internal error (SSL alert number 80)</code>
+    (at <directive module="core">LogLevel</directive> <code>info</code>
+    or higher), you can either rearrange mod_ssl's cipher list with
+    <directive module="mod_ssl">SSLCipherSuite</directive>
+    (possibly in conjunction with <directive module="mod_ssl">SSLHonorCipherOrder</directive>),
+    or you can use the <directive module="mod_ssl">SSLCertificateFile</directive>
+    directive to configure custom DH parameters with a 1024-bit prime, which
+    will always have precedence over any of the built-in DH parameters.</p>
+
+    <p>To generate custom DH parameters, use the <code>openssl dhparam</code>
+    command. Alternatively, you can append the following standard 1024-bit DH
+    parameters from <a href="http://www.ietf.org/rfc/rfc2409.txt">RFC 2409</a>,
+    section 6.2 to the respective
+    <directive module="ssl">SSLCertificateFile</directive> file:</p>
+    <example><pre>-----BEGIN DH PARAMETERS-----
+MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
+Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
+/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
+-----END DH PARAMETERS-----</pre></example>
+</section>
+
 </section>
 <!-- /aboutssl -->
 
index 1b589d8150d307569f8806b34008709144661bd5..45eeb43d9dc9e100b0af3803e286d3f3628b45f3 100644 (file)
@@ -20,7 +20,6 @@ dnl #  list of module object files
 ssl_objs="dnl
 mod_ssl.lo dnl
 ssl_engine_config.lo dnl
-ssl_engine_dh.lo dnl
 ssl_engine_init.lo dnl
 ssl_engine_io.lo dnl
 ssl_engine_kernel.lo dnl
index fc86a7b6e88e33c4fc22ce4a2f44f840b82f1d7b..58b55456ab60916f10fa602420ad3e85217b4e39 100644 (file)
@@ -112,10 +112,6 @@ SOURCE=.\ssl_engine_config.c
 # End Source File
 # Begin Source File
 
-SOURCE=.\ssl_engine_dh.c
-# End Source File
-# Begin Source File
-
 SOURCE=.\ssl_engine_init.c
 # End Source File
 # Begin Source File
diff --git a/modules/ssl/ssl_engine_dh.c b/modules/ssl/ssl_engine_dh.c
deleted file mode 100644 (file)
index 0cc7455..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-#if 0
-=pod
-#endif
-
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*                      _             _
- *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
- * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
- * | | | | | | (_) | (_| |   \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- *                      |_____|
- * ssl_engine_dh.c
- * Diffie-Hellman Built-in Temporary Parameters
- */
-
-#include "ssl_private.h"
-
-/* ----BEGIN GENERATED SECTION-------- */
-
-/*
-** Diffie-Hellman-Parameters: (512 bit)
-**     prime:
-**         00:9f:db:8b:8a:00:45:44:f0:04:5f:17:37:d0:ba:
-**         2e:0b:27:4c:df:1a:9f:58:82:18:fb:43:53:16:a1:
-**         6e:37:41:71:fd:19:d8:d8:f3:7c:39:bf:86:3f:d6:
-**         0e:3e:30:06:80:a3:03:0c:6e:4c:37:57:d0:8f:70:
-**         e6:aa:87:10:33
-**     generator: 2 (0x2)
-** Diffie-Hellman-Parameters: (1024 bit)
-**     prime:
-**         00:d6:7d:e4:40:cb:bb:dc:19:36:d6:93:d3:4a:fd:
-**         0a:d5:0c:84:d2:39:a4:5f:52:0b:b8:81:74:cb:98:
-**         bc:e9:51:84:9f:91:2e:63:9c:72:fb:13:b4:b4:d7:
-**         17:7e:16:d5:5a:c1:79:ba:42:0b:2a:29:fe:32:4a:
-**         46:7a:63:5e:81:ff:59:01:37:7b:ed:dc:fd:33:16:
-**         8a:46:1a:ad:3b:72:da:e8:86:00:78:04:5b:07:a7:
-**         db:ca:78:74:08:7d:15:10:ea:9f:cc:9d:dd:33:05:
-**         07:dd:62:db:88:ae:aa:74:7d:e0:f4:d6:e2:bd:68:
-**         b0:e7:39:3e:0f:24:21:8e:b3
-**     generator: 2 (0x2)
-*/
-
-static unsigned char dh512_p[] = {
-    0x9F, 0xDB, 0x8B, 0x8A, 0x00, 0x45, 0x44, 0xF0, 0x04, 0x5F, 0x17, 0x37,
-    0xD0, 0xBA, 0x2E, 0x0B, 0x27, 0x4C, 0xDF, 0x1A, 0x9F, 0x58, 0x82, 0x18,
-    0xFB, 0x43, 0x53, 0x16, 0xA1, 0x6E, 0x37, 0x41, 0x71, 0xFD, 0x19, 0xD8,
-    0xD8, 0xF3, 0x7C, 0x39, 0xBF, 0x86, 0x3F, 0xD6, 0x0E, 0x3E, 0x30, 0x06,
-    0x80, 0xA3, 0x03, 0x0C, 0x6E, 0x4C, 0x37, 0x57, 0xD0, 0x8F, 0x70, 0xE6,
-    0xAA, 0x87, 0x10, 0x33,
-};
-static unsigned char dh512_g[] = {
-    0x02,
-};
-
-static DH *get_dh512(void)
-{
-    DH *dh;
-
-    if (!(dh = DH_new())) {
-        return NULL;
-    }
-
-    dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
-    dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
-    if (!(dh->p && dh->g)) {
-        DH_free(dh);
-        return NULL;
-    }
-
-    return dh;
-}
-
-static unsigned char dh1024_p[] = {
-    0xD6, 0x7D, 0xE4, 0x40, 0xCB, 0xBB, 0xDC, 0x19, 0x36, 0xD6, 0x93, 0xD3,
-    0x4A, 0xFD, 0x0A, 0xD5, 0x0C, 0x84, 0xD2, 0x39, 0xA4, 0x5F, 0x52, 0x0B,
-    0xB8, 0x81, 0x74, 0xCB, 0x98, 0xBC, 0xE9, 0x51, 0x84, 0x9F, 0x91, 0x2E,
-    0x63, 0x9C, 0x72, 0xFB, 0x13, 0xB4, 0xB4, 0xD7, 0x17, 0x7E, 0x16, 0xD5,
-    0x5A, 0xC1, 0x79, 0xBA, 0x42, 0x0B, 0x2A, 0x29, 0xFE, 0x32, 0x4A, 0x46,
-    0x7A, 0x63, 0x5E, 0x81, 0xFF, 0x59, 0x01, 0x37, 0x7B, 0xED, 0xDC, 0xFD,
-    0x33, 0x16, 0x8A, 0x46, 0x1A, 0xAD, 0x3B, 0x72, 0xDA, 0xE8, 0x86, 0x00,
-    0x78, 0x04, 0x5B, 0x07, 0xA7, 0xDB, 0xCA, 0x78, 0x74, 0x08, 0x7D, 0x15,
-    0x10, 0xEA, 0x9F, 0xCC, 0x9D, 0xDD, 0x33, 0x05, 0x07, 0xDD, 0x62, 0xDB,
-    0x88, 0xAE, 0xAA, 0x74, 0x7D, 0xE0, 0xF4, 0xD6, 0xE2, 0xBD, 0x68, 0xB0,
-    0xE7, 0x39, 0x3E, 0x0F, 0x24, 0x21, 0x8E, 0xB3,
-};
-static unsigned char dh1024_g[] = {
-    0x02,
-};
-
-static DH *get_dh1024(void)
-{
-    DH *dh;
-
-    if (!(dh = DH_new())) {
-        return NULL;
-    }
-
-    dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
-    dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
-    if (!(dh->p && dh->g)) {
-        DH_free(dh);
-        return NULL;
-    }
-
-    return dh;
-}
-
-/* ----END GENERATED SECTION---------- */
-
-DH *ssl_dh_GetTmpParam(int nKeyLen)
-{
-    DH *dh;
-
-    if (nKeyLen == 512)
-        dh = get_dh512();
-    else if (nKeyLen == 1024)
-        dh = get_dh1024();
-    else
-        dh = get_dh1024();
-    return dh;
-}
-
-DH *ssl_dh_GetParamFromFile(char *file)
-{
-    DH *dh = NULL;
-    BIO *bio;
-
-    if ((bio = BIO_new_file(file, "r")) == NULL)
-        return NULL;
-    dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
-    BIO_free(bio);
-    return (dh);
-}
-
-/*
-=cut
-##
-##  Embedded Perl script for generating the temporary DH parameters
-##
-
-require 5.003;
-use strict;
-
-#   configuration
-my $file  = $0;
-my $begin = '----BEGIN GENERATED SECTION--------';
-my $end   = '----END GENERATED SECTION----------';
-
-#   read ourself and keep a backup
-open(FP, "<$file") || die;
-my $source = '';
-$source .= $_ while (<FP>);
-close(FP);
-open(FP, ">$file.bak") || die;
-print FP $source;
-close(FP);
-
-#   generate the DH parameters
-print "1. Generate 512 and 1024 bit Diffie-Hellman parameters (p, g)\n";
-my $rand = '';
-foreach $file (qw(/var/log/messages /var/adm/messages
-                  /kernel /vmunix /vmlinuz /etc/hosts /etc/resolv.conf)) {
-    if (-f $file) {
-        $rand = $file     if ($rand eq '');
-        $rand .= ":$file" if ($rand ne '');
-    }
-}
-$rand = "-rand $rand" if ($rand ne '');
-system("openssl gendh $rand -out dh512.pem 512");
-system("openssl gendh $rand -out dh1024.pem 1024");
-
-#   generate DH param info
-my $dhinfo = '';
-open(FP, "openssl dh -noout -text -in dh512.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -text -in dh1024.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-$dhinfo =~ s|^|** |mg;
-$dhinfo = "\n\/\*\n$dhinfo\*\/\n\n";
-
-my $indent_args = "-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1";
-
-#   generate C source from DH params
-my $dhsource = '';
-open(FP, "openssl dh -noout -C -in dh512.pem | indent $indent_args | expand |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -C -in dh1024.pem | indent $indent_args | expand |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-$dhsource =~ s|(DH\s+\*get_dh)(\d+)[^}]*\n}|static $1$2(void)
-{
-    DH *dh;
-
-    if (!(dh = DH_new())) {
-        return NULL;
-    }
-
-    dh->p = BN_bin2bn(dh$2_p, sizeof(dh$2_p), NULL);
-    dh->g = BN_bin2bn(dh$2_g, sizeof(dh$2_g), NULL);
-    if (!(dh->p && dh->g)) {
-        DH_free(dh);
-        return NULL;
-    }
-
-    return dh;
-}
-|sg;
-
-#   generate output
-my $o = $dhinfo . $dhsource;
-
-#   insert the generated code at the target location
-$source =~ s|(\/\* $begin.+?\n).*\n(.*?\/\* $end)|$1$o$2|s;
-
-#   and update the source on disk
-print "Updating file `$file'\n";
-open(FP, ">$file") || die;
-print FP $source;
-close(FP);
-
-#   cleanup
-unlink("dh512.pem");
-unlink("dh1024.pem");
-
-=pod
-*/
index 9a47bc02fe353e6f7075ed6bf817db2d14c02140..0e352a2d45e6ee15721174426cc668ed7d9959e7 100644 (file)
@@ -1007,10 +1007,14 @@ static void ssl_init_server_certs(server_rec *s,
     const char *rsa_id, *dsa_id;
 #ifdef HAVE_ECC
     const char *ecc_id;
+    EC_GROUP *ecparams;
+    int nid;
+    EC_KEY *eckey;
 #endif
     const char *vhost_id = mctx->sc->vhost_id;
     int i;
     int have_rsa, have_dsa;
+    DH *dhparams;
 #ifdef HAVE_ECC
     int have_ecc;
 #endif
@@ -1058,10 +1062,38 @@ static void ssl_init_server_certs(server_rec *s,
         ssl_die(s);
     }
 
+    /*
+     * 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, APLOGNO()
+                     "Custom DH parameters (%d bits) for %s loaded from %s",
+                     BN_num_bits(dhparams->p), vhost_id,
+                     mctx->pks->cert_files[0]);
+    }
+
 #ifdef HAVE_ECC
-    /* Enable ECDHE by configuring a default curve */
-    SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
-                         EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    /*
+     * 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, APLOGNO()
+                     "ECDH curve %s for %s specified in %s",
+                     OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]);
+    }
+    /*
+     * ...otherwise, configure NIST P-256 (required to enable ECDHE)
+     */
+    else {
+        SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
+                             EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    }
 #endif
 }
 
index 36f3c7046bc2e7049c6ed6ffb0eaec0db3c26860..54edd9ccae4c6d9ff2e0bc048399aab8a69a80b8 100644 (file)
@@ -1300,16 +1300,69 @@ const authz_provider ssl_authz_provider_verify_client =
 */
 
 /*
- * Hand out the already generated DH parameters...
+ * Grab well-defined DH parameters from OpenSSL, see <openssl/bn.h>
+ * (get_rfc*) for all available primes.
+ */
+#define make_get_dh(rfc,size,gen) \
+static DH *get_dh##size(void) \
+{ \
+    DH *dh; \
+    if (!(dh = DH_new())) { \
+        return NULL; \
+    } \
+    dh->p = get_##rfc##_prime_##size(NULL); \
+    BN_dec2bn(&dh->g, #gen); \
+    if (!dh->p || !dh->g) { \
+        DH_free(dh); \
+        return NULL; \
+    } \
+    return dh; \
+}
+
+/*
+ * Prepare DH parameters from 1024 to 4096 bits, in 1024-bit increments
+ */
+make_get_dh(rfc2409, 1024, 2)
+make_get_dh(rfc3526, 2048, 2)
+make_get_dh(rfc3526, 3072, 2)
+make_get_dh(rfc3526, 4096, 2)
+
+/*
+ * Hand out standard DH parameters, based on the authentication strength
  */
 DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
 {
     conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
+    EVP_PKEY *pkey = SSL_get_privatekey(ssl);
+    int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
 
-    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
-                  "handing out parameters for temporary %d bit DH key", keylen);
+    /*
+     * OpenSSL will call us with either keylen == 512 or keylen == 1024
+     * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
+     * Adjust the DH parameter length according to the size of the
+     * RSA/DSA private key used for the current connection, and always
+     * use at least 1024-bit parameters.
+     * Note: This may cause interoperability issues with implementations
+     * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
+     * In this case, SSLCertificateFile can be used to specify fixed
+     * 1024-bit DH parameters (with the effect that OpenSSL skips this
+     * callback).
+     */
+    if ((type == EVP_PKEY_RSA) || (type == EVP_PKEY_DSA)) {
+        keylen = EVP_PKEY_bits(pkey);
+    }
 
-    return ssl_dh_GetTmpParam(keylen);
+    ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
+                  "handing out built-in DH parameters for %d-bit authenticated connection", keylen);
+
+    if (keylen >= 4096)
+        return get_dh4096();
+    else if (keylen >= 3072)
+        return get_dh3072();
+    else if (keylen >= 2048)
+        return get_dh2048();
+    else
+        return get_dh1024();
 }
 
 /*
index 6e47ef63428cd07c69540d449a5b14e7dfcb0e21..01f03be0f404a0642f7da8313c38ecbdf5355483 100644 (file)
@@ -887,8 +887,10 @@ int          ssl_init_ssl_connection(conn_rec *c, request_rec *r);
 void         ssl_pphrase_Handle(server_rec *, apr_pool_t *);
 
 /**  Diffie-Hellman Parameter Support  */
-DH           *ssl_dh_GetTmpParam(int);
-DH           *ssl_dh_GetParamFromFile(char *);
+DH           *ssl_dh_GetParamFromFile(const char *);
+#ifdef HAVE_ECC
+EC_GROUP     *ssl_ec_GetParamFromFile(const char *);
+#endif
 
 unsigned char *ssl_asn1_table_set(apr_hash_t *table,
                                   const char *key,
index a8c36adb47edc54c78e5ed0ed0bc0caf8dd741eb..9f4cfa2c71798d8b2a1878c6d7be98c96e447103 100644 (file)
@@ -481,6 +481,38 @@ BOOL SSL_X509_INFO_load_path(apr_pool_t *ptemp,
     return ok;
 }
 
+/*  _________________________________________________________________
+**
+**  Custom (EC)DH parameter support
+**  _________________________________________________________________
+*/
+
+DH *ssl_dh_GetParamFromFile(const char *file)
+{
+    DH *dh = NULL;
+    BIO *bio;
+
+    if ((bio = BIO_new_file(file, "r")) == NULL)
+        return NULL;
+    dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+    BIO_free(bio);
+    return (dh);
+}
+
+#ifdef HAVE_ECC
+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);
+}
+#endif
+
 /*  _________________________________________________________________
 **
 **  Extra Server Certificate Chain Support