From 8bfbacef9cb973115c0cf0f4185c8f47812c37bc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 23 Jul 2015 19:10:28 +0100 Subject: when building a CSR adding > 1 extension would trigger a bug We were checking sk_X509_EXTENSION_push for a value == 1, but in reality it returns the number of extensions on the stack. We now assert >= 1 and added a test. --- tests/test_x509.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'tests') diff --git a/tests/test_x509.py b/tests/test_x509.py index 94eeab2b..b2262c71 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -978,6 +978,31 @@ class TestCertificateSigningRequestBuilder(object): with pytest.raises(NotImplementedError): builder.sign(private_key, hashes.SHA256(), backend) + def test_add_two_extensions(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + builder = x509.CertificateSigningRequestBuilder() + request = builder.subject_name( + x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')]) + ).add_extension( + x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]), + critical=False, + ).add_extension( + x509.BasicConstraints(ca=True, path_length=2), critical=True + ).sign(private_key, hashes.SHA1(), backend) + + assert isinstance(request.signature_hash_algorithm, hashes.SHA1) + public_key = request.public_key() + assert isinstance(public_key, rsa.RSAPublicKey) + basic_constraints = request.extensions.get_extension_for_oid( + x509.OID_BASIC_CONSTRAINTS + ) + assert basic_constraints.value.ca is True + assert basic_constraints.value.path_length == 2 + ext = request.extensions.get_extension_for_oid( + x509.OID_SUBJECT_ALTERNATIVE_NAME + ) + assert list(ext.value) == [x509.DNSName(u"cryptography.io")] + def test_set_subject_twice(self): builder = x509.CertificateSigningRequestBuilder() builder = builder.subject_name( -- cgit v1.2.3 From dce91f0b2923daf60a6fdfd811eb5b3d81ac7c88 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 23 Jul 2015 20:31:12 +0100 Subject: Support encoding KeyUsage into certificate signing requests --- tests/test_x509.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test_x509.py b/tests/test_x509.py index b2262c71..af7d9421 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -961,6 +961,20 @@ class TestCertificateSigningRequestBuilder(object): ).add_extension( x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]), critical=False, + ).add_extension( + x509.InhibitAnyPolicy(0), + critical=False + ) + with pytest.raises(NotImplementedError): + builder.sign(private_key, hashes.SHA256(), backend) + + def test_key_usage(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + builder = x509.CertificateSigningRequestBuilder() + request = builder.subject_name( + x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'), + ]) ).add_extension( x509.KeyUsage( digital_signature=True, @@ -974,9 +988,57 @@ class TestCertificateSigningRequestBuilder(object): decipher_only=False ), critical=False + ).sign(private_key, hashes.SHA256(), backend) + assert len(request.extensions) == 1 + ext = request.extensions.get_extension_for_oid(x509.OID_KEY_USAGE) + assert ext.critical is False + assert ext.value == x509.KeyUsage( + digital_signature=True, + content_commitment=True, + key_encipherment=False, + data_encipherment=False, + key_agreement=False, + key_cert_sign=True, + crl_sign=False, + encipher_only=False, + decipher_only=False + ) + + def test_key_usage_key_agreement_bit(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + builder = x509.CertificateSigningRequestBuilder() + request = builder.subject_name( + x509.Name([ + x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'), + ]) + ).add_extension( + x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=True, + key_cert_sign=True, + crl_sign=False, + encipher_only=False, + decipher_only=True + ), + critical=False + ).sign(private_key, hashes.SHA256(), backend) + assert len(request.extensions) == 1 + ext = request.extensions.get_extension_for_oid(x509.OID_KEY_USAGE) + assert ext.critical is False + assert ext.value == x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=False, + key_agreement=True, + key_cert_sign=True, + crl_sign=False, + encipher_only=False, + decipher_only=True ) - with pytest.raises(NotImplementedError): - builder.sign(private_key, hashes.SHA256(), backend) def test_add_two_extensions(self, backend): private_key = RSA_KEY_2048.private_key(backend) -- cgit v1.2.3 From 0b8f327f59b5a890f2d2ad9101391a0b818e186a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 23 Jul 2015 21:46:21 +0100 Subject: Support encoding ExtendedKeyUsage into certificate signing requests --- tests/test_x509.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'tests') diff --git a/tests/test_x509.py b/tests/test_x509.py index af7d9421..cacf3c88 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1183,6 +1183,29 @@ class TestCertificateSigningRequestBuilder(object): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) + def test_extended_key_usage(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + builder = x509.CertificateSigningRequestBuilder() + request = builder.subject_name( + x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')]) + ).add_extension( + x509.ExtendedKeyUsage([ + x509.OID_CLIENT_AUTH, + x509.OID_SERVER_AUTH, + x509.OID_CODE_SIGNING, + ]), critical=False + ).sign(private_key, hashes.SHA256(), backend) + + eku = request.extensions.get_extension_for_oid( + x509.OID_EXTENDED_KEY_USAGE + ) + assert eku.critical is False + assert eku.value == x509.ExtendedKeyUsage([ + x509.OID_CLIENT_AUTH, + x509.OID_SERVER_AUTH, + x509.OID_CODE_SIGNING, + ]) + @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) -- cgit v1.2.3 From 4e4a9ba524efe4963961c62c6da915a834ca185c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 25 Jul 2015 18:49:35 +0100 Subject: handle RSA key too small and consume errors on CSR signature failure --- tests/test_x509.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tests') diff --git a/tests/test_x509.py b/tests/test_x509.py index cacf3c88..38432271 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1206,6 +1206,19 @@ class TestCertificateSigningRequestBuilder(object): x509.OID_CODE_SIGNING, ]) + @pytest.mark.requires_backend_interface(interface=RSABackend) + def test_rsa_key_too_small(self, backend): + private_key = rsa.generate_private_key(65537, 512, backend) + builder = x509.CertificateSigningRequestBuilder() + builder = builder.subject_name( + x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')]) + ) + + with pytest.raises(ValueError) as exc: + builder.sign(private_key, hashes.SHA512(), backend) + + assert exc.value.message == "Digest too big for RSA key" + @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) -- cgit v1.2.3 From 6a71f8d9972032c5f034ba47bcf3439c9ffd3494 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 25 Jul 2015 19:15:59 +0100 Subject: py3 fixin' --- tests/test_x509.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/test_x509.py b/tests/test_x509.py index 38432271..98cf49be 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1217,7 +1217,7 @@ class TestCertificateSigningRequestBuilder(object): with pytest.raises(ValueError) as exc: builder.sign(private_key, hashes.SHA512(), backend) - assert exc.value.message == "Digest too big for RSA key" + assert str(exc.value) == "Digest too big for RSA key" @pytest.mark.requires_backend_interface(interface=DSABackend) -- cgit v1.2.3 From ed07bbc76da5c582fa7449321759ad0598b6e20c Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 14:16:00 +0100 Subject: move urandom engine test This test was in the bindings dir, which is incorrect. We do not set the urandom engine to default unless the openssl backend is loaded. The reason the test wasn't failing (even in the random test case) is that the backends are loaded during pytest_generate_tests by a call to _available_backends. So no matter what order it occurred in the engine was already set to default. I discovered this when I tried to run the test_openssl.py bindings tests directly via pytest. Hooray global state. --- tests/hazmat/backends/test_openssl.py | 27 +++++++++++++++++++++++++++ tests/hazmat/bindings/test_openssl.py | 30 ------------------------------ 2 files changed, 27 insertions(+), 30 deletions(-) (limited to 'tests') diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 6a2e8a77..a8401b30 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -34,6 +34,20 @@ from ..primitives.test_ec import _skip_curve_unsupported from ...utils import load_vectors_from_file, raises_unsupported_algorithm +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") + + @utils.register_interface(Mode) class DummyMode(object): name = "dummy-mode" @@ -216,6 +230,19 @@ class TestOpenSSL(object): bn = backend._int_to_bn(0) assert backend._bn_to_int(bn) == 0 + def test_actual_osrandom_bytes(self, monkeypatch): + skip_if_libre_ssl(backend.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 = backend._ffi.new("char[]", length) + backend._lib.RAND_bytes(buf, length) + assert backend._ffi.buffer(buf)[0:length] == sample_data + class TestOpenSSLRandomEngine(object): def teardown_method(self, method): diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index f3f2eaf4..75a8e3f1 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -4,27 +4,11 @@ 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() @@ -108,20 +92,6 @@ class TestOpenSSL(object): 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. b = Binding() -- cgit v1.2.3 From 301952b141eb346fea4c0308e9c54bd94370b145 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 16:30:57 +0100 Subject: this is gonna be unicode now --- tests/hazmat/backends/test_openssl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index a8401b30..040e3677 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -35,17 +35,17 @@ from ...utils import load_vectors_from_file, raises_unsupported_algorithm def skip_if_libre_ssl(openssl_version): - if b'LibreSSL' in openssl_version: + if u'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 + assert skip_if_libre_ssl(u"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") + skip_if_libre_ssl(u"LibreSSL 2.1.6") @utils.register_interface(Mode) -- cgit v1.2.3 From fcd7d707feba6f02b89fa2d2c9eb3b8a0df5e7f4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 19:41:25 +0100 Subject: add a line for the ecdh vector loader to cover a missed branch --- tests/test_utils.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/test_utils.py b/tests/test_utils.py index f71264ea..416de795 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -3047,6 +3047,7 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93 def test_load_kasvs_ecdh_vectors(): vector_data = textwrap.dedent(""" + # CAVS 11.0 # Parameter set(s) supported: EA EB EC ED EE # CAVSid: CAVSid (in hex: 434156536964) # IUTid: In hex: a1b2c3d4e5 -- cgit v1.2.3 From b60b8dd64513411f945da5af5f4f6eaa4330827b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 19:47:22 +0100 Subject: remove some more branching in the vector loaders --- tests/utils.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/tests/utils.py b/tests/utils.py index 5083d48c..7e7abdf1 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -539,8 +539,8 @@ def load_fips_ecdsa_key_pair_vectors(vector_data): elif line.startswith("Qy = "): key_data["y"] = int(line.split("=")[1], 16) - if key_data is not None: - vectors.append(key_data) + assert key_data is not None + vectors.append(key_data) return vectors @@ -559,9 +559,6 @@ def load_fips_ecdsa_signing_vectors(vector_data): for line in vector_data: line = line.strip() - if not line or line.startswith("#"): - continue - curve_match = curve_rx.match(line) if curve_match: curve_name = _ECDSA_CURVE_NAMES[curve_match.group("curve")] @@ -593,8 +590,8 @@ def load_fips_ecdsa_signing_vectors(vector_data): elif line.startswith("Result = "): data["fail"] = line.split("=")[1].strip()[0] == "F" - if data is not None: - vectors.append(data) + assert data is not None + vectors.append(data) return vectors -- cgit v1.2.3 From ac78c866d3fd94c3de0e8a33e18654a312083c3e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 20:26:00 +0100 Subject: add test to cover partial branch in load_kasvs_ecdh_vectors The loop to find supported parameter sets is partially covered otherwise --- tests/test_utils.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests') diff --git a/tests/test_utils.py b/tests/test_utils.py index 416de795..210e9292 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -3045,6 +3045,10 @@ d518475576730ed528779366568e46b7dd4ed787cb72d0733c93 assert expected == load_kasvs_dh_vectors(vector_data) +def test_load_kasvs_ecdh_vectors_empty_vector_data(): + assert [] == load_kasvs_ecdh_vectors([]) + + def test_load_kasvs_ecdh_vectors(): vector_data = textwrap.dedent(""" # CAVS 11.0 -- cgit v1.2.3 From a08693f3a71a6537da9cfa7d9dda7781aef2bcdd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 20:45:21 +0100 Subject: check if the extension decoded to internal openssl repr ...and if not, raise an error (plus consume the error stack) --- tests/test_x509_ext.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'tests') diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 7b135828..2980808f 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -2853,3 +2853,18 @@ class TestInhibitAnyPolicyExtension(object): x509.OID_INHIBIT_ANY_POLICY ).value assert iap.skip_certs == 5 + + +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) +class TestCorruptExtension(object): + def test_invalid_certificate_policies_data(self, backend): + cert = _load_cert( + os.path.join( + "x509", "custom", "cp_invalid.pem" + ), + x509.load_pem_x509_certificate, + backend + ) + with pytest.raises(ValueError): + cert.extensions -- cgit v1.2.3 From 1b7500f5f91a9ad07f5f15caf17264753173f8d8 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 1 Aug 2015 20:56:27 +0100 Subject: corrupt -> invalid --- tests/test_x509_ext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py index 2980808f..890709ae 100644 --- a/tests/test_x509_ext.py +++ b/tests/test_x509_ext.py @@ -2857,7 +2857,7 @@ class TestInhibitAnyPolicyExtension(object): @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) -class TestCorruptExtension(object): +class TestInvalidExtension(object): def test_invalid_certificate_policies_data(self, backend): cert = _load_cert( os.path.join( -- cgit v1.2.3