diff options
| author | Simo Sorce <simo@redhat.com> | 2015-04-30 14:06:47 -0400 | 
|---|---|---|
| committer | Simo Sorce <simo@redhat.com> | 2015-10-17 11:58:07 -0400 | 
| commit | 9aaeee0dc62189204f38097c815a0913fabe006c (patch) | |
| tree | 37621d2d6a20898d9665520a30ecb7a68c0db30e /tests/hazmat | |
| parent | 7a0ed4a7e9443a0506ae5373a8e5cd1ce3539e97 (diff) | |
| download | cryptography-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 'tests/hazmat')
| -rw-r--r-- | tests/hazmat/backends/test_multibackend.py | 12 | ||||
| -rw-r--r-- | tests/hazmat/backends/test_openssl.py | 14 | ||||
| -rw-r--r-- | tests/hazmat/primitives/test_ec.py | 94 | 
3 files changed, 117 insertions, 3 deletions
| diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index 4d17cdb0..57aa7f44 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -138,8 +138,9 @@ class DummyCMACBackend(object):  @utils.register_interface(EllipticCurveBackend)  class DummyEllipticCurveBackend(object): -    def __init__(self, supported_curves): +    def __init__(self, supported_curves, exchange_supported):          self._curves = supported_curves +        self.exchange_supported = exchange_supported      def elliptic_curve_supported(self, curve):          return any( @@ -170,6 +171,9 @@ class DummyEllipticCurveBackend(object):          if not self.elliptic_curve_supported(numbers.curve):              raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE) +    def elliptic_curve_exchange_algorithm_supported(self): +        return self.exchange_supported +  @utils.register_interface(PEMSerializationBackend)  class DummyPEMSerializationBackend(object): @@ -400,7 +404,7 @@ class TestMultiBackend(object):          backend = MultiBackend([              DummyEllipticCurveBackend([                  ec.SECT283K1 -            ]) +            ], True)          ])          assert backend.elliptic_curve_supported(ec.SECT283K1()) is True @@ -462,6 +466,10 @@ class TestMultiBackend(object):                  )              ) +        assert backend.elliptic_curve_exchange_algorithm_supported() is True +        backend2 = MultiBackend([DummyEllipticCurveBackend([], False)]) +        assert backend2.elliptic_curve_exchange_algorithm_supported() is False +      def test_pem_serialization_backend(self):          backend = MultiBackend([DummyPEMSerializationBackend()]) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 8fd0d711..13162046 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -534,6 +534,11 @@ class DummyLibrary(object):      Cryptography_HAS_EC = 0 +class DummyLibraryECDH(object): +    Cryptography_HAS_EC = 1 +    Cryptography_HAS_ECDH = 0 + +  class TestOpenSSLEllipticCurve(object):      def test_elliptic_curve_supported(self, monkeypatch):          monkeypatch.setattr(backend, "_lib", DummyLibrary()) @@ -551,6 +556,15 @@ class TestOpenSSLEllipticCurve(object):          with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE):              _sn_to_elliptic_curve(backend, b"fake") +    def test_elliptic_curve_exchange_algorithm_supported(self, monkeypatch): +        monkeypatch.setattr(backend, "_lib", DummyLibrary()) + +        assert backend.elliptic_curve_exchange_algorithm_supported() is False + +        monkeypatch.setattr(backend, "_lib", DummyLibraryECDH()) + +        assert backend.elliptic_curve_exchange_algorithm_supported() is False +  @pytest.mark.requires_backend_interface(interface=RSABackend)  class TestRSAPEMSerialization(object): diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 5467464a..c3a99e5d 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -7,6 +7,8 @@ from __future__ import absolute_import, division, print_function  import itertools  import os +from binascii import hexlify +  import pytest  from cryptography import exceptions, utils @@ -21,7 +23,8 @@ from cryptography.hazmat.primitives.asymmetric.utils import (  from ...utils import (      load_fips_ecdsa_key_pair_vectors, load_fips_ecdsa_signing_vectors, -    load_vectors_from_file, raises_unsupported_algorithm +    load_kasvs_ecdh_vectors, load_vectors_from_file, +    raises_unsupported_algorithm  )  _HASH_TYPES = { @@ -54,6 +57,15 @@ def _skip_curve_unsupported(backend, curve):          ) +def _skip_exchange_algorithm_unsupported(backend): +    if not backend.elliptic_curve_exchange_algorithm_supported(): +        pytest.skip( +            "Exchange algorithm is not supported by this backend {0}".format( +                backend +            ) +        ) + +  @utils.register_interface(ec.EllipticCurve)  class DummyCurve(object):      name = "dummy-curve" @@ -749,3 +761,83 @@ class TestECDSAVerification(object):          public_key = key.public_key()          with pytest.raises(TypeError):              public_key.verifier(1234, ec.ECDSA(hashes.SHA256())) + + +class DummyECDHBackend(object): +    @classmethod +    def elliptic_curve_exchange_algorithm_supported(cls): +        return False + + +@pytest.mark.requires_backend_interface(interface=EllipticCurveBackend) +class TestECDHVectors(object): + +    def test_unsupported_ecdh_arguments(self, backend): +        with pytest.raises(TypeError): +            ec.ECDH(None) +        curve = ec.SECP521R1 +        _skip_curve_unsupported(backend, curve) +        prikey = ec.generate_private_key(curve, backend) +        ecdh = ec.ECDH(prikey) +        ecdh.compute_key(ecdh.public_key()) +        with pytest.raises(TypeError): +            ecdh.compute_key(None) +        with pytest.raises(exceptions.UnsupportedAlgorithm): +            prikey._backend = DummyECDHBackend() +            ecdh = ec.ECDH(prikey) +        _skip_exchange_algorithm_unsupported(DummyECDHBackend()) + +    def key_exchange(self, backend, vector): +        key_numbers = vector['IUT'] +        peer_numbers = vector['CAVS'] + +        prikey = ec.EllipticCurvePrivateNumbers( +            key_numbers['d'], +            ec.EllipticCurvePublicNumbers( +                key_numbers['x'], +                key_numbers['y'], +                ec._CURVE_TYPES[vector['curve']]() +            ) +        ).private_key(backend) + +        peerkey = ec.EllipticCurvePrivateNumbers( +            peer_numbers['d'], +            ec.EllipticCurvePublicNumbers( +                peer_numbers['x'], +                peer_numbers['y'], +                ec._CURVE_TYPES[vector['curve']]() +            ) +        ).private_key(backend) +        peerpubkey = peerkey.public_key() + +        ecdh = ec.ECDH(prikey) +        z = ecdh.compute_key(peerpubkey) + +        return int(hexlify(z).decode('ascii'), 16) + +    @pytest.mark.parametrize( +        "vector", +        load_vectors_from_file( +            os.path.join( +                "asymmetric", "ECDH", +                "KASValidityTest_ECCStaticUnified_NOKC_ZZOnly_init.fax"), +            load_kasvs_ecdh_vectors +        ) +    ) +    def test_key_exchange_with_vectors(self, backend, vector): +        _skip_curve_unsupported(backend, ec._CURVE_TYPES[vector['curve']]) +        _skip_exchange_algorithm_unsupported(backend) + +        try: +            z = self.key_exchange(backend, vector) +        except ValueError: +            assert vector['fail'] is True + +        if vector['fail']: +            # Errno 7 denotes a changed private key. Errno 8 denotes a changed +            # shared key. Both these errors will not cause a failure in the +            # exchange but should lead to a non-matching derived shared key. +            if vector['errno'] in [7, 8]: +                assert z != vector['Z'] +        else: +            assert z == vector['Z'] | 
