summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-04-04 12:16:56 -0700
committerAndy Lutomirski <luto@amacapital.net>2014-04-04 12:28:25 -0700
commit61d7d393fb8ef50deed4424db94e3ea72f95c4c2 (patch)
tree4ad40fdfdd39522549e2c4a4d209de531b0dadd7
parent5fb416adb91d46945f82cd9b053a8daf7a5ac030 (diff)
downloadpyopenssl-61d7d393fb8ef50deed4424db94e3ea72f95c4c2.tar.gz
ecdh: Use different exception types for different errors
This sneakily fixes some test cases typos, too.
-rw-r--r--OpenSSL/SSL.py45
-rw-r--r--OpenSSL/test/test_ssl.py43
-rw-r--r--doc/api/ssl.rst6
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