diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index dc72f67c6361e2..bfd3f65cb29466 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1769,6 +1769,10 @@ to speed up repeated connections from the same clients. a well-known elliptic curve, for example ``prime256v1`` for a widely supported curve. + For OpenSSL 3.0 and above *curve_name* parameter can be a colon separated + list of curves, for example ``prime256v1:brainpoolP384r1`` specifies two curves that will be + used on a client hello. + This setting doesn't apply to client sockets. You can also use the :data:`OP_SINGLE_ECDH_USE` option to further improve security. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 6ec010d13f9e7e..5f43a12abdf13a 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1375,11 +1375,29 @@ def test_set_ecdh_curve(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx.set_ecdh_curve("prime256v1") ctx.set_ecdh_curve(b"prime256v1") + # Only OpenSSL 3 and above supported for multiple curves + if (IS_OPENSSL_3_0_0 >= 3): + ctx.set_ecdh_curve("prime256v1:brainpoolP384r1") + ctx.set_ecdh_curve(b"prime256v1:brainpoolP384r1") self.assertRaises(TypeError, ctx.set_ecdh_curve) self.assertRaises(TypeError, ctx.set_ecdh_curve, None) self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo") self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo") - + # Multiple bad curves should cause error for any OpenSSL version + self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo:bar") + self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo:bar") + self.assertRaises(ValueError, ctx.set_ecdh_curve, "prime256v1:bar") + self.assertRaises(ValueError, ctx.set_ecdh_curve, b"prime256v1:bar") + self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo:prime256v1") + self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo:prime256v1") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, ":") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, b":") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, "::") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, b"::") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, "prime256v1:") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, b"prime256v1:") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, ":prime256v1") + #self.assertRaises(ValueError, ctx.set_ecdh_curve, b":prime256v1") def test_sni_callback(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) diff --git a/Misc/NEWS.d/next/Library/2024-06-04-07-28-18.gh-issue-109945.02TejW.rst b/Misc/NEWS.d/next/Library/2024-06-04-07-28-18.gh-issue-109945.02TejW.rst new file mode 100644 index 00000000000000..8bb847203aa673 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-06-04-07-28-18.gh-issue-109945.02TejW.rst @@ -0,0 +1 @@ +Adds support for multiple curves to be specified in SSLContext.set_ecdh_curve() for OpenSSL 3.0 and above by setting curve_name to a colon separated list of curves. This allows multiple curves to be passed on a TLS client hello. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 1f5f0215980971..e7533deb1bcda3 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -4379,10 +4379,12 @@ _ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name) /*[clinic end generated code: output=23022c196e40d7d2 input=c2bafb6f6e34726b]*/ { PyObject *name_bytes; - int nid; + if (!PyUnicode_FSConverter(name, &name_bytes)) return NULL; assert(PyBytes_Check(name_bytes)); +#if OPENSSL_VERSION_MAJOR < 3 + int nid; nid = OBJ_sn2nid(PyBytes_AS_STRING(name_bytes)); Py_DECREF(name_bytes); if (nid == 0) { @@ -4390,7 +4392,6 @@ _ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name) "unknown elliptic curve name %R", name); return NULL; } -#if OPENSSL_VERSION_MAJOR < 3 EC_KEY *key = EC_KEY_new_by_curve_name(nid); if (key == NULL) { _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); @@ -4399,8 +4400,10 @@ _ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name) SSL_CTX_set_tmp_ecdh(self->ctx, key); EC_KEY_free(key); #else - if (!SSL_CTX_set1_groups(self->ctx, &nid, 1)) { - _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); + int res = SSL_CTX_set1_groups_list(self->ctx, PyBytes_AS_STRING(name_bytes)); + Py_DECREF(name_bytes); + if (!res) { + PyErr_Format(PyExc_ValueError,"unknown elliptic curves %R", name); return NULL; } #endif pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy