From 00688b60426f4ad1e520a0789e32794f4417331d Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Tue, 20 Nov 2018 15:30:34 -0800 Subject: [PATCH 01/15] tls: add code for ERR_TLS_INVALID_PROTOCOL_METHOD Add an error code property to invalid `secureProtocol` method exceptions. Backport-PR-URL: https://github.com/nodejs/node/pull/26951 PR-URL: https://github.com/nodejs/node/pull/24729 Reviewed-By: Joyee Cheung Reviewed-By: James M Snell --- doc/api/errors.md | 6 ++++++ src/node_crypto.cc | 23 ++++++++++++++++------- src/node_errors.h | 1 + 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index 4115d70115b60f..977c83c0d0eeac 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1714,6 +1714,12 @@ recommended to use 2048 bits or larger for stronger security. A TLS/SSL handshake timed out. In this case, the server must also abort the connection. + +### ERR_TLS_INVALID_PROTOCOL_METHOD + +The specified `secureProtocol` method is invalid. It is either unknown, or +disabled because it is insecure. + ### ERR_TLS_INVALID_PROTOCOL_VERSION diff --git a/src/node_crypto.cc b/src/node_crypto.cc index cf7e5557102f1d..cd354c73d5cf25 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -65,6 +65,8 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL namespace node { namespace crypto { +using node::THROW_ERR_TLS_INVALID_PROTOCOL_METHOD; + using v8::Array; using v8::ArrayBufferView; using v8::Boolean; @@ -424,17 +426,23 @@ void SecureContext::Init(const FunctionCallbackInfo& args) { // protocols are supported unless explicitly disabled (which we do below // for SSLv2 and SSLv3.) if (strcmp(*sslmethod, "SSLv2_method") == 0) { - return env->ThrowError("SSLv2 methods disabled"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv2 methods disabled"); + return; } else if (strcmp(*sslmethod, "SSLv2_server_method") == 0) { - return env->ThrowError("SSLv2 methods disabled"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv2 methods disabled"); + return; } else if (strcmp(*sslmethod, "SSLv2_client_method") == 0) { - return env->ThrowError("SSLv2 methods disabled"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv2 methods disabled"); + return; } else if (strcmp(*sslmethod, "SSLv3_method") == 0) { - return env->ThrowError("SSLv3 methods disabled"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv3 methods disabled"); + return; } else if (strcmp(*sslmethod, "SSLv3_server_method") == 0) { - return env->ThrowError("SSLv3 methods disabled"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv3 methods disabled"); + return; } else if (strcmp(*sslmethod, "SSLv3_client_method") == 0) { - return env->ThrowError("SSLv3 methods disabled"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv3 methods disabled"); + return; } else if (strcmp(*sslmethod, "SSLv23_method") == 0) { // noop } else if (strcmp(*sslmethod, "SSLv23_server_method") == 0) { @@ -478,7 +486,8 @@ void SecureContext::Init(const FunctionCallbackInfo& args) { max_version = TLS1_2_VERSION; method = TLS_client_method(); } else { - return env->ThrowError("Unknown method"); + THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "Unknown method"); + return; } } diff --git a/src/node_errors.h b/src/node_errors.h index 2e9fd761a8319d..835794b17820cc 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -55,6 +55,7 @@ void FatalException(v8::Isolate* isolate, V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \ V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \ V(ERR_STRING_TOO_LONG, Error) \ + V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \ V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \ #define V(code, type) \ From 8e14859459c14b36383c6666c4ce8c1ef5c1041b Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Wed, 27 Mar 2019 18:26:34 -0700 Subject: [PATCH 02/15] tls: revert change to invalid protocol error type In https://github.com/nodejs/node/pull/24729, the error was changed to be a TypeError, which is the standard type for this kind of error. However, it was Error in 11.x and earlier, so revert that single aspect, so the backport can be semver-minor. PR-URL: https://github.com/nodejs/node/pull/26951 Reviewed-By: Rod Vagg Reviewed-By: Beth Griggs --- src/node_errors.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_errors.h b/src/node_errors.h index 835794b17820cc..60abddf9f279a2 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -55,7 +55,7 @@ void FatalException(v8::Isolate* isolate, V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \ V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \ V(ERR_STRING_TOO_LONG, Error) \ - V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \ + V(ERR_TLS_INVALID_PROTOCOL_METHOD, Error) \ V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \ #define V(code, type) \ From 8b5d350a35524f77b24974c92e7e4139f27794b5 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Wed, 27 Mar 2019 18:42:57 -0700 Subject: [PATCH 03/15] src: add .code and SSL specific error properties SSL errors have a long structured message, but lacked the standard .code property which can be used for stable comparisons. Add a `code` property, as well as the 3 string components of an SSL error: `reason`, `library`, and `function`. Backport-PR-URL: https://github.com/nodejs/node/pull/26951 PR-URL: https://github.com/nodejs/node/pull/25093 Reviewed-By: James M Snell Reviewed-By: Daniel Bevenius --- src/env.h | 2 ++ src/tls_wrap.cc | 37 +++++++++++++++++++++++- test/parallel/test-tls-alert-handling.js | 14 +++++++-- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/env.h b/src/env.h index 0516c49f36ddcd..e75e336f9d935b 100644 --- a/src/env.h +++ b/src/env.h @@ -185,6 +185,7 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2; V(fingerprint_string, "fingerprint") \ V(flags_string, "flags") \ V(fragment_string, "fragment") \ + V(function_string, "function") \ V(get_data_clone_error_string, "_getDataCloneError") \ V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \ V(gid_string, "gid") \ @@ -208,6 +209,7 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2; V(issuercert_string, "issuerCertificate") \ V(kill_signal_string, "killSignal") \ V(kind_string, "kind") \ + V(library_string, "library") \ V(mac_string, "mac") \ V(main_string, "main") \ V(max_buffer_string, "maxBuffer") \ diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 412d9e8e86eac6..cf579af85ec124 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -40,6 +40,7 @@ using v8::Exception; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; +using v8::Isolate; using v8::Local; using v8::Object; using v8::ReadOnly; @@ -367,9 +368,43 @@ Local TLSWrap::GetSSLError(int status, int* err, std::string* msg) { BUF_MEM* mem; BIO_get_mem_ptr(bio, &mem); + Isolate* isolate = env()->isolate(); + Local context = isolate->GetCurrentContext(); + Local message = - OneByteString(env()->isolate(), mem->data, mem->length); + OneByteString(isolate, mem->data, mem->length); Local exception = Exception::Error(message); + Local obj = exception->ToObject(context).ToLocalChecked(); + + const char* ls = ERR_lib_error_string(ssl_err); + const char* fs = ERR_func_error_string(ssl_err); + const char* rs = ERR_reason_error_string(ssl_err); + + if (ls != nullptr) + obj->Set(context, env()->library_string(), + OneByteString(isolate, ls)).FromJust(); + if (fs != nullptr) + obj->Set(context, env()->function_string(), + OneByteString(isolate, fs)).FromJust(); + if (rs != nullptr) { + obj->Set(context, env()->reason_string(), + OneByteString(isolate, rs)).FromJust(); + + // SSL has no API to recover the error name from the number, so we + // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR", + // which ends up being close to the original error macro name. + std::string code(rs); + + for (auto& c : code) { + if (c == ' ') + c = '_'; + else + c = ::toupper(c); + } + obj->Set(context, env()->code_string(), + OneByteString(isolate, ("ERR_SSL_" + code).c_str())) + .FromJust(); + } if (msg != nullptr) msg->assign(mem->data, mem->data + mem->length); diff --git a/test/parallel/test-tls-alert-handling.js b/test/parallel/test-tls-alert-handling.js index e88453b115e0ea..63b845122fc1f0 100644 --- a/test/parallel/test-tls-alert-handling.js +++ b/test/parallel/test-tls-alert-handling.js @@ -7,6 +7,7 @@ if (!common.hasCrypto) if (!common.opensslCli) common.skip('node compiled without OpenSSL CLI'); +const assert = require('assert'); const net = require('net'); const tls = require('tls'); const fixtures = require('../common/fixtures'); @@ -29,7 +30,11 @@ const opts = { const max_iter = 20; let iter = 0; -const errorHandler = common.mustCall(() => { +const errorHandler = common.mustCall((err) => { + assert.strictEqual(err.code, 'ERR_SSL_WRONG_VERSION_NUMBER'); + assert.strictEqual(err.library, 'SSL routines'); + assert.strictEqual(err.function, 'ssl3_get_record'); + assert.strictEqual(err.reason, 'wrong version number'); errorReceived = true; if (canCloseServer()) server.close(); @@ -81,5 +86,10 @@ function sendBADTLSRecord() { socket.end(BAD_RECORD); }); })); - client.on('error', common.mustCall()); + client.on('error', common.mustCall((err) => { + assert.strictEqual(err.code, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION'); + assert.strictEqual(err.library, 'SSL routines'); + assert.strictEqual(err.function, 'ssl3_read_bytes'); + assert.strictEqual(err.reason, 'tlsv1 alert protocol version'); + })); } From d8cc478ae9bbba763420f238855ca22750371a93 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Tue, 26 Feb 2019 11:30:23 -0800 Subject: [PATCH 04/15] deps: upgrade openssl sources to 1.1.1b This updates all sources in deps/openssl/openssl with openssl-1.1.1b. Backport-PR-URL: https://github.com/nodejs/node/pull/26951 PR-URL: https://github.com/nodejs/node/pull/26327 Reviewed-By: Gireesh Punathil Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- deps/openssl/openssl/crypto/include/internal/bn_conf.h | 1 - deps/openssl/openssl/crypto/include/internal/dso_conf.h | 1 - deps/openssl/openssl/include/openssl/opensslconf.h | 1 - 3 files changed, 3 deletions(-) delete mode 100644 deps/openssl/openssl/crypto/include/internal/bn_conf.h delete mode 100644 deps/openssl/openssl/crypto/include/internal/dso_conf.h delete mode 100644 deps/openssl/openssl/include/openssl/opensslconf.h diff --git a/deps/openssl/openssl/crypto/include/internal/bn_conf.h b/deps/openssl/openssl/crypto/include/internal/bn_conf.h deleted file mode 100644 index 79400c6472a49c..00000000000000 --- a/deps/openssl/openssl/crypto/include/internal/bn_conf.h +++ /dev/null @@ -1 +0,0 @@ -#include "../../../config/bn_conf.h" diff --git a/deps/openssl/openssl/crypto/include/internal/dso_conf.h b/deps/openssl/openssl/crypto/include/internal/dso_conf.h deleted file mode 100644 index e7f2afa9872320..00000000000000 --- a/deps/openssl/openssl/crypto/include/internal/dso_conf.h +++ /dev/null @@ -1 +0,0 @@ -#include "../../../config/dso_conf.h" diff --git a/deps/openssl/openssl/include/openssl/opensslconf.h b/deps/openssl/openssl/include/openssl/opensslconf.h deleted file mode 100644 index 76c99d433ab886..00000000000000 --- a/deps/openssl/openssl/include/openssl/opensslconf.h +++ /dev/null @@ -1 +0,0 @@ -#include "../../config/opensslconf.h" From 1c98b720b12e4f3ec6449e94ce83c7ad68344ebc Mon Sep 17 00:00:00 2001 From: Shigeki Ohtsu Date: Wed, 7 Mar 2018 23:52:52 +0900 Subject: [PATCH 05/15] deps: add s390 asm rules for OpenSSL-1.1.1 This is a floating patch against OpenSSL-1.1.1 to generate asm files with Makefile rules. Backport-PR-URL: https://github.com/nodejs/node/pull/26951 PR-URL: https://github.com/nodejs/node/pull/26327 Reviewed-By: Gireesh Punathil Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis Original: Fixes: https://github.com/nodejs/node/issues/4270 PR-URL: https://github.com/nodejs/node/pull/19794 Reviewed-By: James M Snell Reviewed-By: Rod Vagg Reviewed-By: Michael Dawson --- deps/openssl/openssl/crypto/chacha/build.info | 2 ++ deps/openssl/openssl/crypto/poly1305/build.info | 2 ++ deps/openssl/openssl/crypto/rc4/build.info | 2 ++ 3 files changed, 6 insertions(+) diff --git a/deps/openssl/openssl/crypto/chacha/build.info b/deps/openssl/openssl/crypto/chacha/build.info index 02f8e518aeca90..e75ca72b67d4fb 100644 --- a/deps/openssl/openssl/crypto/chacha/build.info +++ b/deps/openssl/openssl/crypto/chacha/build.info @@ -9,6 +9,8 @@ GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl $(PERLASM_SCHEME) INCLUDE[chacha-armv4.o]=.. GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl $(PERLASM_SCHEME) INCLUDE[chacha-armv8.o]=.. +GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl $(PERLASM_SCHEME) +INCLUDE[chacha-s390x.o]=.. BEGINRAW[Makefile(unix)] ##### CHACHA assembler implementations diff --git a/deps/openssl/openssl/crypto/poly1305/build.info b/deps/openssl/openssl/crypto/poly1305/build.info index 631b32b8e099ac..b730524afb1393 100644 --- a/deps/openssl/openssl/crypto/poly1305/build.info +++ b/deps/openssl/openssl/crypto/poly1305/build.info @@ -17,6 +17,8 @@ GENERATE[poly1305-armv8.S]=asm/poly1305-armv8.pl $(PERLASM_SCHEME) INCLUDE[poly1305-armv8.o]=.. GENERATE[poly1305-mips.S]=asm/poly1305-mips.pl $(PERLASM_SCHEME) INCLUDE[poly1305-mips.o]=.. +GENERATE[poly1305-s390x.S]=asm/poly1305-s390x.pl $(PERLASM_SCHEME) +INCLUDE[poly1305-s390x.o]=.. BEGINRAW[Makefile(unix)] {- $builddir -}/poly1305-%.S: {- $sourcedir -}/asm/poly1305-%.pl diff --git a/deps/openssl/openssl/crypto/rc4/build.info b/deps/openssl/openssl/crypto/rc4/build.info index 46ee66b61c68a2..913942b5e98003 100644 --- a/deps/openssl/openssl/crypto/rc4/build.info +++ b/deps/openssl/openssl/crypto/rc4/build.info @@ -11,6 +11,8 @@ GENERATE[rc4-md5-x86_64.s]=asm/rc4-md5-x86_64.pl $(PERLASM_SCHEME) GENERATE[rc4-parisc.s]=asm/rc4-parisc.pl $(PERLASM_SCHEME) +GENERATE[rc4-s390x.s]=asm/rc4-s390x.pl $(PERLASM_SCHEME) + BEGINRAW[Makefile] # GNU make "catch all" {- $builddir -}/rc4-%.s: {- $sourcedir -}/asm/rc4-%.pl From 8db791d0fe13ac92191d9483c8864ba4ef5b0014 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Tue, 26 Feb 2019 12:25:11 -0800 Subject: [PATCH 06/15] deps: update archs files for OpenSSL-1.1.1b `cd deps/openssl/config; make` updates all archs dependant files. Backport-PR-URL: https://github.com/nodejs/node/pull/26951 PR-URL: https://github.com/nodejs/node/pull/26327 Reviewed-By: Gireesh Punathil Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- deps/openssl/openssl/crypto/include/internal/bn_conf.h | 1 + deps/openssl/openssl/crypto/include/internal/dso_conf.h | 1 + deps/openssl/openssl/include/openssl/opensslconf.h | 1 + 3 files changed, 3 insertions(+) create mode 100644 deps/openssl/openssl/crypto/include/internal/bn_conf.h create mode 100644 deps/openssl/openssl/crypto/include/internal/dso_conf.h create mode 100644 deps/openssl/openssl/include/openssl/opensslconf.h diff --git a/deps/openssl/openssl/crypto/include/internal/bn_conf.h b/deps/openssl/openssl/crypto/include/internal/bn_conf.h new file mode 100644 index 00000000000000..79400c6472a49c --- /dev/null +++ b/deps/openssl/openssl/crypto/include/internal/bn_conf.h @@ -0,0 +1 @@ +#include "../../../config/bn_conf.h" diff --git a/deps/openssl/openssl/crypto/include/internal/dso_conf.h b/deps/openssl/openssl/crypto/include/internal/dso_conf.h new file mode 100644 index 00000000000000..e7f2afa9872320 --- /dev/null +++ b/deps/openssl/openssl/crypto/include/internal/dso_conf.h @@ -0,0 +1 @@ +#include "../../../config/dso_conf.h" diff --git a/deps/openssl/openssl/include/openssl/opensslconf.h b/deps/openssl/openssl/include/openssl/opensslconf.h new file mode 100644 index 00000000000000..76c99d433ab886 --- /dev/null +++ b/deps/openssl/openssl/include/openssl/opensslconf.h @@ -0,0 +1 @@ +#include "../../config/opensslconf.h" From 7393e37af1c1d71ee894709d9378aea9b5d43e7c Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Wed, 28 Nov 2018 17:58:08 -0800 Subject: [PATCH 07/15] tls: support TLSv1.3 This introduces TLS1.3 support and makes it the default max protocol, but also supports CLI/NODE_OPTIONS switches to disable it if necessary. TLS1.3 is a major update to the TLS protocol, with many security enhancements. It should be preferred over TLS1.2 whenever possible. TLS1.3 is different enough that even though the OpenSSL APIs are technically API/ABI compatible, that when TLS1.3 is negotiated, the timing of protocol records and of callbacks broke assumptions hard-coded into the 'tls' module. This change introduces no API incompatibilities when TLS1.2 is negotiated. It is the intention that it be backported to current and LTS release lines with the default maximum TLS protocol reset to 'TLSv1.2'. This will allow users of those lines to explicitly enable TLS1.3 if they want. API incompatibilities between TLS1.2 and TLS1.3 are: - Renegotiation is not supported by TLS1.3 protocol, attempts to call `.renegotiate()` will always fail. - Compiling against a system OpenSSL lower than 1.1.1 is no longer supported (OpenSSL-1.1.0 used to be supported with configure flags). - Variations of `conn.write('data'); conn.destroy()` have undefined behaviour according to the streams API. They may or may not send the 'data', and may or may not cause a ERR_STREAM_DESTROYED error to be emitted. This has always been true, but conditions under which the write suceeds is slightly but observably different when TLS1.3 is negotiated vs when TLS1.2 or below is negotiated. - If TLS1.3 is negotiated, and a server calls `conn.end()` in its 'secureConnection' listener without any data being written, the client will not receive session tickets (no 'session' events will be emitted, and `conn.getSession()` will never return a resumable session). - The return value of `conn.getSession()` API may not return a resumable session if called right after the handshake. The effect will be that clients using the legacy `getSession()` API will resume sessions if TLS1.2 is negotiated, but will do full handshakes if TLS1.3 is negotiated. See https://github.com/nodejs/node/pull/25831 for more information. Backport-PR-URL: https://github.com/nodejs/node/pull/26951 PR-URL: https://github.com/nodejs/node/pull/26209 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Rod Vagg --- doc/api/cli.md | 40 ++++ doc/api/tls.md | 119 +++++++++--- doc/node.1 | 18 ++ lib/_tls_common.js | 36 +++- lib/_tls_wrap.js | 93 +++++++-- lib/internal/stream_base_commons.js | 4 + lib/tls.js | 20 +- src/node_constants.cc | 1 + src/node_constants.h | 8 +- src/node_crypto.cc | 178 ++++++++++++++---- src/node_crypto.h | 5 + src/node_crypto_clienthello.cc | 2 + src/node_crypto_clienthello.h | 6 + src/node_options.cc | 25 +++ src/node_options.h | 6 + src/tls_wrap.cc | 36 +++- src/tls_wrap.h | 1 + test/async-hooks/test-graph.tls-write-12.js | 11 ++ test/async-hooks/test-graph.tls-write.js | 11 +- test/async-hooks/test-tlswrap.js | 7 +- test/parallel/test-crypto.js | 1 + .../test-https-agent-additional-options.js | 3 +- .../test-https-agent-session-eviction.js | 1 + .../test-https-client-renegotiation-limit.js | 3 + test/parallel/test-https-client-resume.js | 3 +- .../test-process-env-allowed-flags.js | 2 +- test/parallel/test-tls-alert-handling.js | 2 +- .../test-tls-async-cb-after-socket-end.js | 5 +- test/parallel/test-tls-basic-validations.js | 6 +- test/parallel/test-tls-cli-max-version-1.2.js | 15 ++ test/parallel/test-tls-cli-max-version-1.3.js | 15 ++ test/parallel/test-tls-cli-min-version-1.0.js | 15 ++ test/parallel/test-tls-cli-min-version-1.1.js | 15 ++ test/parallel/test-tls-cli-min-version-1.3.js | 15 ++ test/parallel/test-tls-client-auth.js | 37 +++- .../test-tls-client-getephemeralkeyinfo.js | 3 + test/parallel/test-tls-client-reject-12.js | 13 ++ test/parallel/test-tls-client-reject.js | 10 +- .../test-tls-client-renegotiation-13.js | 37 ++++ .../test-tls-client-renegotiation-limit.js | 3 + test/parallel/test-tls-client-resume-12.js | 13 ++ test/parallel/test-tls-client-resume.js | 43 ++++- test/parallel/test-tls-destroy-stream-12.js | 13 ++ test/parallel/test-tls-destroy-stream.js | 20 +- .../test-tls-disable-renegotiation.js | 7 + test/parallel/test-tls-getcipher.js | 23 ++- test/parallel/test-tls-getprotocol.js | 1 + test/parallel/test-tls-min-max-version.js | 75 +++++--- .../test-tls-net-socket-keepalive-12.js | 13 ++ .../parallel/test-tls-net-socket-keepalive.js | 6 +- test/parallel/test-tls-server-verify.js | 2 + test/parallel/test-tls-session-cache.js | 3 +- test/parallel/test-tls-set-ciphers-error.js | 3 + test/parallel/test-tls-set-ciphers.js | 134 ++++++++----- test/parallel/test-tls-ticket-12.js | 12 ++ test/parallel/test-tls-ticket-cluster.js | 16 +- test/parallel/test-tls-ticket.js | 42 ++++- 57 files changed, 1051 insertions(+), 206 deletions(-) create mode 100644 test/async-hooks/test-graph.tls-write-12.js create mode 100644 test/parallel/test-tls-cli-max-version-1.2.js create mode 100644 test/parallel/test-tls-cli-max-version-1.3.js create mode 100644 test/parallel/test-tls-cli-min-version-1.0.js create mode 100644 test/parallel/test-tls-cli-min-version-1.1.js create mode 100644 test/parallel/test-tls-cli-min-version-1.3.js create mode 100644 test/parallel/test-tls-client-reject-12.js create mode 100644 test/parallel/test-tls-client-renegotiation-13.js create mode 100644 test/parallel/test-tls-client-resume-12.js create mode 100644 test/parallel/test-tls-destroy-stream-12.js create mode 100644 test/parallel/test-tls-net-socket-keepalive-12.js create mode 100644 test/parallel/test-tls-ticket-12.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 59554b1c679327..266aeffbb8d9d2 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -443,6 +443,44 @@ added: v4.0.0 Specify an alternative default TLS cipher list. Requires Node.js to be built with crypto support (default). +### `--tls-max-v1.2` + + +Set default [`maxVersion`][] to `'TLSv1.2'`. Use to disable support for TLSv1.3. + +### `--tls-max-v1.3` + + +Set default [`maxVersion`][] to `'TLSv1.3'`. Use to enable support for TLSv1.3. + +### `--tls-min-v1.0` + + +Set default [`minVersion`][] to `'TLSv1'`. Use for compatibility with old TLS +clients or servers. + +### `--tls-min-v1.1` + + +Set default [`minVersion`][] to `'TLSv1.1'`. Use for compatibility with old TLS +clients or servers. + +### `--tls-min-v1.3` + + +Set default [`minVersion`][] to `'TLSv1.3'`. Use to disable support for TLSv1.2 +in favour of TLSv1.3, which is more secure. + ### `--trace-deprecation` @@ -136,6 +139,8 @@ threshold is exceeded. The limits are configurable: The default renegotiation limits should not be modified without a full understanding of the implications and risks. +TLSv1.3 does not support renegotiation. + ### Session Resumption Establishing a TLS session can be relatively slow. The process can be sped @@ -176,6 +181,10 @@ as for resumption with session tickets. For debugging, if [`tls.TLSSocket.getTLSTicket()`][] returns a value, the session data contains a ticket, otherwise it contains client-side session state. +With TLSv1.3, be aware that multiple tickets may be sent by the server, +resulting in multiple `'session'` events, see [`'session'`][] for more +information. + Single process servers need no specific implementation to use session tickets. To use session tickets across server restarts or load balancers, servers must all have the same ticket keys. There are three 16-byte keys internally, but the @@ -230,6 +239,9 @@ Node.js is built with a default suite of enabled and disabled TLS ciphers. Currently, the default cipher suite is: ```txt +TLS_AES_256_GCM_SHA384: +TLS_CHACHA20_POLY1305_SHA256: +TLS_AES_128_GCM_SHA256: ECDHE-RSA-AES128-GCM-SHA256: ECDHE-ECDSA-AES128-GCM-SHA256: ECDHE-RSA-AES256-GCM-SHA384: @@ -270,7 +282,19 @@ The default can also be replaced on a per client or server basis using the in [`tls.createServer()`], [`tls.connect()`], and when creating new [`tls.TLSSocket`]s. -Consult [OpenSSL cipher list format documentation][] for details on the format. +The ciphers list can contain a mixture of TLSv1.3 cipher suite names, the ones +that start with `'TLS_'`, and specifications for TLSv1.2 and below cipher +suites. The TLSv1.2 ciphers support a legacy specification format, consult +the OpenSSL [cipher list format][] documentation for details, but those +specifications do *not* apply to TLSv1.3 ciphers. The TLSv1.3 suites can only +be enabled by including their full name in the cipher list. They cannot, for +example, be enabled or disabled by using the legacy TLSv1.2 `'EECDH'` or +`'!EECDH'` specification. + +Despite the relative order of TLSv1.3 and TLSv1.2 cipher suites, the TLSv1.3 +protocol is significantly more secure than TLSv1.2, and will always be chosen +over TLSv1.2 if the handshake indicates it is supported, and if any TLSv1.3 +cipher suites are enabled. The default cipher suite included within Node.js has been carefully selected to reflect current security best practices and risk mitigation. @@ -289,7 +313,18 @@ Old clients that rely on insecure and deprecated RC4 or DES-based ciphers (like Internet Explorer 6) cannot complete the handshaking process with the default configuration. If these clients _must_ be supported, the [TLS recommendations] may offer a compatible cipher suite. For more details -on the format, see the [OpenSSL cipher list format documentation]. +on the format, see the OpenSSL [cipher list format][] documentation. + +There are only 5 TLSv1.3 cipher suites: +- `'TLS_AES_256_GCM_SHA384'` +- `'TLS_CHACHA20_POLY1305_SHA256'` +- `'TLS_AES_128_GCM_SHA256'` +- `'TLS_AES_128_CCM_SHA256'` +- `'TLS_AES_128_CCM_8_SHA256'` + +The first 3 are enabled by default. The last 2 `CCM`-based suites are supported +by TLSv1.3 because they may be more performant on constrained systems, but they +are not enabled by default since they offer less security. ## Class: tls.Server -Set default [`maxVersion`][] to `'TLSv1.2'`. Use to disable support for TLSv1.3. +Set [`tls.DEFAULT_MAX_VERSION`][] to 'TLSv1.2'. Use to disable support for +TLSv1.3. ### `--tls-max-v1.3` -Set default [`maxVersion`][] to `'TLSv1.3'`. Use to enable support for TLSv1.3. +Set default [`tls.DEFAULT_MAX_VERSION`][] to 'TLSv1.3'. Use to enable support +for TLSv1.3. ### `--tls-min-v1.0` -Set default [`minVersion`][] to `'TLSv1'`. Use for compatibility with old TLS -clients or servers. +Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1'. Use for compatibility with +old TLS clients or servers. ### `--tls-min-v1.1` -Set default [`minVersion`][] to `'TLSv1.1'`. Use for compatibility with old TLS -clients or servers. +Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.1'. Use for compatibility +with old TLS clients or servers. ### `--tls-min-v1.3` -Set default [`minVersion`][] to `'TLSv1.3'`. Use to disable support for TLSv1.2 -in favour of TLSv1.3, which is more secure. +Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.3'. Use to disable support +for TLSv1.2, which is not as secure as TLSv1.3. ### `--trace-deprecation` + +* {string} The default value of the `maxVersion` option of + [`tls.createSecureContext()`][]. It can be assigned any of the supported TLS + protocol versions, `TLSv1.3`, `TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. + **Default:** `'TLSv1.2'`, unless changed using CLI options. Using + `--tls-max-v1.2` sets the default to `'TLSv1.2`'. Using `--tls-max-v1.3` sets + the default to `'TLSv1.3'`. If multiple of the options are provided, the + highest maximum is used. + +## tls.DEFAULT_MIN_VERSION + + +* {string} The default value of the `minVersion` option of + [`tls.createSecureContext()`][]. It can be assigned any of the supported TLS + protocol versions, `'TLSv1.3'`, `TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. + **Default:** `'TLSv1'`, unless changed using CLI options. Using + `--tls-min-v1.0` sets the default to `'TLSv1'`. Using `--tls-min-v1.1` sets + the default to `'TLSv1.1'`. Using `--tls-min-v1.3` sets the default to + `'TLSv1.3'`. If multiple of the options are provided, the lowest minimum is + used. + ## Deprecated APIs ### Class: CryptoStream @@ -1660,6 +1680,8 @@ where `secureSocket` has the same API as `pair.cleartext`. [`server.setTicketKeys()`]: #tls_server_setticketkeys_keys [`socket.setTimeout(timeout)`]: #net_socket_settimeout_timeout_callback [`tls.DEFAULT_ECDH_CURVE`]: #tls_tls_default_ecdh_curve +[`tls.DEFAULT_MAX_VERSION`]: #tls_tls_default_max_version +[`tls.DEFAULT_MIN_VERSION`]: #tls_tls_default_min_version [`tls.Server`]: #tls_class_tls_server [`tls.TLSSocket.getPeerCertificate()`]: #tls_tlssocket_getpeercertificate_detailed [`tls.TLSSocket.getSession()`]: #tls_tlssocket_getsession From 7aeca270f6664753c378489311e3314762fb1204 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Fri, 29 Mar 2019 12:34:49 -0700 Subject: [PATCH 12/15] tls: supported shared openssl 1.1.0 PR-URL: https://github.com/nodejs/node/pull/26951 Reviewed-By: Rod Vagg Reviewed-By: Beth Griggs --- lib/_tls_common.js | 2 +- src/node_constants.cc | 2 ++ src/node_crypto.cc | 9 +++++++-- test/parallel/test-tls-client-renegotiation-13.js | 3 +++ test/parallel/test-tls-getcipher.js | 3 +++ test/parallel/test-tls-min-max-version.js | 12 ++++++++++++ test/parallel/test-tls-set-ciphers-error.js | 3 +++ test/parallel/test-tls-set-ciphers.js | 4 ++++ 8 files changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/_tls_common.js b/lib/_tls_common.js index 618f40e7562b05..a0970571be3383 100644 --- a/lib/_tls_common.js +++ b/lib/_tls_common.js @@ -47,7 +47,7 @@ function toV(which, v, def) { if (v === 'TLSv1') return TLS1_VERSION; if (v === 'TLSv1.1') return TLS1_1_VERSION; if (v === 'TLSv1.2') return TLS1_2_VERSION; - if (v === 'TLSv1.3') return TLS1_3_VERSION; + if (v === 'TLSv1.3' && TLS1_3_VERSION) return TLS1_3_VERSION; throw new ERR_TLS_INVALID_PROTOCOL_VERSION(v, which); } diff --git a/src/node_constants.cc b/src/node_constants.cc index f08bcbcb25b6d8..4593760b2f3d94 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -1245,7 +1245,9 @@ void DefineCryptoConstants(Local target) { NODE_DEFINE_CONSTANT(target, TLS1_VERSION); NODE_DEFINE_CONSTANT(target, TLS1_1_VERSION); NODE_DEFINE_CONSTANT(target, TLS1_2_VERSION); +#ifdef TLS1_3_VERSION NODE_DEFINE_CONSTANT(target, TLS1_3_VERSION); +#endif #endif NODE_DEFINE_CONSTANT(target, INT_MAX); } diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 568b44cf26c25a..8cafc808800b0e 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -411,7 +411,12 @@ void SecureContext::New(const FunctionCallbackInfo& args) { // A maxVersion of 0 means "any", but OpenSSL may support TLS versions that // Node.js doesn't, so pin the max to what we do support. -const int MAX_SUPPORTED_VERSION = TLS1_3_VERSION; +const int MAX_SUPPORTED_VERSION = +#ifdef TLS1_3_VERSION + TLS1_3_VERSION; +#else + TLS1_2_VERSION; +#endif void SecureContext::Init(const FunctionCallbackInfo& args) { SecureContext* sc; @@ -947,7 +952,7 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { void SecureContext::SetCipherSuites(const FunctionCallbackInfo& args) { // BoringSSL doesn't allow API config of TLS1.3 cipher suites. -#ifndef OPENSSL_IS_BORINGSSL +#if defined(TLS1_3_VERSION) && !defined(OPENSSL_IS_BORINGSSL) SecureContext* sc; ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); Environment* env = sc->env(); diff --git a/test/parallel/test-tls-client-renegotiation-13.js b/test/parallel/test-tls-client-renegotiation-13.js index bd7ab70316dc59..cce41578ba31b2 100644 --- a/test/parallel/test-tls-client-renegotiation-13.js +++ b/test/parallel/test-tls-client-renegotiation-13.js @@ -4,6 +4,9 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); +if (!require('constants').TLS1_3_VERSION) + common.skip(`openssl ${process.versions.openssl} does not support TLSv1.3`); + // Confirm that for TLSv1.3, renegotiate() is disallowed. const { diff --git a/test/parallel/test-tls-getcipher.js b/test/parallel/test-tls-getcipher.js index 03c32da03c945b..4379d74897a7dd 100644 --- a/test/parallel/test-tls-getcipher.js +++ b/test/parallel/test-tls-getcipher.js @@ -56,6 +56,9 @@ server.listen(0, '127.0.0.1', common.mustCall(function() { })); })); +if (!require('constants').TLS1_3_VERSION) + return console.log('cannot test TLSv1.3 against 1.3-incapable shared lib'); + tls.createServer({ key: fixtures.readKey('agent2-key.pem'), cert: fixtures.readKey('agent2-cert.pem'), diff --git a/test/parallel/test-tls-min-max-version.js b/test/parallel/test-tls-min-max-version.js index f30b9b3b9897c9..cd8bccca04d612 100644 --- a/test/parallel/test-tls-min-max-version.js +++ b/test/parallel/test-tls-min-max-version.js @@ -9,6 +9,13 @@ const { } = require(fixtures.path('tls-connect')); const DEFAULT_MIN_VERSION = tls.DEFAULT_MIN_VERSION; const DEFAULT_MAX_VERSION = tls.DEFAULT_MAX_VERSION; +const tls13 = !!require('constants').TLS1_3_VERSION; + +if (!tls13 && ( + DEFAULT_MAX_VERSION === 'TLSv1.3' || + DEFAULT_MIN_VERSION === 'TLSv1.3')) { + return common.skip('cannot test TLSv1.3 against 1.3-incapable shared lib'); +} function test(cmin, cmax, cprot, smin, smax, sprot, proto, cerr, serr) { assert(proto || cerr || serr, 'test missing any expectations'); @@ -16,6 +23,11 @@ function test(cmin, cmax, cprot, smin, smax, sprot, proto, cerr, serr) { // at Object. (file:line) // from the stack location, we only want the file:line part. const where = (new Error()).stack.split('\n')[2].replace(/[^(]*/, ''); + if (Array.prototype.includes.call(arguments, 'TLSv1.3')) { + console.log('test: skip because TLSv1.3 is not supported'); + console.log(' ', where); + return; + } connect({ client: { checkServerIdentity: (servername, cert) => { }, diff --git a/test/parallel/test-tls-set-ciphers-error.js b/test/parallel/test-tls-set-ciphers-error.js index f963b414f44630..a09c12b321cba0 100644 --- a/test/parallel/test-tls-set-ciphers-error.js +++ b/test/parallel/test-tls-set-ciphers-error.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (!require('constants').TLS1_3_VERSION) + return common.skip('openssl before TLS1.3 does not check for failure'); + const assert = require('assert'); const tls = require('tls'); const fixtures = require('../common/fixtures'); diff --git a/test/parallel/test-tls-set-ciphers.js b/test/parallel/test-tls-set-ciphers.js index ecf9176c4020a6..254cc52ad4ef37 100644 --- a/test/parallel/test-tls-set-ciphers.js +++ b/test/parallel/test-tls-set-ciphers.js @@ -15,6 +15,10 @@ if (tls13) tls.DEFAULT_MAX_VERSION = 'TLSv1.3'; function test(cciphers, sciphers, cipher, cerr, serr) { + if (!tls13 && (/TLS_/.test(cciphers) || /TLS_/.test(sciphers))) { + // Test relies on TLS1.3, skip it. + return; + } assert(cipher || cerr || serr, 'test missing any expectations'); const where = (new Error()).stack.split('\n')[2].replace(/[^(]*/, ''); connect({ From bf2c283555c6b2651d55ef37816616a16c3f37f5 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Thu, 28 Mar 2019 10:52:41 -0700 Subject: [PATCH 13/15] tls: add --tls-min-v1.2 CLI switch For 11.x, the default minimum is TLSv1, so it needs a CLI switch to change the default to the more secure minimum of TLSv1.2. PR-URL: https://github.com/nodejs/node/pull/26951 Reviewed-By: Rod Vagg Reviewed-By: Beth Griggs --- doc/api/cli.md | 8 ++++++++ doc/node.1 | 4 ++++ lib/tls.js | 2 ++ src/node_options.cc | 4 ++++ src/node_options.h | 1 + test/parallel/test-tls-cli-min-version-1.2.js | 15 +++++++++++++++ 6 files changed, 34 insertions(+) create mode 100644 test/parallel/test-tls-cli-min-version-1.2.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 8c68db546b3742..3d4a1adb91aee2 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -475,6 +475,14 @@ added: REPLACEME Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.1'. Use for compatibility with old TLS clients or servers. +### `--tls-min-v1.2` + + +Set default [`minVersion`][] to `'TLSv1.2'`. Use to disable support for TLSv1 +and TLSv1.1 in favour of TLSv1.2, which is more secure. + ### `--tls-min-v1.3` Set [`tls.DEFAULT_MAX_VERSION`][] to 'TLSv1.2'. Use to disable support for @@ -453,7 +453,7 @@ TLSv1.3. ### `--tls-max-v1.3` Set default [`tls.DEFAULT_MAX_VERSION`][] to 'TLSv1.3'. Use to enable support @@ -461,7 +461,7 @@ for TLSv1.3. ### `--tls-min-v1.0` Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1'. Use for compatibility with @@ -469,7 +469,7 @@ old TLS clients or servers. ### `--tls-min-v1.1` Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.1'. Use for compatibility @@ -477,7 +477,7 @@ with old TLS clients or servers. ### `--tls-min-v1.2` Set default [`minVersion`][] to `'TLSv1.2'`. Use to disable support for TLSv1 @@ -485,7 +485,7 @@ and TLSv1.1 in favour of TLSv1.2, which is more secure. ### `--tls-min-v1.3` Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.3'. Use to disable support diff --git a/doc/api/tls.md b/doc/api/tls.md index 574f5519e71d47..d4a333279d9d56 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -1256,7 +1256,7 @@ argument.