From dc57040a59ce4211a6ab6db843c497a87a825509 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Thu, 24 Sep 2015 20:24:28 -0700 Subject: OpenSSL backend code for CRLs --- tests/test_x509.py | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) (limited to 'tests/test_x509.py') diff --git a/tests/test_x509.py b/tests/test_x509.py index 220e71a5..f5fead53 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -52,6 +52,252 @@ 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_certs(self, backend): + crl = _load_cert( + os.path.join("x509", "custom", "crl_all_reasons.pem"), + x509.load_pem_x509_crl, + backend + ) + + assert isinstance(crl.revoked_certificates, list) + for r in crl.revoked_certificates: + assert isinstance(r, x509.RevokedCertificate) + + 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.revoked_certificates): + 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 + ) + + # First revoked cert doesn't have extensions, test if it is handled + # correctly. + rev0 = crl.revoked_certificates[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) + + assert rev0.get_invalidity_date() is None + assert rev0.get_certificate_issuer() is None + assert rev0.get_reason() is None + + # Test manual retrieval of extension values. + rev1 = crl.revoked_certificates[1] + assert isinstance(rev1.extensions, x509.Extensions) + + reason = rev1.extensions.get_extension_for_oid( + x509.OID_CRL_REASON).value + assert reason == x509.ReasonFlags.unspecified + + 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" + + # Test convenience function. + assert rev1.get_invalidity_date().isoformat() == "2015-01-01T00:00:00" + + # Check if all reason flags can be found in the CRL. + flags = set(x509.ReasonFlags) + # The first revoked cert doesn't have a reason. + for r in crl.revoked_certificates[1:]: + flags.discard(r.get_reason()) + 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.revoked_certificates[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.revoked_certificates[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.revoked_certificates[0].extensions + + def test_cert_issuer_ext(self, backend): + if backend._lib.OPENSSL_VERSION_NUMBER < 0x10000000: + pytest.skip("Requires a newer OpenSSL. Must be at least 1.0.0") + + 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"), + ])) + ]) + + rev = crl.revoked_certificates[1] + issuer = rev.extensions.get_extension_for_oid( + x509.OID_CERTIFICATE_ISSUER).value + assert issuer == exp_issuer + + # Test convenience function. + assert rev.get_certificate_issuer() == exp_issuer + + @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) class TestRSACertificate(object): -- cgit v1.2.3 From 396a282fd5febabe382dcdacf4e8a6c2395f0087 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Mon, 28 Sep 2015 08:56:18 -0700 Subject: use openssl assert change _build* to _decode* make CRLs into iterators various fixes --- tests/test_x509.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tests/test_x509.py') diff --git a/tests/test_x509.py b/tests/test_x509.py index f5fead53..c380b860 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -232,12 +232,15 @@ class TestRevokedCertificate(object): assert rev1.get_invalidity_date().isoformat() == "2015-01-01T00:00:00" # Check if all reason flags can be found in the CRL. + # Also test if CRL as iterator works. flags = set(x509.ReasonFlags) - # The first revoked cert doesn't have a reason. - for r in crl.revoked_certificates[1:]: + for r in crl: flags.discard(r.get_reason()) assert len(flags) == 0 + # Check that len() works for CRLs. + assert len(crl) == 12 + def test_duplicate_entry_ext(self, backend): crl = _load_cert( os.path.join("x509", "custom", "crl_dup_entry_ext.pem"), -- cgit v1.2.3 From 3cdabaf2544b98c6c915ca6704f9e03fdd58e1e6 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Tue, 13 Oct 2015 09:42:53 -0700 Subject: fix indentations change docs to indicate CRL objects are iterable fix docs for revoked certs make _decode_crl_reason more readable add __getitem__ method to CRL object remove double underscores --- tests/test_x509.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests/test_x509.py') diff --git a/tests/test_x509.py b/tests/test_x509.py index c380b860..61e7a7d0 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -241,6 +241,9 @@ class TestRevokedCertificate(object): # Check that len() works for CRLs. assert len(crl) == 12 + # Check that direct access to revoked cert in CRL works + assert isinstance(crl[0], x509.RevokedCertificate) + def test_duplicate_entry_ext(self, backend): crl = _load_cert( os.path.join("x509", "custom", "crl_dup_entry_ext.pem"), -- cgit v1.2.3 From 77f5a2560a2c637364467a5f74b60a0e70e177f9 Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Wed, 14 Oct 2015 08:06:38 -0700 Subject: use X509ExtensionParser for Revoked extensions remove revoked_certificates property from RevokedCertificate class CRLExtensions should actually be RevokedExtensions doctest cleanup for RevokedCertificate --- tests/test_x509.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'tests/test_x509.py') diff --git a/tests/test_x509.py b/tests/test_x509.py index 61e7a7d0..347ed1a6 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -153,17 +153,19 @@ class TestCertificateRevocationList(object): assert crl.next_update.isoformat() == "2016-01-01T00:00:00" assert crl.last_update.isoformat() == "2015-01-01T00:00:00" - def test_revoked_certs(self, backend): + 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 ) - assert isinstance(crl.revoked_certificates, list) - for r in crl.revoked_certificates: + 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"), @@ -186,7 +188,7 @@ class TestRevokedCertificate(object): backend ) - for i, rev in enumerate(crl.revoked_certificates): + for i, rev in enumerate(crl): assert isinstance(rev, x509.RevokedCertificate) assert isinstance(rev.serial_number, int) assert isinstance(rev.revocation_date, datetime.datetime) @@ -204,7 +206,7 @@ class TestRevokedCertificate(object): # First revoked cert doesn't have extensions, test if it is handled # correctly. - rev0 = crl.revoked_certificates[0] + rev0 = crl[0] # It should return an empty Extensions object. assert isinstance(rev0.extensions, x509.Extensions) assert len(rev0.extensions) == 0 @@ -216,7 +218,7 @@ class TestRevokedCertificate(object): assert rev0.get_reason() is None # Test manual retrieval of extension values. - rev1 = crl.revoked_certificates[1] + rev1 = crl[1] assert isinstance(rev1.extensions, x509.Extensions) reason = rev1.extensions.get_extension_for_oid( @@ -232,18 +234,11 @@ class TestRevokedCertificate(object): assert rev1.get_invalidity_date().isoformat() == "2015-01-01T00:00:00" # Check if all reason flags can be found in the CRL. - # Also test if CRL as iterator works. flags = set(x509.ReasonFlags) for r in crl: flags.discard(r.get_reason()) assert len(flags) == 0 - # Check that len() works for CRLs. - assert len(crl) == 12 - - # Check that direct access to revoked cert in CRL works - assert isinstance(crl[0], x509.RevokedCertificate) - def test_duplicate_entry_ext(self, backend): crl = _load_cert( os.path.join("x509", "custom", "crl_dup_entry_ext.pem"), @@ -252,7 +247,7 @@ class TestRevokedCertificate(object): ) with pytest.raises(x509.DuplicateExtension): - crl.revoked_certificates[0].extensions + crl[0].extensions def test_unsupported_crit_entry_ext(self, backend): crl = _load_cert( @@ -264,7 +259,7 @@ class TestRevokedCertificate(object): ) with pytest.raises(x509.UnsupportedExtension): - crl.revoked_certificates[0].extensions + crl[0].extensions def test_unsupported_reason(self, backend): crl = _load_cert( @@ -276,7 +271,7 @@ class TestRevokedCertificate(object): ) with pytest.raises(ValueError): - crl.revoked_certificates[0].extensions + crl[0].extensions def test_cert_issuer_ext(self, backend): if backend._lib.OPENSSL_VERSION_NUMBER < 0x10000000: @@ -295,7 +290,7 @@ class TestRevokedCertificate(object): ])) ]) - rev = crl.revoked_certificates[1] + rev = crl[1] issuer = rev.extensions.get_extension_for_oid( x509.OID_CERTIFICATE_ISSUER).value assert issuer == exp_issuer -- cgit v1.2.3 From d4e7d43416077f18a37008298abdc566bd3f069d Mon Sep 17 00:00:00 2001 From: Erik Trauschke Date: Thu, 15 Oct 2015 14:45:38 -0700 Subject: removing caching mechanism for x509 properties undo name change of CRLExtensionOID use custom parsing mechanism for certIssuer entry extension add new crl to vectors for testing invalid certIssuer entry ext --- tests/test_x509.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'tests/test_x509.py') diff --git a/tests/test_x509.py b/tests/test_x509.py index 347ed1a6..ded2f0ee 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -204,6 +204,13 @@ class TestRevokedCertificate(object): 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] @@ -225,6 +232,10 @@ class TestRevokedCertificate(object): 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) @@ -232,6 +243,7 @@ class TestRevokedCertificate(object): # Test convenience function. assert rev1.get_invalidity_date().isoformat() == "2015-01-01T00:00:00" + assert rev1.get_certificate_issuer() == exp_issuer # Check if all reason flags can be found in the CRL. flags = set(x509.ReasonFlags) @@ -273,30 +285,17 @@ class TestRevokedCertificate(object): with pytest.raises(ValueError): crl[0].extensions - def test_cert_issuer_ext(self, backend): - if backend._lib.OPENSSL_VERSION_NUMBER < 0x10000000: - pytest.skip("Requires a newer OpenSSL. Must be at least 1.0.0") - + def test_invalid_cert_issuer_ext(self, backend): crl = _load_cert( - os.path.join("x509", "custom", "crl_all_reasons.pem"), + os.path.join( + "x509", "custom", "crl_inval_cert_issuer_entry_ext.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"), - ])) - ]) - - rev = crl[1] - issuer = rev.extensions.get_extension_for_oid( - x509.OID_CERTIFICATE_ISSUER).value - assert issuer == exp_issuer - - # Test convenience function. - assert rev.get_certificate_issuer() == exp_issuer + with pytest.raises(ValueError): + crl[0].extensions @pytest.mark.requires_backend_interface(interface=RSABackend) -- cgit v1.2.3