aboutsummaryrefslogtreecommitdiffstats
path: root/tests
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 /tests
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 'tests')
-rw-r--r--tests/hazmat/backends/test_multibackend.py12
-rw-r--r--tests/hazmat/backends/test_openssl.py14
-rw-r--r--tests/hazmat/primitives/test_ec.py94
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']