Based on the recent found weaknesses in DH key exchange,

        http://weakdh.org/

I increased ssl_dh_parameters_length to 2048 bits, and found waited
for 5+ minutes for dovecot to come back online after a restart.
Unless you got a fast machine, the initialization of DH parameters can
exceed your patience.

Regeneration may not be a problem (if ssl_parameters_regenerate=0 or if
Dovecot uses old parameters until regeneration finishes), but for cold
starts, the server can be tied up for a few minutes creating DH parameters
while clients queue up.

I ran "openssl dhparam 2048" and got wildly varying run times of 1m45s,
11m56s, 0.4s, 2m19s, 3h23s.  Most of the time was spent testing primality
of candidate p *and* (p-1)/2 -- so called "safe prime".  If you're
unlucky, this can take a long time.

However, it appears "safe" primes are not what they're cracked up to be
-- they offer some guarantees, but are not safer than non-safe primes.
Creating DH parameters without requiring primality of (p-1)/2 (i.e. what
"openssl dhparam -dsaparam" does) results in much lower run-time bounds.

I cribbed some OpenSSL code to create this (untested) patch.

--------------------------------------------------------------------------------
--- iostream-openssl-params.c~  Tue Nov  3 16:08:38 2015
+++ iostream-openssl-params.c   Tue Nov  3 15:43:39 2015
@@ -6,5 +6,2 @@

-/* 2 or 5. Haven't seen their difference explained anywhere, but 2 is the
-   default.. */
-#define DH_GENERATOR 2

@@ -14,2 +11,3 @@
        DH *dh;
+       DSA *dsa;
        unsigned char *p;
@@ -17,3 +15,13 @@

-       dh = DH_generate_parameters(bitsize, DH_GENERATOR, NULL, NULL);
+       dsa = DSA_generate_parameters(bitsize, NULL, 0, NULL, NULL, NULL, NULL);
+       if (dsa == NULL) {
+               *error_r = t_strdup_printf(
+                       "DSA_generate_parameters(bits=%d) failed: %s",
+                       bitsize, openssl_iostream_error());
+               return -1;
+       }
+
+       dh = DSA_dup_DH(dsa);
+       DSA_free(dsa);
+
        if (dh == NULL) {
@@ -20,4 +28,4 @@
                *error_r = t_strdup_printf(
-                       "DH_generate_parameters(bits=%d, gen=%d) failed: %s",
-                       bitsize, DH_GENERATOR, openssl_iostream_error());
+                       "DSA_dup_DH() failed: %s",
+                       openssl_iostream_error());
                return -1;
--------------------------------------------------------------------------------

The other way to prevent long startup times is to pre-compute the DH
parameter using "openssl dhparam -out dh2048.pem 2048".  I can contribute
a patch to do this (read file, convert it into ssl-parameters.dat, then
set/behave like ssl_parameters_regenerate=0), but I couldn't figure
out the best place to do this. ssl_params_if_unchanged()?

Joseph Tam <jtam.h...@gmail.com>

Reply via email to