[squid-dev] [PATCH] TLS: Add support for EECDH
Paulo Matias
matias at ufscar.br
Fri Jun 5 19:21:13 UTC 2015
Hi Amos,
I have implemented your suggestions. The updated patch follows at the
end of this message. Please tell me if I forgot anything.
On 04-06-2015 20:39, Amos Jeffries wrote:
> 1) The 'dhfile' pointer must now never be freed. Since it is either a
> pointer into tls_dh or eecdhCurve allocated memory.
> - It should simply be set to dhfile=NULL where it was free()'d, and now
> also when the tls_dh and/or eecdhCurve memory is released.
> - I spotted the destructor safe_free(dhfile), maybe elsewhere as well.
The 'dhfile' pointer is still only set by the (deprecated) "dhparams="
option. The pointer to tls_dh or eecdhCurve is instead copied to the local
'dhFile' pointer, which can be discarded without issues after the call
to Ssl::readDHParams. However I should not have named the local pointer
'dhFile', as it causes confusion. I have now renamed it to
'dhParamsFile'. Please tell me if I overlooked anything.
Best regards,
Paulo Matias
-------------- next part --------------
=== modified file 'doc/release-notes/release-4.sgml'
--- doc/release-notes/release-4.sgml 2015-05-22 09:42:55 +0000
+++ doc/release-notes/release-4.sgml 2015-06-04 14:59:38 +0000
@@ -137,6 +137,12 @@
<p>All <em>options=</em> values for SSLv2
configuration or disabling have been removed.
<p>Removed <em>version=</em> option. Use <em>options=</em> instead.
+ <p>New <em>options=SINGLE_ECDH_USE</em> parameter to enable ephemeral
+ ECDH key exchange.
+ <p>Deprecated <em>dhparams=</em> option. Use <em>tls-dh=</em> instead.
+ The new option allows to optionally specify an elliptic curve for
+ ephemeral ECDH by adding <em>curve-name:</em> in front of the
+ parameter file name.
<p>Manual squid.conf update may be required on upgrade.
<tag>sslcrtd_children</tag>
=== modified file 'src/anyp/PortCfg.cc'
--- src/anyp/PortCfg.cc 2015-05-22 09:42:55 +0000
+++ src/anyp/PortCfg.cc 2015-06-05 18:31:38 +0000
@@ -54,6 +54,7 @@
capath(NULL),
crlfile(NULL),
dhfile(NULL),
+ tls_dh(NULL),
sslflags(NULL),
sslContextSessionId(NULL),
generateHostCertificates(false),
@@ -67,6 +68,7 @@
clientVerifyCrls(),
clientCA(),
dhParams(),
+ eecdhCurve(NULL),
contextMethod(),
sslContextFlags(0),
sslOptions(0)
@@ -95,8 +97,10 @@
safe_free(capath);
safe_free(crlfile);
safe_free(dhfile);
+ safe_free(tls_dh);
safe_free(sslflags);
safe_free(sslContextSessionId);
+ safe_free(eecdhCurve);
#endif
}
@@ -140,6 +144,8 @@
b->crlfile = xstrdup(crlfile);
if (dhfile)
b->dhfile = xstrdup(dhfile);
+ if (tls_dh)
+ b->tls_dh = xstrdup(tls_dh);
if (sslflags)
b->sslflags = xstrdup(sslflags);
if (sslContextSessionId)
@@ -227,8 +233,23 @@
contextMethod = SSLv23_server_method();
#endif
- if (dhfile)
- dhParams.reset(Ssl::readDHParams(dhfile));
+ const char *dhParamsFile = dhfile; // backward compatibility for dhparams= configuration
+ safe_free(eecdhCurve); // clear any previous EECDH configuration
+ if (tls_dh && *tls_dh) {
+ eecdhCurve = xstrdup(tls_dh);
+ char *p = strchr(eecdhCurve, ':');
+ if (p) { // tls-dh=eecdhCurve:dhParamsFile
+ *p = '\0';
+ dhParamsFile = p+1;
+ } else { // tls-dh=dhParamsFile
+ dhParamsFile = tls_dh;
+ // a NULL eecdhCurve means "do not use EECDH"
+ safe_free(eecdhCurve);
+ }
+ }
+
+ if (dhParamsFile && *dhParamsFile)
+ dhParams.reset(Ssl::readDHParams(dhParamsFile));
if (sslflags)
sslContextFlags = Ssl::parse_flags(sslflags);
=== modified file 'src/anyp/PortCfg.h'
--- src/anyp/PortCfg.h 2015-01-13 07:25:36 +0000
+++ src/anyp/PortCfg.h 2015-06-03 19:36:39 +0000
@@ -78,6 +78,7 @@
char *capath;
char *crlfile;
char *dhfile;
+ char *tls_dh;
char *sslflags;
char *sslContextSessionId; ///< "session id context" for staticSslContext
bool generateHostCertificates; ///< dynamically make host cert for sslBump
@@ -93,6 +94,7 @@
Ssl::X509_CRL_STACK_Pointer clientVerifyCrls; ///< additional CRL lists to use when verifying the client certificate
Ssl::X509_NAME_STACK_Pointer clientCA; ///< CA certificates to use when verifying client certificates
Ssl::DH_Pointer dhParams; ///< DH parameters for temporary/ephemeral DH key exchanges
+ char *eecdhCurve; ///< Elliptic curve for ephemeral EC-based DH key exchanges
Ssl::ContextMethod contextMethod; ///< The context method (SSL_METHOD) to use when creating certificates
long sslContextFlags; ///< flags modifying the use of SSL
long sslOptions; ///< SSL engine options
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc 2015-05-22 09:42:55 +0000
+++ src/cache_cf.cc 2015-06-03 19:13:55 +0000
@@ -3612,8 +3612,13 @@
safe_free(s->crlfile);
s->crlfile = xstrdup(token + 8);
} else if (strncmp(token, "dhparams=", 9) == 0) {
+ debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: '" << token << "' is deprecated " <<
+ "in " << cfg_directive << ". Use 'tls-dh=' instead.");
safe_free(s->dhfile);
s->dhfile = xstrdup(token + 9);
+ } else if (strncmp(token, "tls-dh=", 7) == 0) {
+ safe_free(s->tls_dh);
+ s->tls_dh = xstrdup(token + 7);
} else if (strncmp(token, "sslflags=", 9) == 0) {
safe_free(s->sslflags);
s->sslflags = xstrdup(token + 9);
@@ -3834,6 +3839,9 @@
if (s->dhfile)
storeAppendPrintf(e, " dhparams=%s", s->dhfile);
+ if (s->tls_dh)
+ storeAppendPrintf(e, " tls-dh=%s", s->tls_dh);
+
if (s->sslflags)
storeAppendPrintf(e, " sslflags=%s", s->sslflags);
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2015-06-02 12:04:00 +0000
+++ src/cf.data.pre 2015-06-03 21:14:04 +0000
@@ -1935,6 +1935,11 @@
Always create a new key when using
temporary/ephemeral DH key exchanges
+ SINGLE_ECDH_USE
+ Enable ephemeral ECDH key exchange.
+ The adopted curve should be specified
+ using the tls-dh option.
+
NO_TICKET
Disable use of RFC5077 session tickets.
Some servers may have problems
@@ -1963,11 +1968,15 @@
the client certificate, in addition to CRLs stored in
the capath. Implies VERIFY_CRL flag below.
- dhparams= File containing DH parameters for temporary/ephemeral
- DH key exchanges. See OpenSSL documentation for details
- on how to create this file.
- WARNING: EDH ciphers will be silently disabled if this
- option is not set.
+ tls-dh=[curve:]file
+ File containing DH parameters for temporary/ephemeral DH key
+ exchanges, optionally prefixed by a curve for ephemeral ECDH
+ key exchanges.
+ See OpenSSL documentation for details on how to create the
+ DH parameter file. Supported curves for ECDH can be listed
+ using the "openssl ecparam -list_curves" command.
+ WARNING: EDH and EECDH ciphers will be silently disabled if
+ this option is not set.
sslflags= Various flags modifying the use of SSL:
DELAYED_AUTH
@@ -2110,6 +2119,11 @@
Always create a new key when using
temporary/ephemeral DH key exchanges
+ SINGLE_ECDH_USE
+ Enable ephemeral ECDH key exchange.
+ The adopted curve should be specified
+ using the tls-dh option.
+
SSL_OP_NO_TICKET
Disable use of RFC5077 session tickets.
Some servers may have problems
@@ -2138,8 +2152,10 @@
the client certificate, in addition to CRLs stored in
the capath. Implies VERIFY_CRL flag below.
- dhparams= File containing DH parameters for temporary/ephemeral
- DH key exchanges.
+ tls-dh=[curve:]file
+ File containing DH parameters for temporary/ephemeral DH key
+ exchanges, optionally prefixed by a curve for ephemeral ECDH
+ key exchanges.
sslflags= Various flags modifying the use of SSL:
DELAYED_AUTH
=== modified file 'src/ssl/support.cc'
--- src/ssl/support.cc 2015-06-03 10:42:08 +0000
+++ src/ssl/support.cc 2015-06-05 18:23:11 +0000
@@ -472,6 +472,11 @@
"NO_TICKET", SSL_OP_NO_TICKET
},
#endif
+#if SSL_OP_SINGLE_ECDH_USE
+ {
+ "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
+ },
+#endif
{
"", 0
},
@@ -824,6 +829,29 @@
}
static bool
+configureSslEECDH(SSL_CTX *sslContext, const char *curve)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
+ int nid = OBJ_sn2nid(curve);
+ if (!nid) {
+ debugs(83, DBG_CRITICAL, "ERROR: Unknown EECDH curve '" << curve << "'");
+ return false;
+ }
+
+ EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid);
+ if (ecdh == NULL)
+ return false;
+
+ const bool ok = SSL_CTX_set_tmp_ecdh(sslContext, ecdh) != 0;
+ EC_KEY_free(ecdh);
+ return ok;
+#else
+ debugs(83, DBG_CRITICAL, "ERROR: EECDH is not available in this build. Please link against OpenSSL>=0.9.8 and ensure OPENSSL_NO_ECDH is not set.");
+ return false;
+#endif
+}
+
+static bool
configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
{
int ssl_error;
@@ -855,6 +883,16 @@
debugs(83, 9, "Setting RSA key generation callback.");
SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
+ if (port.eecdhCurve) {
+ debugs(83, 9, "Setting Ephemeral ECDH curve to " << port.eecdhCurve << ".");
+
+ if (!configureSslEECDH(sslContext, port.eecdhCurve)) {
+ ssl_error = ERR_get_error();
+ debugs(83, DBG_CRITICAL, "ERROR: Unable to configure Ephemeral ECDH: " << ERR_error_string(ssl_error, NULL));
+ return false;
+ }
+ }
+
debugs(83, 9, "Setting CA certificate locations.");
const char *cafile = port.cafile ? port.cafile : port.clientca;
More information about the squid-dev
mailing list