-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SECLEVEL set via ciphers option is applied too late in tls.createSecureContext #36655
Comments
@nodejs/crypto |
FWIW, I'm hitting:
in tests using the newly released "node:16" docker image because the default SECLEVEL has increased since the "node:14" docker image:
IIUC, without this bug I would have been able to workaround with using @Hornwitser Thanks very much for this bug report. |
Facing the same issue. this workaround did the job
|
Do we have a fix for this? Else, it needs to do that workaround patch fix for tls.createSecureContext |
with node.js 18, When node.js app is a server, it throws the following error (when a client makes a connection) when I try load the cert later
It seems like the server is unable to find the right cipher and unable to finish serverHello I get the same error mentioned below in node 16 as well if I do the above (i.e load cert after creating securecontext with ciphers). why there is error if i load the cert later i.e
Error
|
any pointer here @Hornwitser ? |
I don't know Node.js TLS internals, and they might change and break code relying on them with any update, so I wouldn't try making it work like that if I were you. The original post describes how to set up an OpenSSL config file with SECLEVEL set in it, pass that in with |
@Hornwitser I tried this where
tried this too
|
Node.js won't read |
Still the same result @richardlau
Tried this too
|
@Hornwitser @richardlau any idea why does this not work |
I do not. |
I suspect this is an ordering issue that can be fixed with the patch below. Feel free to take it and turn it into a pull request. diff --git a/lib/internal/tls/secure-context.js b/lib/internal/tls/secure-context.js
index 0fa3098ffa..40d995f989 100644
--- a/lib/internal/tls/secure-context.js
+++ b/lib/internal/tls/secure-context.js
@@ -148,6 +148,31 @@ function configSecureContext(context, options = kEmptyObject, name = 'options')
ticketKeys,
} = options;
+ // Set the cipher list and cipher suite before anything else because
+ // @SECLEVEL=<n> changes the security level and that affects subsequent
+ // operations.
+ if (ciphers !== undefined && ciphers !== null)
+ validateString(ciphers, `${name}.ciphers`);
+
+ // Work around an OpenSSL API quirk. cipherList is for TLSv1.2 and below,
+ // cipherSuites is for TLSv1.3 (and presumably any later versions). TLSv1.3
+ // cipher suites all have a standard name format beginning with TLS_, so split
+ // the ciphers and pass them to the appropriate API.
+ const {
+ cipherList,
+ cipherSuites,
+ } = processCiphers(ciphers, `${name}.ciphers`);
+
+ if (cipherSuites !== '')
+ context.setCipherSuites(cipherSuites);
+ context.setCiphers(cipherList);
+
+ if (cipherList === '' &&
+ context.getMinProto() < TLS1_3_VERSION &&
+ context.getMaxProto() > TLS1_2_VERSION) {
+ context.setMinProto(TLS1_3_VERSION);
+ }
+
// Add CA before the cert to be able to load cert's issuer in C++ code.
// NOTE(@jasnell): ca, cert, and key are permitted to be falsy, so do not
// change the checks to !== undefined checks.
@@ -218,28 +243,6 @@ function configSecureContext(context, options = kEmptyObject, name = 'options')
}
}
- if (ciphers !== undefined && ciphers !== null)
- validateString(ciphers, `${name}.ciphers`);
-
- // Work around an OpenSSL API quirk. cipherList is for TLSv1.2 and below,
- // cipherSuites is for TLSv1.3 (and presumably any later versions). TLSv1.3
- // cipher suites all have a standard name format beginning with TLS_, so split
- // the ciphers and pass them to the appropriate API.
- const {
- cipherList,
- cipherSuites,
- } = processCiphers(ciphers, `${name}.ciphers`);
-
- if (cipherSuites !== '')
- context.setCipherSuites(cipherSuites);
- context.setCiphers(cipherList);
-
- if (cipherList === '' &&
- context.getMinProto() < TLS1_3_VERSION &&
- context.getMaxProto() > TLS1_2_VERSION) {
- context.setMinProto(TLS1_3_VERSION);
- }
-
validateString(ecdhCurve, `${name}.ecdhCurve`);
context.setECDHCurve(ecdhCurve);
|
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: nodejs#36655 nodejs#49549 Refs: https://github.com/orgs/nodejs/discussions/49634 https://github.com/orgs/nodejs/discussions/46545
@bnoordhuis Thanks for the guidance. Yes, it seems that was the issue. I made the suggested change and built a binary from the source. It seems working now. raised the PR here: #50186 |
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n>changes the security level and that affects subsequent operations. Fixes: nodejs#36655 nodejs#49549 Refs: https://github.com/orgs/nodejs/discussions/49634 https://github.com/orgs/nodejs/discussions/46545
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: nodejs#36655 nodejs#49549 Refs: https://github.com/orgs/nodejs/discussions/49634 https://github.com/orgs/nodejs/discussions/46545 https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: #36655 Fixes: #49549 Refs: https://github.com/orgs/nodejs/discussions/49634 Refs: https://github.com/orgs/nodejs/discussions/46545 Refs: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html PR-URL: #50186 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Paolo Insogna <[email protected]>
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: nodejs#36655 Fixes: nodejs#49549 Refs: https://github.com/orgs/nodejs/discussions/49634 Refs: https://github.com/orgs/nodejs/discussions/46545 Refs: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html PR-URL: nodejs#50186 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Paolo Insogna <[email protected]>
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: #36655 Fixes: #49549 Refs: https://github.com/orgs/nodejs/discussions/49634 Refs: https://github.com/orgs/nodejs/discussions/46545 Refs: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html PR-URL: #50186 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Paolo Insogna <[email protected]>
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: #36655 Fixes: #49549 Refs: https://github.com/orgs/nodejs/discussions/49634 Refs: https://github.com/orgs/nodejs/discussions/46545 Refs: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html PR-URL: #50186 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Paolo Insogna <[email protected]>
Set the cipher list and cipher suite before anything else because @SECLEVEL=<n> changes the security level and that affects subsequent operations. Fixes: #36655 Fixes: #49549 Refs: https://github.com/orgs/nodejs/discussions/49634 Refs: https://github.com/orgs/nodejs/discussions/46545 Refs: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html PR-URL: #50186 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Paolo Insogna <[email protected]>
Linux box 5.8.5-arch1-1 #1 SMP PREEMPT Thu, 27 Aug 2020 18:53:02 +0000 x86_64 GNU/Linux
What steps will reproduce the bug?
Creating secure context with a certificate who's key bits are too small for the default openssl SECLEVEL causes the operation to throw a key "too small error" even if the SECLEVEL is overridden to an acceptable value via the ciphers option. For example the following code throws on my system (note requires node-forge to generate the certificate, install it via npm):
With the following error:
(if this does not reproduce the issue it might be possible that the system default SECLEVEL is 0, in this case it's possible to reproduce the issue by adding the following to a .cnf file
And then pointing node to it via the
--openssl-config
option.)How often does it reproduce? Is there a required condition?
Whenever the default/configured SECLEVEL for openssl is greater than the one requested via the ciphers and this level is more strict than the certificate used requires.
What is the expected behavior?
Setting SECLEVEL via the ciphers option as Documented in the Ciphers List Format should allow a weaker certificate to be used than the system default SECLEVEL allows.
What do you see instead?
Node.js tries to add the certificate to the secure context before the ciphers option is process, which causes the default SECLEVEL to be used when evaluating the certificate. I know this to be the case as I tested reordering the certificate being added to the security context by using the following monkey patch:
If this is added to the reproduction code above it no longer throws a key too small error.
Additional information
Being able to set the security level in order to use certificates weaken than the default security setting allows is useful for automated testing. A viable workaround is to set the level through an openssl config file like shown above, but it's a bit of a sledgehammer approach. It looks like there's a SSL_CTX_set_security_level function to directly set the level instead of doing through the ciphers option, which might be a better alternative to setting it via the ciphers option.
Note that the reverse situation also does not work correctly: if SECLEVEL is increased in the ciphers option the certificate is still accepted, but handshakes with the server fails with
Error: Client network socket disconnected before secure TLS connection was established
.The text was updated successfully, but these errors were encountered: