aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2015-08-08 12:34:08 -0400
committerAlex Gaynor <alex.gaynor@gmail.com>2015-08-08 12:34:08 -0400
commitc9ee947f528269ea7a907a592219a788edf1a279 (patch)
treef4217e2c9b35f00a13284baeccd25b906aa54a21
parente3bc1b2a398091948cffabfd1e9976c0a8ab07f2 (diff)
parent0777325061deb2773e74dfe242d5150d0ce8b378 (diff)
downloadcryptography-c9ee947f528269ea7a907a592219a788edf1a279.tar.gz
cryptography-c9ee947f528269ea7a907a592219a788edf1a279.tar.bz2
cryptography-c9ee947f528269ea7a907a592219a788edf1a279.zip
Merge pull request #2198 from reaperhulk/encode-crl
support CRLDistributionPoints in the CertificateBuilder
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py68
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py6
-rw-r--r--src/cryptography/x509.py4
-rw-r--r--tests/test_x509.py148
4 files changed, 224 insertions, 2 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 0038ddb0..2752d98d 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -38,7 +38,8 @@ from cryptography.hazmat.backends.openssl.rsa import (
_RSAPrivateKey, _RSAPublicKey
)
from cryptography.hazmat.backends.openssl.x509 import (
- _Certificate, _CertificateSigningRequest
+ _Certificate, _CertificateSigningRequest, _DISTPOINT_TYPE_FULLNAME,
+ _DISTPOINT_TYPE_RELATIVENAME
)
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import hashes, serialization
@@ -359,6 +360,67 @@ def _encode_extended_key_usage(backend, extended_key_usage):
return pp, r
+_CRLREASONFLAGS = {
+ x509.ReasonFlags.key_compromise: 1,
+ x509.ReasonFlags.ca_compromise: 2,
+ x509.ReasonFlags.affiliation_changed: 3,
+ x509.ReasonFlags.superseded: 4,
+ x509.ReasonFlags.cessation_of_operation: 5,
+ x509.ReasonFlags.certificate_hold: 6,
+ x509.ReasonFlags.privilege_withdrawn: 7,
+ x509.ReasonFlags.aa_compromise: 8,
+}
+
+
+def _encode_crl_distribution_points(backend, crl_distribution_points):
+ cdp = backend._lib.sk_DIST_POINT_new_null()
+ cdp = backend._ffi.gc(cdp, backend._lib.sk_DIST_POINT_free)
+ for point in crl_distribution_points:
+ dp = backend._lib.DIST_POINT_new()
+ assert dp != backend._ffi.NULL
+
+ if point.reasons:
+ bitmask = backend._lib.ASN1_BIT_STRING_new()
+ assert bitmask != backend._ffi.NULL
+ dp.reasons = bitmask
+ for reason in point.reasons:
+ res = backend._lib.ASN1_BIT_STRING_set_bit(
+ bitmask, _CRLREASONFLAGS[reason], 1
+ )
+ assert res == 1
+
+ if point.full_name:
+ dpn = backend._lib.DIST_POINT_NAME_new()
+ assert dpn != backend._ffi.NULL
+ dpn.type = _DISTPOINT_TYPE_FULLNAME
+ dpn.name.fullname = _encode_general_names(backend, point.full_name)
+ dp.distpoint = dpn
+
+ if point.relative_name:
+ dpn = backend._lib.DIST_POINT_NAME_new()
+ assert dpn != backend._ffi.NULL
+ dpn.type = _DISTPOINT_TYPE_RELATIVENAME
+ name = _encode_name_gc(backend, point.relative_name)
+ relativename = backend._lib.sk_X509_NAME_ENTRY_dup(name.entries)
+ assert relativename != backend._ffi.NULL
+ dpn.name.relativename = relativename
+ dp.distpoint = dpn
+
+ if point.crl_issuer:
+ dp.CRLissuer = _encode_general_names(backend, point.crl_issuer)
+
+ res = backend._lib.sk_DIST_POINT_push(cdp, dp)
+ assert res >= 1
+
+ pp = backend._ffi.new('unsigned char **')
+ r = backend._lib.i2d_CRL_DIST_POINTS(cdp, pp)
+ assert r > 0
+ pp = backend._ffi.gc(
+ pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+ )
+ return pp, r
+
+
@utils.register_interface(CipherBackend)
@utils.register_interface(CMACBackend)
@utils.register_interface(DERSerializationBackend)
@@ -1177,6 +1239,10 @@ class Backend(object):
pp, r = _encode_authority_information_access(
self, extension.value
)
+ elif isinstance(extension.value, x509.CRLDistributionPoints):
+ pp, r = _encode_crl_distribution_points(
+ self, extension.value
+ )
else:
raise NotImplementedError('Extension not yet supported.')
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index ee9a3bbf..564b2680 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -592,6 +592,10 @@ def _decode_extended_key_usage(backend, sk):
return x509.ExtendedKeyUsage(ekus)
+_DISTPOINT_TYPE_FULLNAME = 0
+_DISTPOINT_TYPE_RELATIVENAME = 1
+
+
def _decode_crl_distribution_points(backend, cdps):
cdps = backend._ffi.cast("Cryptography_STACK_OF_DIST_POINT *", cdps)
cdps = backend._ffi.gc(cdps, backend._lib.sk_DIST_POINT_free)
@@ -651,7 +655,7 @@ def _decode_crl_distribution_points(backend, cdps):
# point so make sure it's not null.
if cdp.distpoint != backend._ffi.NULL:
# Type 0 is fullName, there is no #define for it in the code.
- if cdp.distpoint.type == 0:
+ if cdp.distpoint.type == _DISTPOINT_TYPE_FULLNAME:
full_name = _decode_general_names(
backend, cdp.distpoint.name.fullname
)
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index ddb50608..45a302ba 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -1781,6 +1781,10 @@ class CertificateBuilder(object):
)
elif isinstance(extension, InhibitAnyPolicy):
extension = Extension(OID_INHIBIT_ANY_POLICY, critical, extension)
+ elif isinstance(extension, CRLDistributionPoints):
+ extension = Extension(
+ OID_CRL_DISTRIBUTION_POINTS, critical, extension
+ )
else:
raise NotImplementedError('Unsupported X.509 extension.')
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 5e0342cb..4e763e36 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -1143,6 +1143,154 @@ class TestCertificateBuilder(object):
with pytest.raises(NotImplementedError):
builder.sign(private_key, hashes.SHA512(), backend)
+ @pytest.mark.parametrize(
+ "cdp",
+ [
+ x509.CRLDistributionPoints([
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=x509.Name([
+ x509.NameAttribute(
+ x509.OID_COMMON_NAME,
+ u"indirect CRL for indirectCRL CA3"
+ ),
+ ]),
+ reasons=None,
+ crl_issuer=[x509.DirectoryName(
+ x509.Name([
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ x509.OID_ORGANIZATION_NAME,
+ u"Test Certificates 2011"
+ ),
+ x509.NameAttribute(
+ x509.OID_ORGANIZATIONAL_UNIT_NAME,
+ u"indirectCRL CA3 cRLIssuer"
+ ),
+ ])
+ )],
+ )
+ ]),
+ x509.CRLDistributionPoints([
+ x509.DistributionPoint(
+ full_name=[x509.DirectoryName(
+ x509.Name([
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+ ])
+ )],
+ relative_name=None,
+ reasons=None,
+ crl_issuer=[x509.DirectoryName(
+ x509.Name([
+ x509.NameAttribute(
+ x509.OID_ORGANIZATION_NAME,
+ u"cryptography Testing"
+ ),
+ ])
+ )],
+ )
+ ]),
+ x509.CRLDistributionPoints([
+ x509.DistributionPoint(
+ full_name=[
+ x509.UniformResourceIdentifier(
+ u"http://myhost.com/myca.crl"
+ ),
+ x509.UniformResourceIdentifier(
+ u"http://backup.myhost.com/myca.crl"
+ )
+ ],
+ relative_name=None,
+ reasons=frozenset([
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise
+ ]),
+ crl_issuer=[x509.DirectoryName(
+ x509.Name([
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+ x509.NameAttribute(
+ x509.OID_COMMON_NAME, u"cryptography CA"
+ ),
+ ])
+ )],
+ )
+ ]),
+ x509.CRLDistributionPoints([
+ x509.DistributionPoint(
+ full_name=[x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )],
+ relative_name=None,
+ reasons=frozenset([
+ x509.ReasonFlags.key_compromise,
+ x509.ReasonFlags.ca_compromise,
+ x509.ReasonFlags.affiliation_changed,
+ x509.ReasonFlags.superseded,
+ x509.ReasonFlags.privilege_withdrawn,
+ x509.ReasonFlags.cessation_of_operation,
+ x509.ReasonFlags.aa_compromise,
+ x509.ReasonFlags.certificate_hold,
+ ]),
+ crl_issuer=None
+ )
+ ]),
+ x509.CRLDistributionPoints([
+ x509.DistributionPoint(
+ full_name=None,
+ relative_name=None,
+ reasons=None,
+ crl_issuer=[x509.DirectoryName(
+ x509.Name([
+ x509.NameAttribute(
+ x509.OID_COMMON_NAME, u"cryptography CA"
+ ),
+ ])
+ )],
+ )
+ ]),
+ x509.CRLDistributionPoints([
+ x509.DistributionPoint(
+ full_name=[x509.UniformResourceIdentifier(
+ u"http://domain.com/some.crl"
+ )],
+ relative_name=None,
+ reasons=frozenset([x509.ReasonFlags.aa_compromise]),
+ crl_issuer=None
+ )
+ ])
+ ]
+ )
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_crl_distribution_points(self, backend, cdp):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = RSA_KEY_2048.private_key(backend)
+
+ builder = x509.CertificateBuilder().serial_number(
+ 4444444
+ ).issuer_name(x509.Name([
+ x509.NameAttribute(x509.OID_LOCALITY_NAME, u'Austin'),
+ ])).subject_name(x509.Name([
+ x509.NameAttribute(x509.OID_LOCALITY_NAME, u'Austin'),
+ ])).public_key(
+ subject_private_key.public_key()
+ ).add_extension(
+ cdp,
+ critical=False,
+ ).not_valid_before(
+ datetime.datetime(2002, 1, 1, 12, 1)
+ ).not_valid_after(
+ datetime.datetime(2030, 12, 31, 8, 30)
+ )
+
+ cert = builder.sign(issuer_private_key, hashes.SHA1(), backend)
+
+ ext = cert.extensions.get_extension_for_oid(
+ x509.OID_CRL_DISTRIBUTION_POINTS
+ )
+ assert ext.critical is False
+ assert ext.value == cdp
+
@pytest.mark.requires_backend_interface(interface=DSABackend)
@pytest.mark.requires_backend_interface(interface=X509Backend)
def test_build_cert_with_dsa_private_key(self, backend):