aboutsummaryrefslogtreecommitdiffstats
path: root/src/cryptography
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-04-30 14:06:47 -0400
committerSimo Sorce <simo@redhat.com>2015-10-17 11:58:07 -0400
commit9aaeee0dc62189204f38097c815a0913fabe006c (patch)
tree37621d2d6a20898d9665520a30ecb7a68c0db30e /src/cryptography
parent7a0ed4a7e9443a0506ae5373a8e5cd1ce3539e97 (diff)
downloadcryptography-9aaeee0dc62189204f38097c815a0913fabe006c.tar.gz
cryptography-9aaeee0dc62189204f38097c815a0913fabe006c.tar.bz2
cryptography-9aaeee0dc62189204f38097c815a0913fabe006c.zip
Add an Elliptic Curve Key Exchange Algorithm(ECDH)
The ECDH Key Exchange algorithm as standardized in NIST publication 800-56A Revision 2 Includes tests with vectors from NIST. Signed-off-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'src/cryptography')
-rw-r--r--src/cryptography/exceptions.py1
-rw-r--r--src/cryptography/hazmat/backends/interfaces.py6
-rw-r--r--src/cryptography/hazmat/backends/multibackend.py6
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py20
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py25
5 files changed, 58 insertions, 0 deletions
diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py
index 29be22be..3bf8a75b 100644
--- a/src/cryptography/exceptions.py
+++ b/src/cryptography/exceptions.py
@@ -20,6 +20,7 @@ class _Reasons(Enum):
UNSUPPORTED_ELLIPTIC_CURVE = 6
UNSUPPORTED_SERIALIZATION = 7
UNSUPPORTED_X509 = 8
+ UNSUPPORTED_EXCHANGE_ALGORITHM = 9
class UnsupportedAlgorithm(Exception):
diff --git a/src/cryptography/hazmat/backends/interfaces.py b/src/cryptography/hazmat/backends/interfaces.py
index a43621a7..faa0b313 100644
--- a/src/cryptography/hazmat/backends/interfaces.py
+++ b/src/cryptography/hazmat/backends/interfaces.py
@@ -215,6 +215,12 @@ class EllipticCurveBackend(object):
Return an EllipticCurvePublicKey provider using the given numbers.
"""
+ @abc.abstractmethod
+ def elliptic_curve_exchange_algorithm_supported(self):
+ """
+ Returns whether the exchange algorithm is supported by this backend.
+ """
+
@six.add_metaclass(abc.ABCMeta)
class PEMSerializationBackend(object):
diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py
index 9db32aa5..77a45ccd 100644
--- a/src/cryptography/hazmat/backends/multibackend.py
+++ b/src/cryptography/hazmat/backends/multibackend.py
@@ -271,6 +271,12 @@ class MultiBackend(object):
_Reasons.UNSUPPORTED_ELLIPTIC_CURVE
)
+ def elliptic_curve_exchange_algorithm_supported(self):
+ return any(
+ b.elliptic_curve_exchange_algorithm_supported()
+ for b in self._filtered_backends(EllipticCurveBackend)
+ )
+
def load_pem_private_key(self, data, password):
for b in self._filtered_backends(PEMSerializationBackend):
return b.load_pem_private_key(data, password)
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 0d3b3dd4..d82f3834 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -1671,6 +1671,26 @@ class Backend(object):
return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey)
+ def elliptic_curve_exchange_algorithm_supported(self):
+ return (self._lib.Cryptography_HAS_EC == 1 and
+ self._lib.Cryptography_HAS_ECDH == 1)
+
+ def ecdh_compute_key(self, private_key, peer_public_key):
+ pri_key = private_key._ec_key
+ pub_key = peer_public_key._ec_key
+
+ group = self._lib.EC_KEY_get0_group(pri_key)
+ z_len = (self._lib.EC_GROUP_get_degree(group) + 7) // 8
+ self.openssl_assert(z_len > 0)
+ z_buf = self._ffi.new("uint8_t[]", z_len)
+ peer_key = self._lib.EC_KEY_get0_public_key(pub_key)
+
+ r = self._lib.ECDH_compute_key(z_buf, z_len,
+ peer_key, pri_key,
+ self._ffi.NULL)
+ self.openssl_assert(r > 0)
+ return self._ffi.buffer(z_buf)[:z_len]
+
def _ec_cdata_to_evp_pkey(self, ec_cdata):
evp_pkey = self._lib.EVP_PKEY_new()
self.openssl_assert(evp_pkey != self._ffi.NULL)
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index f1d39eed..978a7c41 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -8,6 +8,7 @@ import abc
import six
+from cryptography import exceptions
from cryptography import utils
@@ -302,3 +303,27 @@ class EllipticCurvePrivateNumbers(object):
def __ne__(self, other):
return not self == other
+
+
+class ECDH(object):
+ def __init__(self, private_key):
+ if not isinstance(private_key, EllipticCurvePrivateKey):
+ raise TypeError("Private Key must be a EllipticCurvePrivateKey")
+ self._private_key = private_key
+ self._backend = private_key._backend
+ if not self._backend.elliptic_curve_exchange_algorithm_supported():
+ raise exceptions.UnsupportedAlgorithm(
+ "This backend does not support the ECDH algorithm.",
+ exceptions._Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM
+ )
+
+ private_key = utils.read_only_property("_private_key")
+
+ def public_key(self):
+ return self._private_key.public_key()
+
+ def compute_key(self, peer_public_key):
+ if not isinstance(peer_public_key, EllipticCurvePublicKey):
+ raise TypeError("Peer Public Key must be a EllipticCurvePublicKey")
+ return self._backend.ecdh_compute_key(self._private_key,
+ peer_public_key)