From fec719b60441b1e69bcca26446b8025bb69ee1fd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 3 Dec 2018 00:42:44 +0800 Subject: encode IssuingDistributionPoint (#4618) --- .../hazmat/backends/openssl/encode_asn1.py | 23 ++++ tests/hazmat/backends/test_openssl_memleak.py | 45 +++++++ tests/x509/test_x509_ext.py | 137 +++++++++++++++++++++ 3 files changed, 205 insertions(+) diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py index 8bc8cb4b..35575762 100644 --- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -136,6 +136,28 @@ def _encode_crl_number_delta_crl_indicator(backend, ext): return _encode_asn1_int_gc(backend, ext.crl_number) +def _encode_issuing_dist_point(backend, ext): + idp = backend._lib.ISSUING_DIST_POINT_new() + backend.openssl_assert(idp != backend._ffi.NULL) + idp = backend._ffi.gc(idp, backend._lib.ISSUING_DIST_POINT_free) + idp.onlyuser = 255 if ext.only_contains_user_certs else 0 + idp.onlyCA = 255 if ext.only_contains_ca_certs else 0 + idp.indirectCRL = 255 if ext.indirect_crl else 0 + idp.onlyattr = 255 if ext.only_contains_attribute_certs else 0 + if ext.only_some_reasons: + idp.onlysomereasons = _encode_reasonflags( + backend, ext.only_some_reasons + ) + + if ext.full_name: + idp.distpoint = _encode_full_name(backend, ext.full_name) + + if ext.relative_name: + idp.distpoint = _encode_relative_name(backend, ext.relative_name) + + return idp + + def _encode_crl_reason(backend, crl_reason): asn1enum = backend._lib.ASN1_ENUMERATED_new() backend.openssl_assert(asn1enum != backend._ffi.NULL) @@ -614,6 +636,7 @@ _CRL_EXTENSION_ENCODE_HANDLERS = { ), ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator, ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator, + ExtensionOID.ISSUING_DISTRIBUTION_POINT: _encode_issuing_dist_point, } _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = { diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index 6f42ed79..1db103b5 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -325,3 +325,48 @@ class TestOpenSSLMemoryLeaks(object): f.read(), b"cryptography", backend ) """), [path]) + + def test_create_crl_with_idp(self): + assert_no_memory_leaks(textwrap.dedent(""" + def func(): + import datetime + from cryptography import x509 + from cryptography.hazmat.backends.openssl import backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import ec + from cryptography.x509.oid import NameOID + + key = ec.generate_private_key(ec.SECP256R1(), backend) + last_update = datetime.datetime(2002, 1, 1, 12, 1) + next_update = datetime.datetime(2030, 1, 1, 12, 1) + idp = x509.IssuingDistributionPoint( + full_name=None, + relative_name=x509.RelativeDistinguishedName([ + x509.NameAttribute( + oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA") + ]), + only_contains_user_certs=False, + only_contains_ca_certs=True, + only_some_reasons=None, + indirect_crl=False, + only_contains_attribute_certs=False, + ) + builder = x509.CertificateRevocationListBuilder().issuer_name( + x509.Name([ + x509.NameAttribute( + NameOID.COMMON_NAME, u"cryptography.io CA" + ) + ]) + ).last_update( + last_update + ).next_update( + next_update + ).add_extension( + idp, True + ) + + crl = builder.sign(key, hashes.SHA256(), backend) + crl.extensions.get_extension_for_class( + x509.IssuingDistributionPoint + ) + """)) diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 5ff3bdd6..bfa37847 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -4727,6 +4727,143 @@ class TestIssuingDistributionPointExtension(object): assert hash(idp1) == hash(idp2) assert hash(idp1) != hash(idp3) + @pytest.mark.requires_backend_interface(interface=RSABackend) + @pytest.mark.requires_backend_interface(interface=X509Backend) + @pytest.mark.parametrize( + "idp", + [ + x509.IssuingDistributionPoint( + full_name=[ + x509.UniformResourceIdentifier( + u"http://myhost.com/myca.crl" + ) + ], + relative_name=None, + only_contains_user_certs=False, + only_contains_ca_certs=False, + only_some_reasons=None, + indirect_crl=True, + only_contains_attribute_certs=False, + ), + x509.IssuingDistributionPoint( + full_name=[ + x509.UniformResourceIdentifier( + u"http://myhost.com/myca.crl" + ) + ], + relative_name=None, + only_contains_user_certs=False, + only_contains_ca_certs=False, + only_some_reasons=None, + indirect_crl=False, + only_contains_attribute_certs=False, + ), + x509.IssuingDistributionPoint( + full_name=[ + x509.UniformResourceIdentifier( + u"http://myhost.com/myca.crl" + ) + ], + relative_name=None, + only_contains_user_certs=False, + only_contains_ca_certs=False, + only_some_reasons=None, + indirect_crl=False, + only_contains_attribute_certs=True, + ), + x509.IssuingDistributionPoint( + full_name=[ + x509.UniformResourceIdentifier( + u"http://myhost.com/myca.crl" + ) + ], + relative_name=None, + only_contains_user_certs=True, + only_contains_ca_certs=False, + only_some_reasons=None, + indirect_crl=False, + only_contains_attribute_certs=False, + ), + x509.IssuingDistributionPoint( + full_name=None, + relative_name=x509.RelativeDistinguishedName([ + x509.NameAttribute( + oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + ) + ]), + only_contains_user_certs=False, + only_contains_ca_certs=True, + only_some_reasons=None, + indirect_crl=False, + only_contains_attribute_certs=False, + ), + x509.IssuingDistributionPoint( + full_name=None, + relative_name=None, + only_contains_user_certs=False, + only_contains_ca_certs=True, + only_some_reasons=frozenset([x509.ReasonFlags.key_compromise]), + indirect_crl=False, + only_contains_attribute_certs=False, + ), + x509.IssuingDistributionPoint( + full_name=None, + relative_name=x509.RelativeDistinguishedName([ + x509.NameAttribute( + oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA"), + x509.NameAttribute( + oid=x509.NameOID.COMMON_NAME, value=u"cryptography") + ]), + only_contains_user_certs=True, + only_contains_ca_certs=False, + only_some_reasons=frozenset([ + x509.ReasonFlags.key_compromise, + x509.ReasonFlags.ca_compromise, + x509.ReasonFlags.affiliation_changed, + x509.ReasonFlags.privilege_withdrawn, + x509.ReasonFlags.aa_compromise, + ]), + indirect_crl=False, + only_contains_attribute_certs=False, + ), + x509.IssuingDistributionPoint( + full_name=None, + relative_name=x509.RelativeDistinguishedName([ + x509.NameAttribute( + oid=x509.NameOID.ORGANIZATION_NAME, value=u"PyCA" + ) + ]), + only_contains_user_certs=False, + only_contains_ca_certs=False, + only_some_reasons=None, + indirect_crl=False, + only_contains_attribute_certs=False, + ), + ] + ) + def test_generate(self, idp, backend): + key = RSA_KEY_2048.private_key(backend) + last_update = datetime.datetime(2002, 1, 1, 12, 1) + next_update = datetime.datetime(2030, 1, 1, 12, 1) + builder = x509.CertificateRevocationListBuilder().issuer_name( + x509.Name([ + x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA") + ]) + ).last_update( + last_update + ).next_update( + next_update + ).add_extension( + idp, True + ) + + crl = builder.sign(key, hashes.SHA256(), backend) + ext = crl.extensions.get_extension_for_class( + x509.IssuingDistributionPoint + ) + assert ext.critical is True + assert ext.value == idp + @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) -- cgit v1.2.3