Add tls_eccurve main config option. Bug 1397
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 26 May 2015 15:36:08 +0000 (16:36 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 14 Jun 2015 19:57:55 +0000 (20:57 +0100)
Patch from Suse, massaged by JH

doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/globals.c
src/src/globals.h
src/src/readconf.c
src/src/tls-openssl.c

index d44349c20092edf8000e26485b5eb1b4926f10c7..50dfaf1fdf4367fb63b8275b1f10e53128f13d40 100644 (file)
@@ -13436,6 +13436,7 @@ listed in more than one group.
 .row &%tls_crl%&                     "certificate revocation list"
 .row &%tls_dh_max_bits%&             "clamp D-H bit count suggestion"
 .row &%tls_dhparam%&                 "DH parameters for server"
 .row &%tls_crl%&                     "certificate revocation list"
 .row &%tls_dh_max_bits%&             "clamp D-H bit count suggestion"
 .row &%tls_dhparam%&                 "DH parameters for server"
+.row &%tls_eccurve%&                 "EC curve selection for server"
 .row &%tls_ocsp_file%&               "location of server certificate status proof"
 .row &%tls_on_connect_ports%&        "specify SSMTP (SMTPS) ports"
 .row &%tls_privatekey%&              "location of server private key"
 .row &%tls_ocsp_file%&               "location of server certificate status proof"
 .row &%tls_on_connect_ports%&        "specify SSMTP (SMTPS) ports"
 .row &%tls_privatekey%&              "location of server private key"
@@ -16627,7 +16628,22 @@ prior to the 4.80 release, as Debian used to patch Exim to raise the minimum
 acceptable bound from 1024 to 2048.
 
 
 acceptable bound from 1024 to 2048.
 
 
+.option tls_eccurve main string&!! prime256v1
+.cindex TLS "EC cryptography"
+If built with a recent-enough version of OpenSSL,
+this option selects a EC curve for use by Exim.
+
+Curve names of the form &'prime256v1'& are accepted.
+For even more-recent library versions, names of the form &'P-512'&
+are also accepted, plus the special value &'auto'&
+which tell the library to choose.
+
+If the option is set to an empty string, no EC curves will be enabled.
+
+
 .option tls_ocsp_file main string&!! unset
 .option tls_ocsp_file main string&!! unset
+.cindex TLS "certificate status"
+.cindex TLS "OCSP proof file"
 This option
 must if set expand to the absolute path to a file which contains a current
 status proof for the server's certificate, as obtained from the
 This option
 must if set expand to the absolute path to a file which contains a current
 status proof for the server's certificate, as obtained from the
@@ -16635,6 +16651,8 @@ Certificate Authority.
 
 
 .option tls_on_connect_ports main "string list" unset
 
 
 .option tls_on_connect_ports main "string list" unset
+.cindex SSMTP
+.cindex SMTPS
 This option specifies a list of incoming SSMTP (aka SMTPS) ports that should
 operate the obsolete SSMTP (SMTPS) protocol, where a TLS session is immediately
 set up without waiting for the client to issue a STARTTLS command. For
 This option specifies a list of incoming SSMTP (aka SMTPS) ports that should
 operate the obsolete SSMTP (SMTPS) protocol, where a TLS session is immediately
 set up without waiting for the client to issue a STARTTLS command. For
index e10a32b3f55c5419ee69d9c8ea14acbb0399a1cc..010c90d1522e30c41a6637040462be7b186c68bd 100644 (file)
@@ -37,6 +37,8 @@ Version 4.86
 
 12. A non-SMTP authenticator using information from TLS client certificates.
 
 
 12. A non-SMTP authenticator using information from TLS client certificates.
 
+13. Main option "tls_eccurve" for selecting an Elliptic Curve for TLS.
+
 
 Version 4.85
 ------------
 
 Version 4.85
 ------------
index cb1e8de397b6bcc4e87002a842d771907e3afd14..63674e51c8620116969b82836774f7392cf9ba25 100644 (file)
@@ -156,6 +156,7 @@ that's the interop problem which has been observed: GnuTLS suggesting a higher
 bit-count as "NORMAL" (2432) and Thunderbird dropping connection. */
 int     tls_dh_max_bits        = 2236;
 uschar *tls_dhparam            = NULL;
 bit-count as "NORMAL" (2432) and Thunderbird dropping connection. */
 int     tls_dh_max_bits        = 2236;
 uschar *tls_dhparam            = NULL;
+uschar *tls_eccurve            = US"prime256v1";
 #ifndef DISABLE_OCSP
 uschar *tls_ocsp_file          = NULL;
 #endif
 #ifndef DISABLE_OCSP
 uschar *tls_ocsp_file          = NULL;
 #endif
index 18dcf2fd052a18f20574876db9648bdca4a92c44..36c25906e8985cce25b0273a10ef5aa53efcaaaa 100644 (file)
@@ -118,6 +118,7 @@ extern uschar *tls_channelbinding_b64; /* string of base64 channel binding */
 extern uschar *tls_crl;                /* CRL File */
 extern int     tls_dh_max_bits;        /* don't accept higher lib suggestions */
 extern uschar *tls_dhparam;            /* DH param file */
 extern uschar *tls_crl;                /* CRL File */
 extern int     tls_dh_max_bits;        /* don't accept higher lib suggestions */
 extern uschar *tls_dhparam;            /* DH param file */
+extern uschar *tls_eccurve;            /* EC curve */
 #ifndef DISABLE_OCSP
 extern uschar *tls_ocsp_file;          /* OCSP stapling proof file */
 #endif
 #ifndef DISABLE_OCSP
 extern uschar *tls_ocsp_file;          /* OCSP stapling proof file */
 #endif
index a36fdd3b7e327c966bbb2959f03c65ab391dc945..8b43c7a9fb183789962e9c6c3c9de84a83984211 100644 (file)
@@ -448,6 +448,7 @@ static optionlist optionlist_config[] = {
   { "tls_crl",                  opt_stringptr,   &tls_crl },
   { "tls_dh_max_bits",          opt_int,         &tls_dh_max_bits },
   { "tls_dhparam",              opt_stringptr,   &tls_dhparam },
   { "tls_crl",                  opt_stringptr,   &tls_crl },
   { "tls_dh_max_bits",          opt_int,         &tls_dh_max_bits },
   { "tls_dhparam",              opt_stringptr,   &tls_dhparam },
+  { "tls_eccurve",              opt_stringptr,   &tls_eccurve },
 # ifndef DISABLE_OCSP
   { "tls_ocsp_file",            opt_stringptr,   &tls_ocsp_file },
 # endif
 # ifndef DISABLE_OCSP
   { "tls_ocsp_file",            opt_stringptr,   &tls_ocsp_file },
 # endif
index 21e086e653ca30ccf5094e40281c32d781cd439d..e1dcd77bc67b3bf8dcdcb3869e32e747b0f36021 100644 (file)
@@ -22,6 +22,9 @@ functions from the OpenSSL library. */
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
+#ifndef OPENSSL_NO_ECDH
+# include <openssl/ec.h>
+#endif
 #ifndef DISABLE_OCSP
 # include <openssl/ocsp.h>
 #endif
 #ifndef DISABLE_OCSP
 # include <openssl/ocsp.h>
 #endif
@@ -59,6 +62,16 @@ functions from the OpenSSL library. */
     && (OPENSSL_VERSION_NUMBER & 0x0000ff000L) >= 0x000002000L
 #  define EXIM_HAVE_OPENSSL_CHECKHOST
 # endif
     && (OPENSSL_VERSION_NUMBER & 0x0000ff000L) >= 0x000002000L
 #  define EXIM_HAVE_OPENSSL_CHECKHOST
 # endif
+
+# if !defined(OPENSSL_NO_ECDH)
+#  if OPENSSL_VERSION_NUMBER >= 0x0090800fL
+#   define EXIM_HAVE_ECDH
+#  endif
+#  if OPENSSL_VERSION_NUMBER >= 0x10002000L
+#   define EXIM_HAVE_OPENSSL_ECDH_AUTO
+#   define EXIM_HAVE_OPENSSL_EC_NIST2NID
+#  endif
+# endif
 #endif
 
 #if !defined(EXIM_HAVE_OPENSSL_TLSEXT) && !defined(DISABLE_OCSP)
 #endif
 
 #if !defined(EXIM_HAVE_OPENSSL_TLSEXT) && !defined(DISABLE_OCSP)
@@ -644,42 +657,74 @@ Returns:    TRUE if OK (nothing to set up, or setup worked)
 */
 
 static BOOL
 */
 
 static BOOL
-init_ecdh(SSL_CTX *sctx, host_item *host)
+init_ecdh(SSL_CTX * sctx, host_item * host)
 {
 {
+EC_KEY * ecdh;
+uschar * exp_curve;
+int nid;
+BOOL rv;
+
+#ifdef OPENSSL_NO_ECDH
+return TRUE;
+#else
+
 if (host)      /* No ECDH setup for clients, only for servers */
   return TRUE;
 
 if (host)      /* No ECDH setup for clients, only for servers */
   return TRUE;
 
-#ifndef SSL_CTX_set_tmp_ecdh
-/* No elliptic curve API in OpenSSL, skip it */
+# ifndef EXIM_HAVE_ECDH
 DEBUG(D_tls)
   debug_printf("No OpenSSL API to define ECDH parameters, skipping\n");
 return TRUE;
 DEBUG(D_tls)
   debug_printf("No OpenSSL API to define ECDH parameters, skipping\n");
 return TRUE;
-#else
-# ifndef NID_X9_62_prime256v1
-/* For now, stick to NIST P-256 to get "something" running.
-If that's not available, bail */
-DEBUG(D_tls)
-  debug_printf("NIST P-256 EC curve not available, skipping ECDH setup\n");
-return TRUE;
 # else
 # else
+
+if (!expand_check(tls_eccurve, US"tls_eccurve", &exp_curve))
+  return FALSE;
+if (!exp_curve || !*exp_curve)
+  return TRUE;
+
+#  ifdef EXIM_HAVE_OPENSSL_ECDH_AUTO
+/* check if new enough library to support auto ECDH temp key parameter selection */
+if (Ustrcmp(exp_curve, "auto") == 0)
   {
   {
-  EC_KEY * ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-  BOOL rv;
+  DEBUG(D_tls) debug_printf(
+    "ECDH temp key parameter settings: OpenSSL 1.2+ autoselection\n");
+  SSL_CTX_set_ecdh_auto(sctx, 1);
+  return TRUE;
+  }
+#  endif
 
 
-  /* The "tmp" in the name here refers to setting a tempoary key
-  not to the stability of the interface. */
+DEBUG(D_tls) debug_printf("ECDH: curve '%s'\n", exp_curve);
+if (  (nid = OBJ_sn2nid       (CCS exp_curve)) == NID_undef
+#   ifdef EXIM_HAVE_OPENSSL_EC_NIST2NID
+   && (nid = EC_curve_nist2nid(CCS exp_curve)) == NID_undef
+#   endif
+   )
+  {
+  tls_error(string_sprintf("Unknown curve name tls_eccurve '%s'",
+      exp_curve),
+    host, NULL);
+  return FALSE;
+  }
 
 
-  if ((rv = SSL_CTX_set_tmp_ecdh(sctx, ecdh) != 0))
-    {
-    DEBUG(D_tls) debug_printf("ECDH: enable NIST P-256 curve\n");
-    }
-  else
-    tls_error(US"Error enabling NIST P-256 curve", host, NULL);
-  EC_KEY_free(ecdh);
-  return rv;
+if (!(ecdh = EC_KEY_new_by_curve_name(nid)))
+  {
+  tls_error("Unable to create ec curve", host, NULL);
+  return FALSE;
   }
   }
-# endif
-#endif
+
+/* The "tmp" in the name here refers to setting a temporary key
+not to the stability of the interface. */
+
+if ((rv = SSL_CTX_set_tmp_ecdh(sctx, ecdh) == 0))
+  tls_error(string_sprintf("Error enabling '%s' curve", exp_curve), host, NULL);
+else
+  DEBUG(D_tls) debug_printf("ECDH: enabled '%s' curve\n", exp_curve);
+
+EC_KEY_free(ecdh);
+return !rv;
+
+# endif        /*EXIM_HAVE_ECDH*/
+#endif /*OPENSSL_NO_ECDH*/
 }
 
 
 }
 
 
@@ -1321,6 +1366,7 @@ else
   DEBUG(D_tls) debug_printf("no SSL CTX options to set\n");
 
 /* Initialize with DH parameters if supplied */
   DEBUG(D_tls) debug_printf("no SSL CTX options to set\n");
 
 /* Initialize with DH parameters if supplied */
+/* Initialize ECDH temp key parameter selection */
 
 if (  !init_dh(*ctxp, dhparam, host)
    || !init_ecdh(*ctxp, host)
 
 if (  !init_dh(*ctxp, dhparam, host)
    || !init_ecdh(*ctxp, host)