support CRLDistributionPoints in the CertificateBuilder
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 0038ddb..c2f4ba6 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -359,6 +359,95 @@
     return pp, r
 
 
+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:
+            # TODO: determining reason flag is quadratic
+            bitmask = backend._lib.ASN1_BIT_STRING_new()
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask, 1, x509.ReasonFlags.key_compromise in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask, 2, x509.ReasonFlags.ca_compromise in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask,
+                3,
+                x509.ReasonFlags.affiliation_changed in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask, 4, x509.ReasonFlags.superseded in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask,
+                5,
+                x509.ReasonFlags.cessation_of_operation in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask, 6, x509.ReasonFlags.certificate_hold in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask,
+                7,
+                x509.ReasonFlags.privilege_withdrawn in point.reasons
+            )
+            assert res == 1
+            res = backend._lib.ASN1_BIT_STRING_set_bit(
+                bitmask, 8, x509.ReasonFlags.aa_compromise in point.reasons
+            )
+            assert res == 1
+
+            dp.reasons = bitmask
+
+        if point.full_name:
+            # Type 0 is fullName, there is no #define for it in the code.
+            dpn = backend._lib.DIST_POINT_NAME_new()
+            assert dpn != backend._ffi.NULL
+            dpn.type = 0
+            for name in point.full_name:
+                gns = backend._lib.GENERAL_NAMES_new()
+                assert gns != backend._ffi.NULL
+                for name in point.full_name:
+                    gn = _encode_general_name(backend, name)
+                    res = backend._lib.sk_GENERAL_NAME_push(gns, gn)
+                    assert res >= 1
+
+            dpn.name.fullname = gns
+            dp.distpoint = dpn
+
+        if point.relative_name:
+            # TODO: don't duplicate this with fullname above
+            dpn = backend._lib.DIST_POINT_NAME_new()
+            assert dpn != backend._ffi.NULL
+            dpn.name.relativename = _encode_name(backend, point.relative_name)
+            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 +1266,10 @@
                 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/x509.py b/src/cryptography/x509.py
index 08a0c7c..0245fad 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -1780,6 +1780,10 @@
             )
         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 5e0342c..71c29f7 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -1143,6 +1143,124 @@
         with pytest.raises(NotImplementedError):
             builder.sign(private_key, hashes.SHA512(), backend)
 
+    @pytest.mark.parametrize(
+        "cdp",
+        [
+            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"
+                    )],
+                    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):