diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index 1ce524cf84f4f5..9f08beb2495529 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -203,7 +203,8 @@ automatically set as a listener for the [secureConnection][] event. The - `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. + load, it is silently discarded. Its key length should be greater + than or equal to 768 bits, otherwise an error will be thrown. - `handshakeTimeout`: Abort the connection if the SSL/TLS handshake does not finish in this many milliseconds. The default is 120 seconds. diff --git a/src/node.cc b/src/node.cc index 978d3fd477a63e..1da83287c1b42d 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3041,6 +3041,8 @@ static void ParseArgs(int* argc, #if HAVE_OPENSSL SSL3_ENABLE = true; #endif + } else if (strcmp(arg, "--allow-insecure-server-dhparam") == 0) { + ALLOW_INSECURE_SERVER_DHPARAM = true; } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { PrintHelp(); exit(0); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index c81bd807dfce82..454c9be190a351 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -77,6 +77,7 @@ namespace node { bool SSL2_ENABLE = false; bool SSL3_ENABLE = false; +bool ALLOW_INSECURE_SERVER_DHPARAM = false; namespace crypto { @@ -785,6 +786,13 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo& args) { if (dh == NULL) return; + if (!ALLOW_INSECURE_SERVER_DHPARAM) { + const int keylen = BN_num_bits(dh->p); + if (keylen < 768) { + return env->ThrowError("DH parameter is less than 768 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/src/node_crypto.h b/src/node_crypto.h index 0a4c34a1f33836..4687d40e2f8226 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -63,6 +63,7 @@ namespace node { extern bool SSL2_ENABLE; extern bool SSL3_ENABLE; +extern bool ALLOW_INSECURE_SERVER_DHPARAM; namespace crypto { diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile index f7f9c6495f6a5a..ee667c60156db4 100644 --- a/test/fixtures/keys/Makefile +++ b/test/fixtures/keys/Makefile @@ -1,4 +1,4 @@ -all: agent1-cert.pem agent2-cert.pem agent3-cert.pem agent4-cert.pem agent5-cert.pem ca2-crl.pem ec-cert.pem dh1024.pem dh2048.pem +all: agent1-cert.pem agent2-cert.pem agent3-cert.pem agent4-cert.pem agent5-cert.pem ca2-crl.pem ec-cert.pem dh512.pem dh1024.pem dh2048.pem # @@ -170,6 +170,9 @@ ec-cert.pem: ec-csr.pem ec-key.pem -signkey ec-key.pem \ -out ec-cert.pem +dh512.pem: + openssl dhparam -out dh512.pem 512 + dh1024.pem: openssl dhparam -out dh1024.pem 1024 diff --git a/test/fixtures/keys/dh512.pem b/test/fixtures/keys/dh512.pem new file mode 100644 index 00000000000000..dcab8db9fbc81f --- /dev/null +++ b/test/fixtures/keys/dh512.pem @@ -0,0 +1,4 @@ +-----BEGIN DH PARAMETERS----- +MEYCQQDpl3okBAjG92NSOaQEsIyqzvJRN06yHuGXunxYVIqxg7TnU8DBZW0ZYyiJ +rJLRA/9b9dCk5DXpq1pFGoAkYLoDAgEC +-----END DH PARAMETERS----- diff --git a/test/simple/test-tls-dhe-allow-insecure-server-dhparam.js b/test/simple/test-tls-dhe-allow-insecure-server-dhparam.js new file mode 100644 index 00000000000000..033591d36158d9 --- /dev/null +++ b/test/simple/test-tls-dhe-allow-insecure-server-dhparam.js @@ -0,0 +1,52 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Flags: --allow-insecure-server-dhparam + +var common = require('../common'); + +var assert = require('assert'); +var tls = require('tls'); +var fs = require('fs'); +var key = fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'); +var cert = fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'); + +function loadDHParam(n) { + var path = common.fixturesDir; + if (n !== 'error') path += '/keys'; + return fs.readFileSync(path + '/dh' + n + '.pem'); +} + +// validate that the server will accept a key smaller than +// 768 provided the required command line option is specified +// the flags statement above ensures that the test harnesss +// runs the test with the required command line option +function test512() { + var options = { + key: key, + cert: cert, + dhparam: loadDHParam(512) + }; + + var server = tls.createServer(options) +} + +test512(); diff --git a/test/simple/test-tls-dhe.js b/test/simple/test-tls-dhe.js index e4f9d8479401cb..76ff55469d87fd 100644 --- a/test/simple/test-tls-dhe.js +++ b/test/simple/test-tls-dhe.js @@ -95,8 +95,25 @@ function testError() { ntests++; } +// validate that the server will not allow keys less than +// 768 +function test512() { + var options = { + key: key, + cert: cert, + dhparam: loadDHParam(512) + }; + + assert.throws(function() {var server = tls.createServer(options)}, + 'Should not be able to create server with key smaller than 768'); +} + +// test client/server communication with different key sizes test1024(); +// test server key length enforcement +test512(); + process.on('exit', function() { assert.equal(ntests, nsuccess); });