diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-04-04 12:16:56 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-04-04 12:28:25 -0700 |
commit | 61d7d393fb8ef50deed4424db94e3ea72f95c4c2 (patch) | |
tree | 4ad40fdfdd39522549e2c4a4d209de531b0dadd7 | |
parent | 5fb416adb91d46945f82cd9b053a8daf7a5ac030 (diff) | |
download | pyopenssl-61d7d393fb8ef50deed4424db94e3ea72f95c4c2.tar.gz |
ecdh: Use different exception types for different errors
This sneakily fixes some test cases typos, too.
-rw-r--r-- | OpenSSL/SSL.py | 45 | ||||
-rw-r--r-- | OpenSSL/test/test_ssl.py | 43 | ||||
-rw-r--r-- | doc/api/ssl.rst | 6 |
3 files changed, 82 insertions, 12 deletions
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 5b748ee..a3a525e 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -230,6 +230,37 @@ def _asFileDescriptor(obj): +class ECNotAvailable(ValueError): + """ + Raised if a request for an elliptic curve fails because OpenSSL + is compiled without elliptic curve support. + """ + def __init__(self): + ValueError.__init__(self, "OpenSSL is compiled without EC support") + + + +class UnknownObject(ValueError): + """ + Raised if OpenSSL does not recognize the requested object. + """ + def __init__(self, sn): + ValueError.__init__(self, "OpenSSL does not recognize %r" % sn) + self.sn = sn + + + +class UnsupportedEllipticCurve(ValueError): + """ + Raised if OpenSSL does not support the requested elliptic curve. + """ + def __init__(self, sn): + ValueError.__init__( + self, "OpenSSL does not support the elliptic curve %r" % sn) + self.sn = sn + + + def SSLeay_version(type): """ Return a string describing the version of OpenSSL in use. @@ -618,8 +649,10 @@ class Context(object): 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. + Raises a subclass of ``ValueError`` if the linked OpenSSL was + not compiled with elliptical curve support or the specified + curve is not available. You can check the specific subclass, + but, in general, you should just handle ``ValueError``. :param curve_name: The 'short name' of a curve, e.g. 'prime256v1' :type curve_name: str @@ -628,16 +661,14 @@ class Context(object): if _lib.Cryptography_HAS_EC: nid = _lib.OBJ_sn2nid(curve_name.encode('ascii')) if nid == _lib.NID_undef: - raise ValueError("No such OpenSSL object '%s'" % curve_name) + raise UnknownObject(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" - ) + raise UnsupportedEllipticCurve(sn) _lib.SSL_CTX_set_tmp_ecdh(self._context, ecdh) _lib.EC_KEY_free(ecdh) else: - raise ValueError("OpenSSL is compiled without ECDH support") + raise ECNotAvailable() def set_cipher_list(self, cipher_list): diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index b07514f..a1cb417 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -36,7 +36,8 @@ from OpenSSL.SSL import ( SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP, SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL) from OpenSSL.SSL import ( - _Cryptography_HAS_EC, ELLIPTIC_CURVE_DESCRIPTIONS) + _Cryptography_HAS_EC, ELLIPTIC_CURVE_DESCRIPTIONS, + ECNotAvailable, UnknownObject) from OpenSSL.SSL import ( Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError) @@ -1176,14 +1177,50 @@ class ContextTests(TestCase, _LoopbackMixin): 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. + :py:obj:`Context.set_tmp_ecdh_curve` sets the elliptic + curve for Diffie-Hellman to the specified named curve. """ context = Context(TLSv1_METHOD) for curve in ELLIPTIC_CURVE_DESCRIPTIONS.keys(): context.set_tmp_ecdh_curve(curve) # Must not throw. + def test_set_tmp_ecdh_curve_bad_sn(self): + """ + :py:obj:`Context.set_tmp_ecdh_curve` raises + :py:obj:`UnknownObject` if passed a curve_name that OpenSSL + does not recognize and EC is available. It raises + :py:obj:`ECNotAvailable` if EC is not available at all. + """ + context = Context(TLSv1_METHOD) + try: + context.set_tmp_ecdh_curve('not_an_elliptic_curve') + except ECNotAvailable: + self.assertFalse(_Cryptography_HAS_EC) + except UnknownObject: + self.assertTrue(_Cryptography_HAS_EC) + else: + self.assertFalse(True) + + + def test_set_tmp_ecdh_curve_not_a_curve(self): + """ + :py:obj:`Context.set_tmp_ecdh_curve` raises + :py:obj:`UnsupportedEllipticCurve` if passed a curve_name that + OpenSSL cannot instantiate as an elliptic curve. It raises + :py:obj:`ECNotAvailable` if EC is not available at all. + """ + context = Context(TLSv1_METHOD) + try: + context.set_tmp_ecdh_curve('sha256') + except ECNotAvailable: + self.assertFalse(_Cryptography_HAS_EC) + except UnknownObject: + self.assertTrue(_Cryptography_HAS_EC) + else: + self.assertFalse(True) + + def test_has_curve_descriptions(self): """ If the underlying cryptography bindings claim to have elliptic diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index b581450..54d790c 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -334,8 +334,10 @@ Context objects have the following methods: The valid values of *curve_name* are the keys in :py:data:`ELLIPTIC_CURVE_DESCRIPTIONS`. - Raises a ``ValueError`` if the linked OpenSSL was not compiled with - elliptical curve support, or the specified curve is not available. + Raises a subclass of ``ValueError`` if the linked OpenSSL was not + compiled with elliptical curve support or the specified curve is + not available. You can check the specific subclass, but, in + general, you should just handle ``ValueError``. :param curve_name: The 'short name' of a curve, e.g. 'prime256v1' :type curve_name: str |