diff options
Diffstat (limited to 'src/cryptography')
-rw-r--r-- | src/cryptography/exceptions.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/interfaces.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/multibackend.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 7 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/ec.py | 25 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/ec.py | 11 |
6 files changed, 56 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 d93968cf..92d9653a 100644 --- a/src/cryptography/hazmat/backends/interfaces.py +++ b/src/cryptography/hazmat/backends/interfaces.py @@ -215,6 +215,12 @@ class EllipticCurveBackend(object): Return an EllipticCurvePrivateKey provider using the given numbers. """ + @abc.abstractmethod + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + """ + 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..c4d2c133 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, algorithm, curve): + return any( + b.elliptic_curve_exchange_algorithm_supported(algorithm, curve) + 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..f86c3aa1 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1671,6 +1671,13 @@ class Backend(object): return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey) + def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): + return ( + self.elliptic_curve_supported(curve) and + self._lib.Cryptography_HAS_ECDH == 1 and + isinstance(algorithm, ec.ECDH) + ) + 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/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index 939a3f90..cfd559ae 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -171,6 +171,31 @@ class _EllipticCurvePrivateKey(object): "Unsupported elliptic curve signature algorithm.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) + def exchange(self, algorithm, peer_public_key): + if not ( + self._backend.elliptic_curve_exchange_algorithm_supported( + algorithm, self.curve + ) + ): + raise UnsupportedAlgorithm( + "This backend does not support the ECDH algorithm.", + _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM + ) + + group = self._backend._lib.EC_KEY_get0_group(self._ec_key) + z_len = (self._backend._lib.EC_GROUP_get_degree(group) + 7) // 8 + self._backend.openssl_assert(z_len > 0) + z_buf = self._backend._ffi.new("uint8_t[]", z_len) + peer_key = self._backend._lib.EC_KEY_get0_public_key( + peer_public_key._ec_key + ) + + r = self._backend._lib.ECDH_compute_key( + z_buf, z_len, peer_key, self._ec_key, self._backend._ffi.NULL + ) + self._backend.openssl_assert(r > 0) + return self._backend._ffi.buffer(z_buf)[:z_len] + def public_key(self): group = self._backend._lib.EC_KEY_get0_group(self._ec_key) self._backend.openssl_assert(group != self._backend._ffi.NULL) diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index f1d39eed..c6f83667 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -44,6 +44,13 @@ class EllipticCurvePrivateKey(object): """ @abc.abstractmethod + def exchange(self, algorithm, peer_public_key): + """ + Performs a key exchange operation using the provided algorithm with the + provided peer's public key. + """ + + @abc.abstractmethod def public_key(self): """ The EllipticCurvePublicKey for this private key. @@ -302,3 +309,7 @@ class EllipticCurvePrivateNumbers(object): def __ne__(self, other): return not self == other + + +class ECDH(object): + pass |