Node: TLS Module: The default ecdhCurve, prime256v1 (aka NIST P-256) is not safe.

Created on 22 Apr 2015  路  36Comments  路  Source: nodejs/node

This document states that the default curve for the ecdhCurve parameter is prime256v1.
https://iojs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener

Appendix A of this document indicates that prime256v1 is also known as NIST P-256.
http://www.rfc-editor.org/rfc/rfc4492.txt

This site indicates that NIST P-256 is not secure.
http://safecurves.cr.yp.to/

I recommend that a safe alternative should be chosen as the default and unsafe curves should not be made available.

Also posted to nodejs: https://github.com/joyent/node/issues/18205

blocked openssl security tls

Most helpful comment

OpenSSL 1.1.0 released, things can start moving ;).

All 36 comments

/cc @indutny

Good catch, now which curve should we choose?

My OpenSSL has these curves defined: https://gist.github.com/silverwind/9e9090833fce8acffa50

I'm having a hard time matching them to the curve names on http://safecurves.cr.yp.to/. Maybe we need to define a custom curve?

According to http://security.stackexchange.com/a/78624 client support is pretty limited besides prime256v1 and secp384r1, so that would heavily limit our options.

@mattcollier The linked SE answer raises some doubts about the 'not safe' statement.

curve25519 is one of the candidates we adopt in the future but it's not been implemented in openssl yet.
We also should care about compatibilities to especially browsers for the default curve. curve25519 is only supported on Safari and Chrome as in http://ianix.com/pub/ed25519-deployment.html while NIST P-256 is included in suiteB and widely deployed at present.
I think we had better to wait and see the ec implementation of openssl and deployment of safer curves in browsers for now.

I think we should aim for secure by default. The curve is configurable with the ecdhCurve option or globally through the tls.DEFAULT_ECDH_CURVE property; people that want to revert to prime256v1, can. We just need to call it out in the release notes.

I don't know what a good replacement is, though. I don't think http://safecurves.cr.yp.to/ considers any of the existing curves in OpenSSL safe.

I think this is a non-issue, let me quote above SE answer:

What they _mean_ is not that some curves are inherently unsafe, but that _safe implementation_ of some curves is easier than for others

Use P-256 to minimize trouble. If you feel that your manhood is threatened by using a 256-bit curve where a 384-bit curve is available, then use P-384

If anything, this should probably be brought up to OpenSSL

Yeah, exactly. There are nothing we could do about it right now. Perhaps somewhere later when OpenSSL will implement these safe curves.

What they mean is not that some curves are inherently unsafe, but that safe implementation of some curves is easier than for others

I don't think that's true. The FIPS mandated curves are suspect because there is reason to believe the NSA may have influenced the decision making process around them.

From https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929:

I no longer trust the constants. I believe the NSA has manipulated them through their relationships with industry.

Let's be straight about it. There are three concerns that are mentioned on safecurves.cr.yp.to:

  • Rigidity - curve was generated using unexplained constant, this is quite questionable and doesn't raise anything except the suspicion
  • Ladder - no ladder scalar multiplication, this may lead to the side-channel attacks. But I believe that OpenSSL mitigates many of them
  • Completeness - requires checks for the points (I believe OpenSSL should be fine with this)
  • Indistinguishability - prevents attackers recognizing the EC curve point in the data stream. This one doesn't really matter for TLS, because it is easy to recognize the protocol anyway.

So only ladder and rigidity actually apply. This is not that great, but not totally bad either IMHO

Yes, it is suspicion. How about adding tls.DEFAULT_ECDH_CURVE to doc as 02a51cf1ce43f55fdaec0f9fbba588431652c767 ?
That's all we can do now.

Sounds good to me!

@indutny Thanks. Probably it is following to Ben's comment.
@silverwind How do you think it for closing this issue?

I understand there is little to be done at this time because openssl does not currently provide a better alternative. Is there some mechanism in place to keep this issue from being lost and forgotten? Perhaps a "good enough for now" tag?

I think it is better to put a comment in the source as

diff --git a/lib/tls.js b/lib/tls.js
index 3ae7a8f..44ea058 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -33,6 +33,7 @@ exports.DEFAULT_CIPHERS = [
   '!CAMELLIA'
 ].join(':');

+// reconsider this when more safer curve is available.
 exports.DEFAULT_ECDH_CURVE = 'prime256v1';

 exports.getCiphers = function() {

I wonder if it's worth to explore client compatibilty for the NIST P-384 aka secp384r1 as a better default. It scores a tiny bit better on the linked table.

@silverwind how is it different?

@indutny ah, it's the same. I've just misread that table.

curve25519 has been suggested in the node issue. Still no OpenSSL support, however.

I linked to the relevant openssl issue, https://github.com/openssl/openssl/issues/309.

Updates for curve25519:

Nice! What about browser support?

Chrome Canary (50) has already support it. https://code.google.com/p/chromium/issues/detail?id=579716
Microsoft is working on it but it is not yet public.
Firefox is not moving to support it for now. https://bugzilla.mozilla.org/show_bug.cgi?id=957105
Others (e.g. Safari) are still unknown.

What's the current status on this one?

I think this is still on hold pending support in FF, IE and Safari.

And OpenSSL 1.1.0

Isn't it only dependant on the OpenSSL update? Since when are clients our concern? :wink:

It's about the default curve to use. I don't think we'd change it to something that's not very usable in a practical setting yet. And yes, we'd need to upgrade openssl first.

And there is no OpenSSL 1.1.0 yet AFAIK

OpenSSL 1.1.0 released, things can start moving ;).

ping @nodejs/crypto ... what can we do on this one?

We are waiting this until upgrading the forthcoming OpenSSL-1.1.1 in Node-v9 or v10.
It will support x25519 for key exchange and Ed25519 in signing and we can be free from NIST-curve at that time.

What about supporting multiple curves and defining a preferred order? Like nginx: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ecdh_curve

Since OpenSSL 1.1.0 just landed, I think this can be looked at again.

I think the discussion of the default curve is obsolete since it's default value has changed to 'auto', see https://github.com/nodejs/node/commit/af78840b194528a147e4683aed27a320f9764ea5.

Good find, I'll close this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stevenvachon picture stevenvachon  路  3Comments

jmichae3 picture jmichae3  路  3Comments

srl295 picture srl295  路  3Comments

danielstaleiny picture danielstaleiny  路  3Comments

sandeepks1 picture sandeepks1  路  3Comments