[Python-checkins] cpython: Issue #13627: Add support for SSL Elliptic Curve-based Diffie-Hellman

antoine.pitrou python-checkins at python.org
Mon Dec 19 17:18:23 CET 2011


http://hg.python.org/cpython/rev/8b729d65cfd2
changeset: 74084:8b729d65cfd2
user: Antoine Pitrou <solipsis at pitrou.net>
date: Mon Dec 19 17:16:51 2011 +0100
summary:
 Issue #13627: Add support for SSL Elliptic Curve-based Diffie-Hellman
key exchange, through the SSLContext.set_ecdh_curve() method and the
ssl.OP_SINGLE_ECDH_USE option.
files:
 Doc/library/ssl.rst | 26 +++++++++++++++++++++++++
 Lib/ssl.py | 2 +-
 Lib/test/ssl_servers.py | 5 ++++
 Lib/test/test_ssl.py | 10 +++++++++
 Misc/NEWS | 4 +++
 Modules/_ssl.c | 30 +++++++++++++++++++++++++++++
 6 files changed, 76 insertions(+), 1 deletions(-)
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -428,6 +428,14 @@
 
 .. versionadded:: 3.3
 
+.. data:: OP_SINGLE_ECDH_USE
+
+ Prevents re-use of the same ECDH key for several SSL sessions. This
+ improves forward secrecy but requires more computational resources.
+ This option only applies to server sockets.
+
+ .. versionadded:: 3.3
+
 .. data:: HAS_SNI
 
 Whether the OpenSSL library has built-in support for the *Server Name
@@ -672,6 +680,24 @@
 when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will
 give the currently selected cipher.
 
+.. method:: SSLContext.set_ecdh_curve(curve_name)
+
+ Set the curve name for Elliptic Curve-based Diffie-Hellman (abbreviated
+ ECDH) key exchange. Using Diffie-Hellman key exchange improves forward
+ secrecy at the expense of computational resources (both on the server and
+ on the client). The *curve_name* parameter should be a string describing
+ a well-known elliptic curve, for example ``prime256v1`` for a widely
+ supported curve.
+
+ This setting doesn't apply to client sockets. You can also use the
+ :data:`OP_SINGLE_ECDH_USE` option to further improve security.
+
+ .. versionadded:: 3.3
+
+ .. seealso::
+ `SSL/TLS & Perfect Forward Secrecy <http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html>`_
+ Vincent Bernat.
+
 .. method:: SSLContext.wrap_socket(sock, server_side=False, \
 do_handshake_on_connect=True, suppress_ragged_eofs=True, \
 server_hostname=None)
diff --git a/Lib/ssl.py b/Lib/ssl.py
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -68,7 +68,7 @@
 from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
 from _ssl import (
 OP_ALL, OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1,
- OP_CIPHER_SERVER_PREFERENCE,
+ OP_CIPHER_SERVER_PREFERENCE, OP_SINGLE_ECDH_USE,
 )
 from _ssl import RAND_status, RAND_egd, RAND_add, RAND_bytes, RAND_pseudo_bytes
 from _ssl import (
diff --git a/Lib/test/ssl_servers.py b/Lib/test/ssl_servers.py
--- a/Lib/test/ssl_servers.py
+++ b/Lib/test/ssl_servers.py
@@ -176,6 +176,9 @@
 action='store_false', help='be less verbose')
 parser.add_argument('-s', '--stats', dest='use_stats_handler', default=False,
 action='store_true', help='always return stats page')
+ parser.add_argument('--curve-name', dest='curve_name', type=str,
+ action='store',
+ help='curve name for EC-based Diffie-Hellman')
 args = parser.parse_args()
 
 support.verbose = args.verbose
@@ -186,6 +189,8 @@
 handler_class.root = os.getcwd()
 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 context.load_cert_chain(CERTFILE)
+ if args.curve_name:
+ context.set_ecdh_curve(args.curve_name)
 
 server = HTTPSServer(("", args.port), handler_class, context)
 if args.verbose:
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -99,6 +99,7 @@
 ssl.CERT_OPTIONAL
 ssl.CERT_REQUIRED
 ssl.OP_CIPHER_SERVER_PREFERENCE
+ ssl.OP_SINGLE_ECDH_USE
 self.assertIn(ssl.HAS_SNI, {True, False})
 
 def test_random(self):
@@ -558,6 +559,15 @@
 ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
 ctx.set_default_verify_paths()
 
+ def test_set_ecdh_curve(self):
+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+ ctx.set_ecdh_curve("prime256v1")
+ ctx.set_ecdh_curve(b"prime256v1")
+ 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")
+
 
 class NetworkedTests(unittest.TestCase):
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -419,6 +419,10 @@
 Library
 -------
 
+- Issue #13627: Add support for SSL Elliptic Curve-based Diffie-Hellman
+ key exchange, through the SSLContext.set_ecdh_curve() method and the
+ ssl.OP_SINGLE_ECDH_USE option.
+
 - Issue #13635: Add ssl.OP_CIPHER_SERVER_PREFERENCE, so that SSL servers
 choose the cipher based on their own preferences, rather than on the
 client's.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1986,6 +1986,33 @@
 Py_RETURN_NONE;
 }
 
+static PyObject *
+set_ecdh_curve(PySSLContext *self, PyObject *name)
+{
+ PyObject *name_bytes;
+ int nid;
+ EC_KEY *key;
+
+ if (!PyUnicode_FSConverter(name, &name_bytes))
+ return NULL;
+ assert(PyBytes_Check(name_bytes));
+ nid = OBJ_sn2nid(PyBytes_AS_STRING(name_bytes));
+ Py_DECREF(name_bytes);
+ if (nid == 0) {
+ PyErr_Format(PyExc_ValueError,
+ "unknown elliptic curve name %R", name);
+ return NULL;
+ }
+ key = EC_KEY_new_by_curve_name(nid);
+ if (key == NULL) {
+ _setSSLError(NULL, 0, __FILE__, __LINE__);
+ return NULL;
+ }
+ SSL_CTX_set_tmp_ecdh(self->ctx, key);
+ EC_KEY_free(key);
+ Py_RETURN_NONE;
+}
+
 static PyGetSetDef context_getsetlist[] = {
 {"options", (getter) get_options,
 (setter) set_options, NULL},
@@ -2007,6 +2034,8 @@
 METH_NOARGS, NULL},
 {"set_default_verify_paths", (PyCFunction) set_default_verify_paths,
 METH_NOARGS, NULL},
+ {"set_ecdh_curve", (PyCFunction) set_ecdh_curve,
+ METH_O, NULL},
 {NULL, NULL} /* sentinel */
 };
 
@@ -2452,6 +2481,7 @@
 PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);
 PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE",
 SSL_OP_CIPHER_SERVER_PREFERENCE);
+ PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE);
 
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
 r = Py_True;
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /