aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/hazmat/backends/test_multibackend.py12
-rw-r--r--tests/hazmat/bindings/test_openssl.py4
-rw-r--r--tests/hazmat/primitives/test_keywrap.py116
-rw-r--r--tests/test_x509.py355
-rw-r--r--tests/test_x509_ext.py14
5 files changed, 499 insertions, 2 deletions
diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py
index 2a533750..81a64ce0 100644
--- a/tests/hazmat/backends/test_multibackend.py
+++ b/tests/hazmat/backends/test_multibackend.py
@@ -200,6 +200,12 @@ class DummyX509Backend(object):
def load_der_x509_certificate(self, data):
pass
+ def load_pem_x509_crl(self, data):
+ pass
+
+ def load_der_x509_crl(self, data):
+ pass
+
def load_pem_x509_csr(self, data):
pass
@@ -502,6 +508,8 @@ class TestMultiBackend(object):
backend.load_pem_x509_certificate(b"certdata")
backend.load_der_x509_certificate(b"certdata")
+ backend.load_pem_x509_crl(b"crldata")
+ backend.load_der_x509_crl(b"crldata")
backend.load_pem_x509_csr(b"reqdata")
backend.load_der_x509_csr(b"reqdata")
backend.create_x509_csr(object(), b"privatekey", hashes.SHA1())
@@ -513,6 +521,10 @@ class TestMultiBackend(object):
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
backend.load_der_x509_certificate(b"certdata")
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
+ backend.load_pem_x509_crl(b"crldata")
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
+ backend.load_der_x509_crl(b"crldata")
+ with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
backend.load_pem_x509_csr(b"reqdata")
with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_X509):
backend.load_der_x509_csr(b"reqdata")
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index 20171fa7..76a9218b 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -89,8 +89,8 @@ class TestOpenSSL(object):
def test_add_engine_more_than_once(self):
b = Binding()
- with pytest.raises(RuntimeError):
- b._register_osrandom_engine()
+ b._register_osrandom_engine()
+ assert b.lib.ERR_get_error() == 0
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_keywrap.py b/tests/hazmat/primitives/test_keywrap.py
new file mode 100644
index 00000000..f1238c9a
--- /dev/null
+++ b/tests/hazmat/primitives/test_keywrap.py
@@ -0,0 +1,116 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+import os
+
+import pytest
+
+from cryptography.hazmat.backends.interfaces import CipherBackend
+from cryptography.hazmat.primitives import keywrap
+from cryptography.hazmat.primitives.ciphers import algorithms, modes
+
+from .utils import _load_all_params
+from ...utils import load_nist_vectors
+
+
+@pytest.mark.requires_backend_interface(interface=CipherBackend)
+class TestAESKeyWrap(object):
+ @pytest.mark.parametrize(
+ "params",
+ _load_all_params(
+ os.path.join("keywrap", "kwtestvectors"),
+ ["KW_AE_128.txt", "KW_AE_192.txt", "KW_AE_256.txt"],
+ load_nist_vectors
+ )
+ )
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES("\x00" * 16), modes.ECB()
+ ),
+ skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
+ " is unsupported",
+ )
+ def test_wrap(self, backend, params):
+ wrapping_key = binascii.unhexlify(params["k"])
+ key_to_wrap = binascii.unhexlify(params["p"])
+ wrapped_key = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
+ assert params["c"] == binascii.hexlify(wrapped_key)
+
+ @pytest.mark.parametrize(
+ "params",
+ _load_all_params(
+ os.path.join("keywrap", "kwtestvectors"),
+ ["KW_AD_128.txt", "KW_AD_192.txt", "KW_AD_256.txt"],
+ load_nist_vectors
+ )
+ )
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES("\x00" * 16), modes.ECB()
+ ),
+ skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
+ " is unsupported",
+ )
+ def test_unwrap(self, backend, params):
+ wrapping_key = binascii.unhexlify(params["k"])
+ wrapped_key = binascii.unhexlify(params["c"])
+ if params.get("fail") is True:
+ with pytest.raises(keywrap.InvalidUnwrap):
+ keywrap.aes_key_unwrap(wrapping_key, wrapped_key, backend)
+ else:
+ unwrapped_key = keywrap.aes_key_unwrap(
+ wrapping_key, wrapped_key, backend
+ )
+ assert params["p"] == binascii.hexlify(unwrapped_key)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES("\x00" * 16), modes.ECB()
+ ),
+ skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
+ " is unsupported",
+ )
+ def test_wrap_invalid_key_length(self, backend):
+ # The wrapping key must be of length [16, 24, 32]
+ with pytest.raises(ValueError):
+ keywrap.aes_key_wrap(b"badkey", b"sixteen_byte_key", backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES("\x00" * 16), modes.ECB()
+ ),
+ skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
+ " is unsupported",
+ )
+ def test_unwrap_invalid_key_length(self, backend):
+ with pytest.raises(ValueError):
+ keywrap.aes_key_unwrap(b"badkey", b"\x00" * 24, backend)
+
+ @pytest.mark.supported(
+ only_if=lambda backend: backend.cipher_supported(
+ algorithms.AES("\x00" * 16), modes.ECB()
+ ),
+ skip_message="Does not support AES key wrap (RFC 3394) because AES-ECB"
+ " is unsupported",
+ )
+ def test_wrap_invalid_key_to_wrap_length(self, backend):
+ # Keys to wrap must be at least 16 bytes long
+ with pytest.raises(ValueError):
+ keywrap.aes_key_wrap(b"sixteen_byte_key", b"\x00" * 15, backend)
+
+ # Keys to wrap must be a multiple of 8 bytes
+ with pytest.raises(ValueError):
+ keywrap.aes_key_wrap(b"sixteen_byte_key", b"\x00" * 23, backend)
+
+ def test_unwrap_invalid_wrapped_key_length(self, backend):
+ # Keys to unwrap must be at least 24 bytes
+ with pytest.raises(ValueError):
+ keywrap.aes_key_unwrap(b"sixteen_byte_key", b"\x00" * 16, backend)
+
+ # Keys to unwrap must be a multiple of 8 bytes
+ with pytest.raises(ValueError):
+ keywrap.aes_key_unwrap(b"sixteen_byte_key", b"\x00" * 27, backend)
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 43eca472..4072ef15 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -56,6 +56,255 @@ def _load_cert(filename, loader, backend):
return cert
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestCertificateRevocationList(object):
+ def test_load_pem_crl(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ assert isinstance(crl, x509.CertificateRevocationList)
+ fingerprint = binascii.hexlify(crl.fingerprint(hashes.SHA1()))
+ assert fingerprint == b"3234b0cb4c0cedf6423724b736729dcfc9e441ef"
+ assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
+
+ def test_load_der_crl(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
+ x509.load_der_x509_crl,
+ backend
+ )
+
+ assert isinstance(crl, x509.CertificateRevocationList)
+ fingerprint = binascii.hexlify(crl.fingerprint(hashes.SHA1()))
+ assert fingerprint == b"dd3db63c50f4c4a13e090f14053227cb1011a5ad"
+ assert isinstance(crl.signature_hash_algorithm, hashes.SHA256)
+
+ def test_invalid_pem(self, backend):
+ with pytest.raises(ValueError):
+ x509.load_pem_x509_crl(b"notacrl", backend)
+
+ def test_invalid_der(self, backend):
+ with pytest.raises(ValueError):
+ x509.load_der_x509_crl(b"notacrl", backend)
+
+ def test_unknown_signature_algorithm(self, backend):
+ crl = _load_cert(
+ os.path.join(
+ "x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
+ ),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ with pytest.raises(UnsupportedAlgorithm):
+ crl.signature_hash_algorithm()
+
+ def test_issuer(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
+ x509.load_der_x509_crl,
+ backend
+ )
+
+ assert isinstance(crl.issuer, x509.Name)
+ assert list(crl.issuer) == [
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US'),
+ x509.NameAttribute(
+ x509.OID_ORGANIZATION_NAME, u'Test Certificates 2011'
+ ),
+ x509.NameAttribute(x509.OID_COMMON_NAME, u'Good CA')
+ ]
+ assert crl.issuer.get_attributes_for_oid(x509.OID_COMMON_NAME) == [
+ x509.NameAttribute(x509.OID_COMMON_NAME, u'Good CA')
+ ]
+
+ def test_equality(self, backend):
+ crl1 = _load_cert(
+ os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
+ x509.load_der_x509_crl,
+ backend
+ )
+
+ crl2 = _load_cert(
+ os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
+ x509.load_der_x509_crl,
+ backend
+ )
+
+ crl3 = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ assert crl1 == crl2
+ assert crl1 != crl3
+ assert crl1 != object()
+
+ def test_update_dates(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ assert isinstance(crl.next_update, datetime.datetime)
+ assert isinstance(crl.last_update, datetime.datetime)
+
+ assert crl.next_update.isoformat() == "2016-01-01T00:00:00"
+ assert crl.last_update.isoformat() == "2015-01-01T00:00:00"
+
+ def test_revoked_cert_retrieval(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ for r in crl:
+ assert isinstance(r, x509.RevokedCertificate)
+
+ # Check that len() works for CRLs.
+ assert len(crl) == 12
+
+ def test_extensions(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ # CRL extensions are currently not supported in the OpenSSL backend.
+ with pytest.raises(NotImplementedError):
+ crl.extensions
+
+
+@pytest.mark.requires_backend_interface(interface=X509Backend)
+class TestRevokedCertificate(object):
+
+ def test_revoked_basics(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ for i, rev in enumerate(crl):
+ assert isinstance(rev, x509.RevokedCertificate)
+ assert isinstance(rev.serial_number, int)
+ assert isinstance(rev.revocation_date, datetime.datetime)
+ assert isinstance(rev.extensions, x509.Extensions)
+
+ assert rev.serial_number == i
+ assert rev.revocation_date.isoformat() == "2015-01-01T00:00:00"
+
+ def test_revoked_extensions(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ exp_issuer = x509.GeneralNames([
+ x509.DirectoryName(x509.Name([
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+ x509.NameAttribute(x509.OID_COMMON_NAME, u"cryptography.io"),
+ ]))
+ ])
+
+ # First revoked cert doesn't have extensions, test if it is handled
+ # correctly.
+ rev0 = crl[0]
+ # It should return an empty Extensions object.
+ assert isinstance(rev0.extensions, x509.Extensions)
+ assert len(rev0.extensions) == 0
+ with pytest.raises(x509.ExtensionNotFound):
+ rev0.extensions.get_extension_for_oid(x509.OID_CRL_REASON)
+ with pytest.raises(x509.ExtensionNotFound):
+ rev0.extensions.get_extension_for_oid(x509.OID_CERTIFICATE_ISSUER)
+ with pytest.raises(x509.ExtensionNotFound):
+ rev0.extensions.get_extension_for_oid(x509.OID_INVALIDITY_DATE)
+
+ # Test manual retrieval of extension values.
+ rev1 = crl[1]
+ assert isinstance(rev1.extensions, x509.Extensions)
+
+ reason = rev1.extensions.get_extension_for_oid(
+ x509.OID_CRL_REASON).value
+ assert reason == x509.ReasonFlags.unspecified
+
+ issuer = rev1.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_ISSUER).value
+ assert issuer == exp_issuer
+
+ date = rev1.extensions.get_extension_for_oid(
+ x509.OID_INVALIDITY_DATE).value
+ assert isinstance(date, datetime.datetime)
+ assert date.isoformat() == "2015-01-01T00:00:00"
+
+ # Check if all reason flags can be found in the CRL.
+ flags = set(x509.ReasonFlags)
+ for rev in crl:
+ try:
+ r = rev.extensions.get_extension_for_oid(x509.OID_CRL_REASON)
+ except x509.ExtensionNotFound:
+ # Not all revoked certs have a reason extension.
+ pass
+ else:
+ flags.discard(r.value)
+
+ assert len(flags) == 0
+
+ def test_duplicate_entry_ext(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_dup_entry_ext.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ with pytest.raises(x509.DuplicateExtension):
+ crl[0].extensions
+
+ def test_unsupported_crit_entry_ext(self, backend):
+ crl = _load_cert(
+ os.path.join(
+ "x509", "custom", "crl_md2_unknown_crit_entry_ext.pem"
+ ),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ with pytest.raises(x509.UnsupportedExtension):
+ crl[0].extensions
+
+ def test_unsupported_reason(self, backend):
+ crl = _load_cert(
+ os.path.join(
+ "x509", "custom", "crl_unsupported_reason.pem"
+ ),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ with pytest.raises(ValueError):
+ crl[0].extensions
+
+ def test_invalid_cert_issuer_ext(self, backend):
+ crl = _load_cert(
+ os.path.join(
+ "x509", "custom", "crl_inval_cert_issuer_entry_ext.pem"
+ ),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ with pytest.raises(ValueError):
+ crl[0].extensions
+
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
class TestRSACertificate(object):
@@ -1486,6 +1735,95 @@ class TestCertificateBuilder(object):
with pytest.raises(ValueError):
builder.sign(issuer_private_key, hashes.SHA512(), backend)
+ @pytest.mark.parametrize(
+ "cp",
+ [
+ x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [u"http://other.com/cps"]
+ )
+ ]),
+ x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ None
+ )
+ ]),
+ x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ u"http://example.com/cps",
+ u"http://other.com/cps",
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ u"thing"
+ )
+ ]
+ )
+ ]),
+ x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ u"http://example.com/cps",
+ x509.UserNotice(
+ x509.NoticeReference(u"UTF8\u2122'", [1, 2, 3, 4]),
+ u"We heart UTF8!\u2122"
+ )
+ ]
+ )
+ ]),
+ x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [x509.UserNotice(None, u"thing")]
+ )
+ ]),
+ x509.CertificatePolicies([
+ x509.PolicyInformation(
+ x509.ObjectIdentifier("2.16.840.1.12345.1.2.3.4.1"),
+ [
+ x509.UserNotice(
+ x509.NoticeReference(u"my org", [1, 2, 3, 4]),
+ None
+ )
+ ]
+ )
+ ])
+ ]
+ )
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_certificate_policies(self, cp, backend):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = RSA_KEY_2048.private_key(backend)
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ cert = x509.CertificateBuilder().subject_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+ ).issuer_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+ ).not_valid_before(
+ not_valid_before
+ ).not_valid_after(
+ not_valid_after
+ ).public_key(
+ subject_private_key.public_key()
+ ).serial_number(
+ 123
+ ).add_extension(
+ cp, critical=False
+ ).sign(issuer_private_key, hashes.SHA256(), backend)
+
+ ext = cert.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_POLICIES
+ )
+ assert ext.value == cp
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_issuer_alt_name(self, backend):
@@ -2547,6 +2885,23 @@ class TestName(object):
assert name1 != name2
assert name1 != object()
+ def test_hash(self):
+ name1 = x509.Name([
+ x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'),
+ x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'),
+ ])
+ name2 = x509.Name([
+ x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'),
+ x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'),
+ ])
+ name3 = x509.Name([
+ x509.NameAttribute(x509.ObjectIdentifier('oid2'), u'value2'),
+ x509.NameAttribute(x509.ObjectIdentifier('oid'), u'value1'),
+ ])
+
+ assert hash(name1) == hash(name2)
+ assert hash(name1) != hash(name3)
+
def test_repr(self):
name = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index 1bc14620..8f469366 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -857,6 +857,20 @@ class TestExtensions(object):
assert ext is not None
assert isinstance(ext.value, x509.BasicConstraints)
+ def test_repr(self, backend):
+ cert = _load_cert(
+ os.path.join(
+ "x509", "custom", "basic_constraints_not_critical.pem"
+ ),
+ x509.load_pem_x509_certificate,
+ backend
+ )
+ assert repr(cert.extensions) == (
+ "<Extensions([<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name"
+ "=basicConstraints)>, critical=False, value=<BasicConstraints(ca=F"
+ "alse, path_length=None)>)>])>"
+ )
+
@pytest.mark.requires_backend_interface(interface=RSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)