Add ECDHE support to TLS

2 min read Original article ↗

Ephemeral ECDH suites require one of {SSL_CTX,SSL}_set_tmp_ecdh{,_callback} to be used. The attached patch is a minimal example that works for me, but I'd suggest expanding this into a function and/or option of tls.Server that takes the EC curve names which should be used. Ideally, the function and option would have the same signature, which is a list of string EC curve names. The NID can be obtained from the string curve name via OBJ_sn2nid(curve_name), like so:

int nid = OBJ_sn2nid("secp521r1");
if (NID_undef == nid)
  handle_error();

Though generating EC keys is extremely fast compared to generating DH params, I'd still suggest only generating one ephemeral key for each curve, when the list of curves is assigned. The callback set using SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, int export, int bit_length) should iterate through this list until it finds a key with the requested bit length, otherwise returning NULL. The bit length can be retrieved as follows:

EC_GROUP *ecgrp = EC_KEY_get0_group(eckey);
if (NULL == ecgrp)
  handle_error();
int bit_len = EC_GROUP_get_degree(ecgrp);

Obviously, more complex but similarly performant key schedules are possible, such as generating a new key for a curve after a time interval, or some number of uses, but the above represents a robust solution.

diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index a2ecfdb..6a69364 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -220,6 +220,11 @@ Handle<Value> SecureContext::Init(const Arguments& args) {

   sc->ctx_ = SSL_CTX_new(method);

+  EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+  if (NULL == ecdh)
+    return ThrowException(Exception::Error(String::New("Unable to generate temp ECDH key")));
+  SSL_CTX_set_tmp_ecdh(sc->ctx_, ecdh);
+
   // SSL session cache configuration
   SSL_CTX_set_session_cache_mode(sc->ctx_,
                                  SSL_SESS_CACHE_SERVER |