diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-03-13 17:22:25 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-03-13 17:40:33 -0700 |
commit | f05a273f1bd6a083cb922cc3c5565ad01cbc05e0 (patch) | |
tree | 41dcb073ffdc3bc83c511ece228bc440a0238005 | |
parent | 76a6133518e5671cc6380304fdc06aae66542d7c (diff) | |
download | pyopenssl-f05a273f1bd6a083cb922cc3c5565ad01cbc05e0.tar.gz |
Identify elliptic curves by short name, not NID
Using NIDs is awkward and requires updating pyOpenSSL every time a new
curve is added. This approach avoids needing to update pyOpenSSL
each time a new curve is added, and it results in more readable code
and a more readable dict ELLIPTIC_CURVE_DESCRIPTIONS.
-rw-r--r-- | OpenSSL/SSL.py | 20 | ||||
-rw-r--r-- | OpenSSL/test/test_ssl.py | 27 | ||||
-rw-r--r-- | doc/api/ssl.rst | 34 |
3 files changed, 50 insertions, 31 deletions
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 602a98c..f6d62d4 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -271,7 +271,8 @@ if _Cryptography_HAS_EC: _num_curves = _lib.EC_get_builtin_curves(_ffi.NULL, 0) _curves = _ffi.new('EC_builtin_curve[]', _num_curves) if _lib.EC_get_builtin_curves(_curves, _num_curves) == _num_curves: - ELLIPTIC_CURVE_DESCRIPTIONS = dict((c.nid, _ffi.string(c.comment)) + ELLIPTIC_CURVE_DESCRIPTIONS = dict((_ffi.string(_lib.OBJ_nid2sn(c.nid)), + _ffi.string(c.comment)) for c in _curves) del _num_curves del _curves @@ -749,16 +750,25 @@ class Context(object): _lib.SSL_CTX_set_tmp_dh(self._context, dh) - def set_tmp_ecdh_by_curve_name(self, curve_name): + def set_tmp_ecdh_curve(self, curve_name): """ Select a curve to use for ECDHE key exchange. - :param curve_name: One of the named curve constants. - :type curve_name: int + The valid values of *curve_name* are the keys in + :py:data:OpenSSL.SSL.ELLIPTIC_CURVE_DESCRIPTIONS. + + Raises a ``ValueError`` if the linked OpenSSL was not compiled with + elliptical curve support, or the specified curve is not available. + + :param curve_name: The 'short name' of a curve, e.g. 'prime256v1' + :type curve_name: str :return: None """ if _lib.Cryptography_HAS_EC: - ecdh = _lib.EC_KEY_new_by_curve_name(curve_name) + nid = _lib.OBJ_sn2nid(curve_name) + if nid == _lib.NID_undef: + raise ValueError("No such OpenSSL object '%s'" % curve_name) + ecdh = _lib.EC_KEY_new_by_curve_name(nid) if ecdh == _ffi.NULL: raise ValueError( "OpenSSL could not load the requested elliptic curve" diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 2686d12..0fc8f29 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -35,7 +35,8 @@ from OpenSSL.SSL import ( SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH, SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP, SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL) -from OpenSSL.SSL import NID_X9_62_prime256v1, _Cryptography_HAS_EC +from OpenSSL.SSL import ( + _Cryptography_HAS_EC, ELLIPTIC_CURVE_DESCRIPTIONS) from OpenSSL.SSL import ( Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError) @@ -1173,15 +1174,21 @@ class ContextTests(TestCase, _LoopbackMixin): # XXX What should I assert here? -exarkun - if _Cryptography_HAS_EC: - def test_set_tmp_ecdh_by_curve_name(self): - """ - :py:obj:`Context.set_tmp_ecdh_by_curve_name` sets the Eliptical - Curve for Diffie-Hellman by the named curve. - """ - context = Context(TLSv1_METHOD) - context.set_tmp_ecdh_by_curve_name(NID_X9_62_prime256v1) - # XXX What should I assert here? -alex + def test_set_tmp_ecdh_curve(self): + """ + :py:obj:`Context.set_tmp_ecdh_curve` sets the Eliptical + Curve for Diffie-Hellman by the named curve. + """ + context = Context(TLSv1_METHOD) + for curve in ELLIPTIC_CURVE_DESCRIPTIONS.keys(): + context.set_tmp_ecdh_curve(curve) # Must not throw. + + if _Cryptography_HAS_EC: + # If EC is compiled in, there must be at least one curve + # Tn theory there could be an OpenSSL that violates this + # assumption. If so, this test will fail and we'll find + # out. + self.assertTrue(ELLIPTIC_CURVE_DESCRIPTIONS) def test_set_cipher_list_bytes(self): diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index 76fb0ad..f169cbc 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -116,16 +116,15 @@ Context, Connection. .. versionadded:: 0.14 -.. py:data:: NID_X9_62_prime192v1 - NID_X9_62_prime192v2 - NID_X9_62_prime192v3 - NID_X9_62_prime239v1 - NID_X9_62_prime239v2 - NID_X9_62_prime239v3 - NID_X9_62_prime256v1 +.. py:data:: ELLIPTIC_CURVE_DESCRIPTIONS - Constants used with :py:meth:`Context.set_tmp_ecdh_by_curve_name` to - specify which elliptical curve should be used. + A dictionary mapping short names of elliptic curves to textual + descriptions. This dictionary contains exactly the set of curves + supported by the OpenSSL build in use. + + The keys are the curve names that can be passed into + Constants used with :py:meth:`Context.set_tmp_ecdh_curve` to + specify which elliptical curve should be used for ECDHE key exchange. .. py:data:: OPENSSL_VERSION_NUMBER @@ -334,16 +333,19 @@ Context objects have the following methods: Load parameters for Ephemeral Diffie-Hellman from *dhfile*. -.. py:method:: Context.set_tmp_ecdh_by_curve_name(curve_name) +.. py:method:: Context.set_tmp_ecdh_curve(curve_name) + + Select a curve to use for ECDHE key exchange. - Configure this connection to people to use Elliptical Curve Diffie-Hellman - key exchanges. + The valid values of *curve_name* are the keys in + :py:data:`ELLIPTIC_CURVE_DESCRIPTIONS`. - ``curve_name`` should be one of the named curve constants, such as - :py:data:`NID_X9_62_prime256v1`. + Raises a ``ValueError`` if the linked OpenSSL was not compiled with + elliptical curve support, or the specified curve is not available. - Raises a ``ValueError`` if the linked OpenSSL was not compiled with - elliptical curve support, or the specified curve is not available. + :param curve_name: The 'short name' of a curve, e.g. 'prime256v1' + :type curve_name: str + :return: None .. py:method:: Context.set_app_data(data) |