Skip to content

Commit caa16b4

Browse files
committed
tls: prevent server from using dhe keys < 768
As part of the fix for logjam, node was upgraded to a level of openssl which rejects connections to servers that are using keys smaller than 768 bits. It is still possible, however, to create a server that uses a smaller key size and and older client may be able to connect to it. This PR moves us to a secure by default stance on the server side as well, preventing the creation of a server using a dhe key size less than 768. This can be overridden with the command line option which is also added. It is derived from 9b35be5 which was landed in later io.js/node versions but makes the limit 1024. This PR uses the smaller limit in order to meet the recomendations for logjam while matching was was done on the client side in openssl to minimize the potential impacton users. The command line option will only be documented in the release notes and will not be added to the tls documentation. The goal is that people who are upgrading are aware and can use the option if they run into issues, but otherwise the option is not visible/used. PR-URL: #3890 Fixes: nodejs/Release#49 Reviewed-By: Myles Borins <mborins@us.ibm.com> Reviewed-By: James Snell <jasnell@gmail.com> Reviewed-By: Rod Vagg <r@va.gg> Reviewed-By: Shigeki Ohtsu <ohtsu@iij.ad.jp>
1 parent ca97fb6 commit caa16b4

8 files changed

+90
-2
lines changed

doc/api/tls.markdown

+2-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ automatically set as a listener for the [secureConnection][] event. The
203203

204204
- `dhparam`: DH parameter file to use for DHE key agreement. Use
205205
`openssl dhparam` command to create it. If the file is invalid to
206-
load, it is silently discarded.
206+
load, it is silently discarded. Its key length should be greater
207+
than or equal to 768 bits, otherwise an error will be thrown.
207208

208209
- `handshakeTimeout`: Abort the connection if the SSL/TLS handshake does not
209210
finish in this many milliseconds. The default is 120 seconds.

src/node.cc

+2
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,8 @@ static void ParseArgs(int* argc,
30413041
#if HAVE_OPENSSL
30423042
SSL3_ENABLE = true;
30433043
#endif
3044+
} else if (strcmp(arg, "--allow-insecure-server-dhparam") == 0) {
3045+
ALLOW_INSECURE_SERVER_DHPARAM = true;
30443046
} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
30453047
PrintHelp();
30463048
exit(0);

src/node_crypto.cc

+8
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ namespace node {
7777

7878
bool SSL2_ENABLE = false;
7979
bool SSL3_ENABLE = false;
80+
bool ALLOW_INSECURE_SERVER_DHPARAM = false;
8081

8182
namespace crypto {
8283

@@ -785,6 +786,13 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
785786
if (dh == NULL)
786787
return;
787788

789+
if (!ALLOW_INSECURE_SERVER_DHPARAM) {
790+
const int keylen = BN_num_bits(dh->p);
791+
if (keylen < 768) {
792+
return env->ThrowError("DH parameter is less than 768 bits");
793+
}
794+
}
795+
788796
SSL_CTX_set_options(sc->ctx_, SSL_OP_SINGLE_DH_USE);
789797
int r = SSL_CTX_set_tmp_dh(sc->ctx_, dh);
790798
DH_free(dh);

src/node_crypto.h

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ namespace node {
6363

6464
extern bool SSL2_ENABLE;
6565
extern bool SSL3_ENABLE;
66+
extern bool ALLOW_INSECURE_SERVER_DHPARAM;
6667

6768
namespace crypto {
6869

test/fixtures/keys/Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
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
1+
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
22

33

44
#
@@ -170,6 +170,9 @@ ec-cert.pem: ec-csr.pem ec-key.pem
170170
-signkey ec-key.pem \
171171
-out ec-cert.pem
172172

173+
dh512.pem:
174+
openssl dhparam -out dh512.pem 512
175+
173176
dh1024.pem:
174177
openssl dhparam -out dh1024.pem 1024
175178

test/fixtures/keys/dh512.pem

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-----BEGIN DH PARAMETERS-----
2+
MEYCQQDpl3okBAjG92NSOaQEsIyqzvJRN06yHuGXunxYVIqxg7TnU8DBZW0ZYyiJ
3+
rJLRA/9b9dCk5DXpq1pFGoAkYLoDAgEC
4+
-----END DH PARAMETERS-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
//
22+
// Flags: --allow-insecure-server-dhparam
23+
24+
var common = require('../common');
25+
26+
var assert = require('assert');
27+
var tls = require('tls');
28+
var fs = require('fs');
29+
var key = fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem');
30+
var cert = fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem');
31+
32+
function loadDHParam(n) {
33+
var path = common.fixturesDir;
34+
if (n !== 'error') path += '/keys';
35+
return fs.readFileSync(path + '/dh' + n + '.pem');
36+
}
37+
38+
// validate that the server will accept a key smaller than
39+
// 768 provided the required command line option is specified
40+
// the flags statement above ensures that the test harnesss
41+
// runs the test with the required command line option
42+
function test512() {
43+
var options = {
44+
key: key,
45+
cert: cert,
46+
dhparam: loadDHParam(512)
47+
};
48+
49+
var server = tls.createServer(options)
50+
}
51+
52+
test512();

test/simple/test-tls-dhe.js

+17
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,25 @@ function testError() {
9595
ntests++;
9696
}
9797

98+
// validate that the server will not allow keys less than
99+
// 768
100+
function test512() {
101+
var options = {
102+
key: key,
103+
cert: cert,
104+
dhparam: loadDHParam(512)
105+
};
106+
107+
assert.throws(function() {var server = tls.createServer(options)},
108+
'Should not be able to create server with key smaller than 768');
109+
}
110+
111+
// test client/server communication with different key sizes
98112
test1024();
99113

114+
// test server key length enforcement
115+
test512();
116+
100117
process.on('exit', function() {
101118
assert.equal(ntests, nsuccess);
102119
});

0 commit comments

Comments
 (0)