diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/conftest.py | 8 | ||||
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 12 | ||||
-rw-r--r-- | tests/hazmat/bindings/test_openssl.py | 34 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_aes.py | 50 | ||||
-rw-r--r-- | tests/test_interfaces.py | 4 | ||||
-rw-r--r-- | tests/test_utils.py | 4 | ||||
-rw-r--r-- | tests/test_x509_ext.py | 82 | ||||
-rw-r--r-- | tests/utils.py | 9 |
8 files changed, 186 insertions, 17 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index c4d6b9c1..6599a643 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,11 +18,13 @@ def pytest_generate_tests(metafunc): if "backend" in metafunc.fixturenames: filtered_backends = [] required = metafunc.function.requires_backend_interface - required_interfaces = tuple( + required_interfaces = [ mark.kwargs["interface"] for mark in required - ) + ] for backend in selected_backends: - if isinstance(backend, required_interfaces): + if all( + isinstance(backend, iface) for iface in required_interfaces + ): filtered_backends.append(backend) # If you pass an empty list to parametrize Bad Things(tm) happen diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 34fff277..6a2e8a77 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -224,7 +224,7 @@ class TestOpenSSLRandomEngine(object): backend.activate_osrandom_engine() current_default = backend._lib.ENGINE_get_default_RAND() name = backend._lib.ENGINE_get_name(current_default) - assert name == backend._lib.Cryptography_osrandom_engine_name + assert name == backend._binding._osrandom_engine_name def test_osrandom_engine_is_default(self, tmpdir): engine_printer = textwrap.dedent( @@ -258,7 +258,7 @@ class TestOpenSSLRandomEngine(object): ) osrandom_engine_name = backend._ffi.string( - backend._lib.Cryptography_osrandom_engine_name + backend._binding._osrandom_engine_name ) assert engine_name.read().encode('ascii') == osrandom_engine_name @@ -277,7 +277,7 @@ class TestOpenSSLRandomEngine(object): backend.activate_osrandom_engine() e = backend._lib.ENGINE_get_default_RAND() name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name + assert name == backend._binding._osrandom_engine_name res = backend._lib.ENGINE_free(e) assert res == 1 @@ -285,7 +285,7 @@ class TestOpenSSLRandomEngine(object): e = backend._lib.ENGINE_get_default_RAND() assert e != backend._ffi.NULL name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name + assert name == backend._binding._osrandom_engine_name res = backend._lib.ENGINE_free(e) assert res == 1 backend.activate_builtin_random() @@ -303,13 +303,13 @@ class TestOpenSSLRandomEngine(object): def test_activate_osrandom_already_default(self): e = backend._lib.ENGINE_get_default_RAND() name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name + assert name == backend._binding._osrandom_engine_name res = backend._lib.ENGINE_free(e) assert res == 1 backend.activate_osrandom_engine() e = backend._lib.ENGINE_get_default_RAND() name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name + assert name == backend._binding._osrandom_engine_name res = backend._lib.ENGINE_free(e) assert res == 1 diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index e6d6fc45..f3f2eaf4 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -4,11 +4,27 @@ from __future__ import absolute_import, division, print_function +import os + import pytest from cryptography.hazmat.bindings.openssl.binding import Binding +def skip_if_libre_ssl(openssl_version): + if b'LibreSSL' in openssl_version: + pytest.skip("LibreSSL hard-codes RAND_bytes to use arc4random.") + + +class TestLibreSkip(object): + def test_skip_no(self): + assert skip_if_libre_ssl(b"OpenSSL 0.9.8zf 19 Mar 2015") is None + + def test_skip_yes(self): + with pytest.raises(pytest.skip.Exception): + skip_if_libre_ssl(b"LibreSSL 2.1.6") + + class TestOpenSSL(object): def test_binding_loads(self): binding = Binding() @@ -89,8 +105,22 @@ class TestOpenSSL(object): def test_add_engine_more_than_once(self): b = Binding() - res = b.lib.Cryptography_add_osrandom_engine() - assert res == 2 + with pytest.raises(RuntimeError): + b._register_osrandom_engine() + + def test_actual_osrandom_bytes(self, monkeypatch): + b = Binding() + skip_if_libre_ssl(b.ffi.string(b.lib.OPENSSL_VERSION_TEXT)) + sample_data = (b"\x01\x02\x03\x04" * 4) + length = len(sample_data) + + def notrandom(size): + assert size == length + return sample_data + monkeypatch.setattr(os, "urandom", notrandom) + buf = b.ffi.new("char[]", length) + b.lib.RAND_bytes(buf, length) + assert b.ffi.buffer(buf)[0:length] == sample_data def test_ssl_ctx_options(self): # Test that we're properly handling 32-bit unsigned on all platforms. diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 4d48e8ad..2c3e5f90 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -253,3 +253,53 @@ class TestAESModeGCM(object): computed_ct = encryptor.update(pt) + encryptor.finalize() assert computed_ct == ct assert encryptor.tag == tag + + def test_gcm_ciphertext_limit(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16 + encryptor.update(b"0" * 16) + assert ( + encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES + ) + with pytest.raises(ValueError): + encryptor.update(b"0") + + def test_gcm_aad_limit(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16 + encryptor.authenticate_additional_data(b"0" * 16) + assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES + with pytest.raises(ValueError): + encryptor.authenticate_additional_data(b"0") + + def test_gcm_ciphertext_increments(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor.update(b"0" * 8) + assert encryptor._bytes_processed == 8 + encryptor.update(b"0" * 7) + assert encryptor._bytes_processed == 15 + encryptor.update(b"0" * 18) + assert encryptor._bytes_processed == 33 + + def test_gcm_aad_increments(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend + ).encryptor() + encryptor.authenticate_additional_data(b"0" * 8) + assert encryptor._aad_bytes_processed == 8 + encryptor.authenticate_additional_data(b"0" * 18) + assert encryptor._aad_bytes_processed == 26 diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 4d571ea6..bdb4a94d 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -36,6 +36,8 @@ class TestVerifyInterface(object): def method(self): """Method with no arguments""" + # Invoke this to ensure the line is covered + NonImplementer().method() with pytest.raises(InterfaceNotImplemented): verify_interface(SimpleInterface, NonImplementer) @@ -51,4 +53,6 @@ class TestVerifyInterface(object): def property(self): """A concrete property""" + # Invoke this to ensure the line is covered + NonImplementer().property verify_interface(SimpleInterface, NonImplementer) diff --git a/tests/test_utils.py b/tests/test_utils.py index 8601d11d..f71264ea 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -85,7 +85,7 @@ def test_check_backend_support_skip(): supported = pretend.stub( kwargs={"only_if": lambda backend: False, "skip_message": "Nope"} ) - item = pretend.stub(keywords={"supported": supported}, + item = pretend.stub(keywords={"supported": [supported]}, funcargs={"backend": True}) with pytest.raises(pytest.skip.Exception) as exc_info: check_backend_support(item) @@ -96,7 +96,7 @@ def test_check_backend_support_no_skip(): supported = pretend.stub( kwargs={"only_if": lambda backend: True, "skip_message": "Nope"} ) - item = pretend.stub(keywords={"supported": supported}, + item = pretend.stub(keywords={"supported": [supported]}, funcargs={"backend": True}) assert check_backend_support(item) is None diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 6d91ba41..0ef84e79 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -2033,6 +2033,88 @@ class TestNameConstraints(object): assert nc != object() +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) +class TestNameConstraintsExtension(object): + def test_permitted_excluded(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "nc_permitted_excluded_2.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + nc = cert.extensions.get_extension_for_oid( + x509.OID_NAME_CONSTRAINTS + ).value + assert nc == x509.NameConstraints( + permitted_subtrees=[ + x509.DNSName(u"zombo.local"), + ], + excluded_subtrees=[ + x509.DirectoryName(x509.Name([ + x509.NameAttribute(x509.OID_COMMON_NAME, u"zombo") + ])) + ] + ) + + def test_permitted(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "nc_permitted_2.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + nc = cert.extensions.get_extension_for_oid( + x509.OID_NAME_CONSTRAINTS + ).value + assert nc == x509.NameConstraints( + permitted_subtrees=[ + x509.DNSName(u"zombo.local"), + ], + excluded_subtrees=None + ) + + def test_permitted_with_leading_period(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "nc_permitted.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + nc = cert.extensions.get_extension_for_oid( + x509.OID_NAME_CONSTRAINTS + ).value + assert nc == x509.NameConstraints( + permitted_subtrees=[ + x509.DNSName(u".cryptography.io"), + x509.UniformResourceIdentifier(u"ftp://cryptography.test") + ], + excluded_subtrees=None + ) + + def test_excluded_with_leading_period(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "nc_excluded.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + nc = cert.extensions.get_extension_for_oid( + x509.OID_NAME_CONSTRAINTS + ).value + assert nc == x509.NameConstraints( + permitted_subtrees=None, + excluded_subtrees=[ + x509.DNSName(u".cryptography.io"), + x509.UniformResourceIdentifier(u"gopher://cryptography.test") + ] + ) + + class TestDistributionPoint(object): def test_distribution_point_full_name_not_general_names(self): with pytest.raises(TypeError): diff --git a/tests/utils.py b/tests/utils.py index 8be5c1fa..5083d48c 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -53,10 +53,11 @@ def skip_if_empty(backend_list, required_interfaces): def check_backend_support(item): supported = item.keywords.get("supported") if supported and "backend" in item.funcargs: - if not supported.kwargs["only_if"](item.funcargs["backend"]): - pytest.skip("{0} ({1})".format( - supported.kwargs["skip_message"], item.funcargs["backend"] - )) + for mark in supported: + if not mark.kwargs["only_if"](item.funcargs["backend"]): + pytest.skip("{0} ({1})".format( + mark.kwargs["skip_message"], item.funcargs["backend"] + )) elif supported: raise ValueError("This mark is only available on methods that take a " "backend") |