From 7b8d57a7b806b7af9c5650e8152357d5a5755ca7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 17 Jan 2014 12:08:54 -0600 Subject: [PATCH 01/11] Expose support for using ecdhe with SSL connections --- OpenSSL/SSL.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 8da25e2e0..d960eb36e 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -119,6 +119,15 @@ class _memoryview(object): SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE +NID_X9_62_prime192v1 = _lib.NID_X9_62_prime192v1 +NID_X9_62_prime192v2 = _lib.NID_X9_62_prime192v2 +NID_X9_62_prime192v3 = _lib.NID_X9_62_prime192v3 +NID_X9_62_prime239v1 = _lib.NID_X9_62_prime239v1 +NID_X9_62_prime239v2 = _lib.NID_X9_62_prime239v2 +NID_X9_62_prime239v3 = _lib.NID_X9_62_prime239v3 +NID_X9_62_prime256v1 = _lib.NID_X9_62_prime256v1 + + class Error(Exception): """ An error occurred in an `OpenSSL.SSL` API. @@ -581,6 +590,26 @@ def load_tmp_dh(self, dhfile): _lib.SSL_CTX_set_tmp_dh(self._context, dh) + def set_tmp_ecdh_by_curve_name(self, curve_name): + """ + Configure this connection to people to use Elliptical Curve + Diffie-Hellman key exchanges. + + :param curve_name: One of the named curve constsants. + :return: None + """ + if _lib.Cryptography_HAS_EC: + ecdh = _lib.EC_KEY_new_by_curve_name(curve_name) + if ecdh == _ffi.NULL: + raise ValueError( + "OpenSSL could not load the requested elliptic curve" + ) + _lib.SSL_CTX_set_tmp_ecdh(self._context, ecdh) + _lib.EC_KEY_free(ecdh) + else: + raise ValueError("OpenSSL is compiled without ECDH support") + + def set_cipher_list(self, cipher_list): """ Change the cipher list From a683fc0b8fabb4d763c77d7d04d8bf87799c9ca3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 17 Jan 2014 12:45:56 -0600 Subject: [PATCH 02/11] Corrected a typo --- OpenSSL/SSL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index d960eb36e..325b82568 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -595,7 +595,7 @@ def set_tmp_ecdh_by_curve_name(self, curve_name): Configure this connection to people to use Elliptical Curve Diffie-Hellman key exchanges. - :param curve_name: One of the named curve constsants. + :param curve_name: One of the named curve constants. :return: None """ if _lib.Cryptography_HAS_EC: From 12dc084f3a4e087d240e8393d9dc529240b12e44 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 17 Jan 2014 12:51:31 -0600 Subject: [PATCH 03/11] Added tests --- OpenSSL/SSL.py | 2 ++ OpenSSL/test/test_ssl.py | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 325b82568..e80ea3c49 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -127,6 +127,8 @@ class _memoryview(object): NID_X9_62_prime239v3 = _lib.NID_X9_62_prime239v3 NID_X9_62_prime256v1 = _lib.NID_X9_62_prime256v1 +OPENSSL_NO_EC = not _lib.Cryptography_HAS_EC + class Error(Exception): """ diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index 95cb538b4..c884148e7 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -33,6 +33,7 @@ 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, OPENSSL_NO_EC from OpenSSL.SSL import ( Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError) @@ -1057,6 +1058,17 @@ def test_load_tmp_dh(self): # XXX What should I assert here? -exarkun + if not OPENSSL_NO_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_cipher_list(self): """ :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which From 2c04e86b244055f4f3c9e05eb5cb1e1be787db77 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 17 Jan 2014 12:52:29 -0600 Subject: [PATCH 04/11] Added a gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..539da7411 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.py[co] From 807853c55afd447e821c30232801a72c88a048b4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 17 Jan 2014 13:03:27 -0600 Subject: [PATCH 05/11] Use the internal name --- OpenSSL/SSL.py | 2 +- OpenSSL/test/test_ssl.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index e80ea3c49..62ce6c1c4 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -127,7 +127,7 @@ class _memoryview(object): NID_X9_62_prime239v3 = _lib.NID_X9_62_prime239v3 NID_X9_62_prime256v1 = _lib.NID_X9_62_prime256v1 -OPENSSL_NO_EC = not _lib.Cryptography_HAS_EC +_Cryptography_HAS_EC = _lib.Cryptography_HAS_EC class Error(Exception): diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index c884148e7..5e08e9ba4 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -33,7 +33,7 @@ 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, OPENSSL_NO_EC +from OpenSSL.SSL import NID_X9_62_prime256v1, _Cryptography_HAS_EC from OpenSSL.SSL import ( Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError) @@ -1058,7 +1058,7 @@ def test_load_tmp_dh(self): # XXX What should I assert here? -exarkun - if not OPENSSL_NO_EC: + 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 From d5419e2a78be9d39ddd3983c38fa7e0ec3b23265 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 19 Jan 2014 21:03:36 -0600 Subject: [PATCH 06/11] Added documentation --- doc/api/ssl.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/api/ssl.rst b/doc/api/ssl.rst index b506757d3..76fb0ad06 100644 --- a/doc/api/ssl.rst +++ b/doc/api/ssl.rst @@ -116,6 +116,18 @@ 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 + + Constants used with :py:meth:`Context.set_tmp_ecdh_by_curve_name` to + specify which elliptical curve should be used. + + .. py:data:: OPENSSL_VERSION_NUMBER An integer giving the version number of the OpenSSL library used to build this @@ -322,6 +334,16 @@ 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) + + Configure this connection to people to use Elliptical Curve Diffie-Hellman + key exchanges. + + ``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. .. py:method:: Context.set_app_data(data) From b4e5c8d71227afdead269fdcc7a81cfc674efaff Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 5 Mar 2014 12:54:15 -0800 Subject: [PATCH 07/11] Expose all of the EC curve name constants It would be great if there were a clean way to enumerate them rather than just listing them like this, but I don't know of one. --- OpenSSL/SSL.py | 135 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 03aa47bee..a3e4cd017 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -122,13 +122,148 @@ class _memoryview(object): SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE +NID_X9_62_c2pnb163v1 = _lib.NID_X9_62_c2pnb163v1 +SN_X9_62_c2pnb163v1 = _ffi.string(_lib.SN_X9_62_c2pnb163v1) +NID_X9_62_c2pnb163v2 = _lib.NID_X9_62_c2pnb163v2 +SN_X9_62_c2pnb163v2 = _ffi.string(_lib.SN_X9_62_c2pnb163v2) +NID_X9_62_c2pnb163v3 = _lib.NID_X9_62_c2pnb163v3 +SN_X9_62_c2pnb163v3 = _ffi.string(_lib.SN_X9_62_c2pnb163v3) +NID_X9_62_c2pnb176v1 = _lib.NID_X9_62_c2pnb176v1 +SN_X9_62_c2pnb176v1 = _ffi.string(_lib.SN_X9_62_c2pnb176v1) +NID_X9_62_c2tnb191v1 = _lib.NID_X9_62_c2tnb191v1 +SN_X9_62_c2tnb191v1 = _ffi.string(_lib.SN_X9_62_c2tnb191v1) +NID_X9_62_c2tnb191v2 = _lib.NID_X9_62_c2tnb191v2 +SN_X9_62_c2tnb191v2 = _ffi.string(_lib.SN_X9_62_c2tnb191v2) +NID_X9_62_c2tnb191v3 = _lib.NID_X9_62_c2tnb191v3 +SN_X9_62_c2tnb191v3 = _ffi.string(_lib.SN_X9_62_c2tnb191v3) +NID_X9_62_c2onb191v4 = _lib.NID_X9_62_c2onb191v4 +SN_X9_62_c2onb191v4 = _ffi.string(_lib.SN_X9_62_c2onb191v4) +NID_X9_62_c2onb191v5 = _lib.NID_X9_62_c2onb191v5 +SN_X9_62_c2onb191v5 = _ffi.string(_lib.SN_X9_62_c2onb191v5) +NID_X9_62_c2pnb208w1 = _lib.NID_X9_62_c2pnb208w1 +SN_X9_62_c2pnb208w1 = _ffi.string(_lib.SN_X9_62_c2pnb208w1) +NID_X9_62_c2tnb239v1 = _lib.NID_X9_62_c2tnb239v1 +SN_X9_62_c2tnb239v1 = _ffi.string(_lib.SN_X9_62_c2tnb239v1) +NID_X9_62_c2tnb239v2 = _lib.NID_X9_62_c2tnb239v2 +SN_X9_62_c2tnb239v2 = _ffi.string(_lib.SN_X9_62_c2tnb239v2) +NID_X9_62_c2tnb239v3 = _lib.NID_X9_62_c2tnb239v3 +SN_X9_62_c2tnb239v3 = _ffi.string(_lib.SN_X9_62_c2tnb239v3) +NID_X9_62_c2onb239v4 = _lib.NID_X9_62_c2onb239v4 +SN_X9_62_c2onb239v4 = _ffi.string(_lib.SN_X9_62_c2onb239v4) +NID_X9_62_c2onb239v5 = _lib.NID_X9_62_c2onb239v5 +SN_X9_62_c2onb239v5 = _ffi.string(_lib.SN_X9_62_c2onb239v5) +NID_X9_62_c2pnb272w1 = _lib.NID_X9_62_c2pnb272w1 +SN_X9_62_c2pnb272w1 = _ffi.string(_lib.SN_X9_62_c2pnb272w1) +NID_X9_62_c2pnb304w1 = _lib.NID_X9_62_c2pnb304w1 +SN_X9_62_c2pnb304w1 = _ffi.string(_lib.SN_X9_62_c2pnb304w1) +NID_X9_62_c2tnb359v1 = _lib.NID_X9_62_c2tnb359v1 +SN_X9_62_c2tnb359v1 = _ffi.string(_lib.SN_X9_62_c2tnb359v1) +NID_X9_62_c2pnb368w1 = _lib.NID_X9_62_c2pnb368w1 +SN_X9_62_c2pnb368w1 = _ffi.string(_lib.SN_X9_62_c2pnb368w1) +NID_X9_62_c2tnb431r1 = _lib.NID_X9_62_c2tnb431r1 +SN_X9_62_c2tnb431r1 = _ffi.string(_lib.SN_X9_62_c2tnb431r1) NID_X9_62_prime192v1 = _lib.NID_X9_62_prime192v1 +SN_X9_62_prime192v1 = _ffi.string(_lib.SN_X9_62_prime192v1) NID_X9_62_prime192v2 = _lib.NID_X9_62_prime192v2 +SN_X9_62_prime192v2 = _ffi.string(_lib.SN_X9_62_prime192v2) NID_X9_62_prime192v3 = _lib.NID_X9_62_prime192v3 +SN_X9_62_prime192v3 = _ffi.string(_lib.SN_X9_62_prime192v3) NID_X9_62_prime239v1 = _lib.NID_X9_62_prime239v1 +SN_X9_62_prime239v1 = _ffi.string(_lib.SN_X9_62_prime239v1) NID_X9_62_prime239v2 = _lib.NID_X9_62_prime239v2 +SN_X9_62_prime239v2 = _ffi.string(_lib.SN_X9_62_prime239v2) NID_X9_62_prime239v3 = _lib.NID_X9_62_prime239v3 +SN_X9_62_prime239v3 = _ffi.string(_lib.SN_X9_62_prime239v3) NID_X9_62_prime256v1 = _lib.NID_X9_62_prime256v1 +SN_X9_62_prime256v1 = _ffi.string(_lib.SN_X9_62_prime256v1) +NID_secp112r1 = _lib.NID_secp112r1 +SN_secp112r1 = _ffi.string(_lib.SN_secp112r1) +NID_secp112r2 = _lib.NID_secp112r2 +SN_secp112r2 = _ffi.string(_lib.SN_secp112r2) +NID_secp128r1 = _lib.NID_secp128r1 +SN_secp128r1 = _ffi.string(_lib.SN_secp128r1) +NID_secp128r2 = _lib.NID_secp128r2 +SN_secp128r2 = _ffi.string(_lib.SN_secp128r2) +NID_secp160k1 = _lib.NID_secp160k1 +SN_secp160k1 = _ffi.string(_lib.SN_secp160k1) +NID_secp160r1 = _lib.NID_secp160r1 +SN_secp160r1 = _ffi.string(_lib.SN_secp160r1) +NID_secp160r2 = _lib.NID_secp160r2 +SN_secp160r2 = _ffi.string(_lib.SN_secp160r2) +NID_sect163k1 = _lib.NID_sect163k1 +SN_sect163k1 = _ffi.string(_lib.SN_sect163k1) +NID_sect163r1 = _lib.NID_sect163r1 +SN_sect163r1 = _ffi.string(_lib.SN_sect163r1) +NID_sect163r2 = _lib.NID_sect163r2 +SN_sect163r2 = _ffi.string(_lib.SN_sect163r2) +NID_secp192k1 = _lib.NID_secp192k1 +SN_secp192k1 = _ffi.string(_lib.SN_secp192k1) +NID_secp224k1 = _lib.NID_secp224k1 +SN_secp224k1 = _ffi.string(_lib.SN_secp224k1) +NID_secp224r1 = _lib.NID_secp224r1 +SN_secp224r1 = _ffi.string(_lib.SN_secp224r1) +NID_secp256k1 = _lib.NID_secp256k1 +SN_secp256k1 = _ffi.string(_lib.SN_secp256k1) +NID_secp384r1 = _lib.NID_secp384r1 +SN_secp384r1 = _ffi.string(_lib.SN_secp384r1) +NID_secp521r1 = _lib.NID_secp521r1 +SN_secp521r1 = _ffi.string(_lib.SN_secp521r1) +NID_sect113r1 = _lib.NID_sect113r1 +SN_sect113r1 = _ffi.string(_lib.SN_sect113r1) +NID_sect113r2 = _lib.NID_sect113r2 +SN_sect113r2 = _ffi.string(_lib.SN_sect113r2) +NID_sect131r1 = _lib.NID_sect131r1 +SN_sect131r1 = _ffi.string(_lib.SN_sect131r1) +NID_sect131r2 = _lib.NID_sect131r2 +SN_sect131r2 = _ffi.string(_lib.SN_sect131r2) +NID_sect193r1 = _lib.NID_sect193r1 +SN_sect193r1 = _ffi.string(_lib.SN_sect193r1) +NID_sect193r2 = _lib.NID_sect193r2 +SN_sect193r2 = _ffi.string(_lib.SN_sect193r2) +NID_sect233k1 = _lib.NID_sect233k1 +SN_sect233k1 = _ffi.string(_lib.SN_sect233k1) +NID_sect233r1 = _lib.NID_sect233r1 +SN_sect233r1 = _ffi.string(_lib.SN_sect233r1) +NID_sect239k1 = _lib.NID_sect239k1 +SN_sect239k1 = _ffi.string(_lib.SN_sect239k1) +NID_sect283k1 = _lib.NID_sect283k1 +SN_sect283k1 = _ffi.string(_lib.SN_sect283k1) +NID_sect283r1 = _lib.NID_sect283r1 +SN_sect283r1 = _ffi.string(_lib.SN_sect283r1) +NID_sect409k1 = _lib.NID_sect409k1 +SN_sect409k1 = _ffi.string(_lib.SN_sect409k1) +NID_sect409r1 = _lib.NID_sect409r1 +SN_sect409r1 = _ffi.string(_lib.SN_sect409r1) +NID_sect571k1 = _lib.NID_sect571k1 +SN_sect571k1 = _ffi.string(_lib.SN_sect571k1) +NID_sect571r1 = _lib.NID_sect571r1 +SN_sect571r1 = _ffi.string(_lib.SN_sect571r1) +NID_wap_wsg_idm_ecid_wtls1 = _lib.NID_wap_wsg_idm_ecid_wtls1 +SN_wap_wsg_idm_ecid_wtls1 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls1) +NID_wap_wsg_idm_ecid_wtls3 = _lib.NID_wap_wsg_idm_ecid_wtls3 +SN_wap_wsg_idm_ecid_wtls3 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls3) +NID_wap_wsg_idm_ecid_wtls4 = _lib.NID_wap_wsg_idm_ecid_wtls4 +SN_wap_wsg_idm_ecid_wtls4 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls4) +NID_wap_wsg_idm_ecid_wtls5 = _lib.NID_wap_wsg_idm_ecid_wtls5 +SN_wap_wsg_idm_ecid_wtls5 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls5) +NID_wap_wsg_idm_ecid_wtls6 = _lib.NID_wap_wsg_idm_ecid_wtls6 +SN_wap_wsg_idm_ecid_wtls6 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls6) +NID_wap_wsg_idm_ecid_wtls7 = _lib.NID_wap_wsg_idm_ecid_wtls7 +SN_wap_wsg_idm_ecid_wtls7 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls7) +NID_wap_wsg_idm_ecid_wtls8 = _lib.NID_wap_wsg_idm_ecid_wtls8 +SN_wap_wsg_idm_ecid_wtls8 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls8) +NID_wap_wsg_idm_ecid_wtls9 = _lib.NID_wap_wsg_idm_ecid_wtls9 +SN_wap_wsg_idm_ecid_wtls9 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls9) +NID_wap_wsg_idm_ecid_wtls10 = _lib.NID_wap_wsg_idm_ecid_wtls10 +SN_wap_wsg_idm_ecid_wtls10 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls10) +NID_wap_wsg_idm_ecid_wtls11 = _lib.NID_wap_wsg_idm_ecid_wtls11 +SN_wap_wsg_idm_ecid_wtls11 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls11) +NID_wap_wsg_idm_ecid_wtls12 = _lib.NID_wap_wsg_idm_ecid_wtls12 +SN_wap_wsg_idm_ecid_wtls12 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls12) +NID_ipsec3 = _lib.NID_ipsec3 +SN_ipsec3 = _ffi.string(_lib.SN_ipsec3) +NID_ipsec4 = _lib.NID_ipsec4 +SN_ipsec4 = _ffi.string(_lib.SN_ipsec4) _Cryptography_HAS_EC = _lib.Cryptography_HAS_EC From 9bca0edb8a68b5fdb23287d0412ed8205bc1d91a Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 5 Mar 2014 14:41:41 -0800 Subject: [PATCH 08/11] Add SSL.ELLIPTIC_CURVE_DESCRIPTIONS to expose the actual supported curves Different OpenSSL builds support different curves. Determine the supported curves at startup and expose the list. --- OpenSSL/SSL.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index a3e4cd017..9fe700199 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -266,6 +266,15 @@ class _memoryview(object): SN_ipsec4 = _ffi.string(_lib.SN_ipsec4) _Cryptography_HAS_EC = _lib.Cryptography_HAS_EC +ELLIPTIC_CURVE_DESCRIPTIONS = {} # In case there's no EC support +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 = {c.nid : _ffi.string(c.comment) + for c in _curves} + del _num_curves + del _curves class Error(Exception): From 76a6133518e5671cc6380304fdc06aae66542d7c Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 12 Mar 2014 15:02:56 -0700 Subject: [PATCH 09/11] Fix docstring and Python 2.6 issues in ECDHE support --- OpenSSL/SSL.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 9fe700199..602a98c8f 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -271,8 +271,8 @@ class _memoryview(object): _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 = {c.nid : _ffi.string(c.comment) - for c in _curves} + ELLIPTIC_CURVE_DESCRIPTIONS = dict((c.nid, _ffi.string(c.comment)) + for c in _curves) del _num_curves del _curves @@ -751,10 +751,10 @@ def load_tmp_dh(self, dhfile): def set_tmp_ecdh_by_curve_name(self, curve_name): """ - Configure this connection to people to use Elliptical Curve - Diffie-Hellman key exchanges. + Select a curve to use for ECDHE key exchange. :param curve_name: One of the named curve constants. + :type curve_name: int :return: None """ if _lib.Cryptography_HAS_EC: From f05a273f1bd6a083cb922cc3c5565ad01cbc05e0 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 13 Mar 2014 17:22:25 -0700 Subject: [PATCH 10/11] 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. --- OpenSSL/SSL.py | 20 +++++++++++++++----- OpenSSL/test/test_ssl.py | 27 +++++++++++++++++---------- doc/api/ssl.rst | 34 ++++++++++++++++++---------------- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index 602a98c8f..f6d62d406 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -271,7 +271,8 @@ class _memoryview(object): _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 @@ def load_tmp_dh(self, dhfile): _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 2686d120d..0fc8f2979 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -35,7 +35,8 @@ 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 @@ def test_load_tmp_dh(self): # 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 76fb0ad06..f169cbc09 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) From 4064ea18c2a68bb5d6e82f40be7ecddc0752d6f9 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 13 Mar 2014 17:40:54 -0700 Subject: [PATCH 11/11] Stop exposing all the NID and SN objects for elliptic curves, now that we access them by name. --- OpenSSL/SSL.py | 144 ------------------------------------------------- 1 file changed, 144 deletions(-) diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py index f6d62d406..2229ccfd1 100644 --- a/OpenSSL/SSL.py +++ b/OpenSSL/SSL.py @@ -121,150 +121,6 @@ class _memoryview(object): SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE - -NID_X9_62_c2pnb163v1 = _lib.NID_X9_62_c2pnb163v1 -SN_X9_62_c2pnb163v1 = _ffi.string(_lib.SN_X9_62_c2pnb163v1) -NID_X9_62_c2pnb163v2 = _lib.NID_X9_62_c2pnb163v2 -SN_X9_62_c2pnb163v2 = _ffi.string(_lib.SN_X9_62_c2pnb163v2) -NID_X9_62_c2pnb163v3 = _lib.NID_X9_62_c2pnb163v3 -SN_X9_62_c2pnb163v3 = _ffi.string(_lib.SN_X9_62_c2pnb163v3) -NID_X9_62_c2pnb176v1 = _lib.NID_X9_62_c2pnb176v1 -SN_X9_62_c2pnb176v1 = _ffi.string(_lib.SN_X9_62_c2pnb176v1) -NID_X9_62_c2tnb191v1 = _lib.NID_X9_62_c2tnb191v1 -SN_X9_62_c2tnb191v1 = _ffi.string(_lib.SN_X9_62_c2tnb191v1) -NID_X9_62_c2tnb191v2 = _lib.NID_X9_62_c2tnb191v2 -SN_X9_62_c2tnb191v2 = _ffi.string(_lib.SN_X9_62_c2tnb191v2) -NID_X9_62_c2tnb191v3 = _lib.NID_X9_62_c2tnb191v3 -SN_X9_62_c2tnb191v3 = _ffi.string(_lib.SN_X9_62_c2tnb191v3) -NID_X9_62_c2onb191v4 = _lib.NID_X9_62_c2onb191v4 -SN_X9_62_c2onb191v4 = _ffi.string(_lib.SN_X9_62_c2onb191v4) -NID_X9_62_c2onb191v5 = _lib.NID_X9_62_c2onb191v5 -SN_X9_62_c2onb191v5 = _ffi.string(_lib.SN_X9_62_c2onb191v5) -NID_X9_62_c2pnb208w1 = _lib.NID_X9_62_c2pnb208w1 -SN_X9_62_c2pnb208w1 = _ffi.string(_lib.SN_X9_62_c2pnb208w1) -NID_X9_62_c2tnb239v1 = _lib.NID_X9_62_c2tnb239v1 -SN_X9_62_c2tnb239v1 = _ffi.string(_lib.SN_X9_62_c2tnb239v1) -NID_X9_62_c2tnb239v2 = _lib.NID_X9_62_c2tnb239v2 -SN_X9_62_c2tnb239v2 = _ffi.string(_lib.SN_X9_62_c2tnb239v2) -NID_X9_62_c2tnb239v3 = _lib.NID_X9_62_c2tnb239v3 -SN_X9_62_c2tnb239v3 = _ffi.string(_lib.SN_X9_62_c2tnb239v3) -NID_X9_62_c2onb239v4 = _lib.NID_X9_62_c2onb239v4 -SN_X9_62_c2onb239v4 = _ffi.string(_lib.SN_X9_62_c2onb239v4) -NID_X9_62_c2onb239v5 = _lib.NID_X9_62_c2onb239v5 -SN_X9_62_c2onb239v5 = _ffi.string(_lib.SN_X9_62_c2onb239v5) -NID_X9_62_c2pnb272w1 = _lib.NID_X9_62_c2pnb272w1 -SN_X9_62_c2pnb272w1 = _ffi.string(_lib.SN_X9_62_c2pnb272w1) -NID_X9_62_c2pnb304w1 = _lib.NID_X9_62_c2pnb304w1 -SN_X9_62_c2pnb304w1 = _ffi.string(_lib.SN_X9_62_c2pnb304w1) -NID_X9_62_c2tnb359v1 = _lib.NID_X9_62_c2tnb359v1 -SN_X9_62_c2tnb359v1 = _ffi.string(_lib.SN_X9_62_c2tnb359v1) -NID_X9_62_c2pnb368w1 = _lib.NID_X9_62_c2pnb368w1 -SN_X9_62_c2pnb368w1 = _ffi.string(_lib.SN_X9_62_c2pnb368w1) -NID_X9_62_c2tnb431r1 = _lib.NID_X9_62_c2tnb431r1 -SN_X9_62_c2tnb431r1 = _ffi.string(_lib.SN_X9_62_c2tnb431r1) -NID_X9_62_prime192v1 = _lib.NID_X9_62_prime192v1 -SN_X9_62_prime192v1 = _ffi.string(_lib.SN_X9_62_prime192v1) -NID_X9_62_prime192v2 = _lib.NID_X9_62_prime192v2 -SN_X9_62_prime192v2 = _ffi.string(_lib.SN_X9_62_prime192v2) -NID_X9_62_prime192v3 = _lib.NID_X9_62_prime192v3 -SN_X9_62_prime192v3 = _ffi.string(_lib.SN_X9_62_prime192v3) -NID_X9_62_prime239v1 = _lib.NID_X9_62_prime239v1 -SN_X9_62_prime239v1 = _ffi.string(_lib.SN_X9_62_prime239v1) -NID_X9_62_prime239v2 = _lib.NID_X9_62_prime239v2 -SN_X9_62_prime239v2 = _ffi.string(_lib.SN_X9_62_prime239v2) -NID_X9_62_prime239v3 = _lib.NID_X9_62_prime239v3 -SN_X9_62_prime239v3 = _ffi.string(_lib.SN_X9_62_prime239v3) -NID_X9_62_prime256v1 = _lib.NID_X9_62_prime256v1 -SN_X9_62_prime256v1 = _ffi.string(_lib.SN_X9_62_prime256v1) -NID_secp112r1 = _lib.NID_secp112r1 -SN_secp112r1 = _ffi.string(_lib.SN_secp112r1) -NID_secp112r2 = _lib.NID_secp112r2 -SN_secp112r2 = _ffi.string(_lib.SN_secp112r2) -NID_secp128r1 = _lib.NID_secp128r1 -SN_secp128r1 = _ffi.string(_lib.SN_secp128r1) -NID_secp128r2 = _lib.NID_secp128r2 -SN_secp128r2 = _ffi.string(_lib.SN_secp128r2) -NID_secp160k1 = _lib.NID_secp160k1 -SN_secp160k1 = _ffi.string(_lib.SN_secp160k1) -NID_secp160r1 = _lib.NID_secp160r1 -SN_secp160r1 = _ffi.string(_lib.SN_secp160r1) -NID_secp160r2 = _lib.NID_secp160r2 -SN_secp160r2 = _ffi.string(_lib.SN_secp160r2) -NID_sect163k1 = _lib.NID_sect163k1 -SN_sect163k1 = _ffi.string(_lib.SN_sect163k1) -NID_sect163r1 = _lib.NID_sect163r1 -SN_sect163r1 = _ffi.string(_lib.SN_sect163r1) -NID_sect163r2 = _lib.NID_sect163r2 -SN_sect163r2 = _ffi.string(_lib.SN_sect163r2) -NID_secp192k1 = _lib.NID_secp192k1 -SN_secp192k1 = _ffi.string(_lib.SN_secp192k1) -NID_secp224k1 = _lib.NID_secp224k1 -SN_secp224k1 = _ffi.string(_lib.SN_secp224k1) -NID_secp224r1 = _lib.NID_secp224r1 -SN_secp224r1 = _ffi.string(_lib.SN_secp224r1) -NID_secp256k1 = _lib.NID_secp256k1 -SN_secp256k1 = _ffi.string(_lib.SN_secp256k1) -NID_secp384r1 = _lib.NID_secp384r1 -SN_secp384r1 = _ffi.string(_lib.SN_secp384r1) -NID_secp521r1 = _lib.NID_secp521r1 -SN_secp521r1 = _ffi.string(_lib.SN_secp521r1) -NID_sect113r1 = _lib.NID_sect113r1 -SN_sect113r1 = _ffi.string(_lib.SN_sect113r1) -NID_sect113r2 = _lib.NID_sect113r2 -SN_sect113r2 = _ffi.string(_lib.SN_sect113r2) -NID_sect131r1 = _lib.NID_sect131r1 -SN_sect131r1 = _ffi.string(_lib.SN_sect131r1) -NID_sect131r2 = _lib.NID_sect131r2 -SN_sect131r2 = _ffi.string(_lib.SN_sect131r2) -NID_sect193r1 = _lib.NID_sect193r1 -SN_sect193r1 = _ffi.string(_lib.SN_sect193r1) -NID_sect193r2 = _lib.NID_sect193r2 -SN_sect193r2 = _ffi.string(_lib.SN_sect193r2) -NID_sect233k1 = _lib.NID_sect233k1 -SN_sect233k1 = _ffi.string(_lib.SN_sect233k1) -NID_sect233r1 = _lib.NID_sect233r1 -SN_sect233r1 = _ffi.string(_lib.SN_sect233r1) -NID_sect239k1 = _lib.NID_sect239k1 -SN_sect239k1 = _ffi.string(_lib.SN_sect239k1) -NID_sect283k1 = _lib.NID_sect283k1 -SN_sect283k1 = _ffi.string(_lib.SN_sect283k1) -NID_sect283r1 = _lib.NID_sect283r1 -SN_sect283r1 = _ffi.string(_lib.SN_sect283r1) -NID_sect409k1 = _lib.NID_sect409k1 -SN_sect409k1 = _ffi.string(_lib.SN_sect409k1) -NID_sect409r1 = _lib.NID_sect409r1 -SN_sect409r1 = _ffi.string(_lib.SN_sect409r1) -NID_sect571k1 = _lib.NID_sect571k1 -SN_sect571k1 = _ffi.string(_lib.SN_sect571k1) -NID_sect571r1 = _lib.NID_sect571r1 -SN_sect571r1 = _ffi.string(_lib.SN_sect571r1) -NID_wap_wsg_idm_ecid_wtls1 = _lib.NID_wap_wsg_idm_ecid_wtls1 -SN_wap_wsg_idm_ecid_wtls1 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls1) -NID_wap_wsg_idm_ecid_wtls3 = _lib.NID_wap_wsg_idm_ecid_wtls3 -SN_wap_wsg_idm_ecid_wtls3 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls3) -NID_wap_wsg_idm_ecid_wtls4 = _lib.NID_wap_wsg_idm_ecid_wtls4 -SN_wap_wsg_idm_ecid_wtls4 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls4) -NID_wap_wsg_idm_ecid_wtls5 = _lib.NID_wap_wsg_idm_ecid_wtls5 -SN_wap_wsg_idm_ecid_wtls5 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls5) -NID_wap_wsg_idm_ecid_wtls6 = _lib.NID_wap_wsg_idm_ecid_wtls6 -SN_wap_wsg_idm_ecid_wtls6 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls6) -NID_wap_wsg_idm_ecid_wtls7 = _lib.NID_wap_wsg_idm_ecid_wtls7 -SN_wap_wsg_idm_ecid_wtls7 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls7) -NID_wap_wsg_idm_ecid_wtls8 = _lib.NID_wap_wsg_idm_ecid_wtls8 -SN_wap_wsg_idm_ecid_wtls8 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls8) -NID_wap_wsg_idm_ecid_wtls9 = _lib.NID_wap_wsg_idm_ecid_wtls9 -SN_wap_wsg_idm_ecid_wtls9 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls9) -NID_wap_wsg_idm_ecid_wtls10 = _lib.NID_wap_wsg_idm_ecid_wtls10 -SN_wap_wsg_idm_ecid_wtls10 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls10) -NID_wap_wsg_idm_ecid_wtls11 = _lib.NID_wap_wsg_idm_ecid_wtls11 -SN_wap_wsg_idm_ecid_wtls11 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls11) -NID_wap_wsg_idm_ecid_wtls12 = _lib.NID_wap_wsg_idm_ecid_wtls12 -SN_wap_wsg_idm_ecid_wtls12 = _ffi.string(_lib.SN_wap_wsg_idm_ecid_wtls12) -NID_ipsec3 = _lib.NID_ipsec3 -SN_ipsec3 = _ffi.string(_lib.SN_ipsec3) -NID_ipsec4 = _lib.NID_ipsec4 -SN_ipsec4 = _ffi.string(_lib.SN_ipsec4) - _Cryptography_HAS_EC = _lib.Cryptography_HAS_EC ELLIPTIC_CURVE_DESCRIPTIONS = {} # In case there's no EC support if _Cryptography_HAS_EC: