diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index dc3a0431bee..89bd5d8e3be 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -201,9 +201,12 @@ automatically set as a listener for the [secureConnection][] event. The Defaults to `prime256v1`. Consult [RFC 4492] for more details. - - `dhparam`: DH parameter file to use for DHE key agreement. Use - `openssl dhparam` command to create it. If the file is invalid to - load, it is silently discarded. + - `dhparam`: A string or `Buffer` containing Diffie Hellman parameters, + required for Perfect Forward Secrecy. Use `openssl dhparam` to create it. + Its key length should be greater than or equal to 1024 bits, otherwise + it throws an error. It is strongly recommended to use 2048 bits or + more for stronger security. If omitted or invalid, it is silently + discarded and DHE ciphers won't be available. - `handshakeTimeout`: Abort the connection if the SSL/TLS handshake does not finish in this many milliseconds. The default is 120 seconds. diff --git a/lib/_tls_common.js b/lib/_tls_common.js index 72648be9843..c612b21d81a 100644 --- a/lib/_tls_common.js +++ b/lib/_tls_common.js @@ -143,7 +143,11 @@ exports.createSecureContext = function createSecureContext(options, context) { else if (options.ecdhCurve) c.context.setECDHCurve(options.ecdhCurve); - if (options.dhparam) c.context.setDHParam(options.dhparam); + if (options.dhparam) { + var warning = c.context.setDHParam(options.dhparam); + if (warning) + console.trace(warning); + } if (options.crl) { if (util.isArray(options.crl)) { diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 03650a98c61..57c50852cd7 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -792,7 +792,16 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo& args) { if (dh == NULL) return; + const int size = BN_num_bits(dh->p); + if (size < 1024) { + return env->ThrowError("DH parameter is less than 1024 bits"); + } else if (size < 2048) { + args.GetReturnValue().Set(FIXED_ONE_BYTE_STRING( + env->isolate(), "WARNING: DH parameter is less than 2048 bits")); + } + SSL_CTX_set_options(sc->ctx_, SSL_OP_SINGLE_DH_USE); + int r = SSL_CTX_set_tmp_dh(sc->ctx_, dh); DH_free(dh); diff --git a/test/simple/test-tls-dhe.js b/test/simple/test-tls-dhe.js index 3975c5ed40a..568cfa3d1f6 100644 --- a/test/simple/test-tls-dhe.js +++ b/test/simple/test-tls-dhe.js @@ -81,8 +81,9 @@ function test(keylen, expectedCipher, cb) { } function test512() { - test(512, 'DHE-RSA-AES128-SHA256', test1024); - ntests++; + assert.throws(function() { + test(512, 'DHE-RSA-AES128-SHA256', null); + }, /DH parameter is less than 1024 bits/); } function test1024() { @@ -96,12 +97,13 @@ function test2048() { } function testError() { - test('error', 'ECDHE-RSA-AES128-SHA256', null); + test('error', 'ECDHE-RSA-AES128-SHA256', test512); ntests++; } -test512(); +test1024(); process.on('exit', function() { assert.equal(ntests, nsuccess); + assert.equal(ntests, 3); });