support revoked certificates in CertificateRevocationListBuilder
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 8d8bda4..e02d4b2 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -788,12 +788,18 @@
         ... ]))
         >>> builder = builder.last_update(datetime.datetime.today())
         >>> builder = builder.next_update(datetime.datetime.today() + one_day)
+        >>> revoked_cert = x509.RevokedCertificateBuilder().serial_number(
+        ...     333
+        ... ).revocation_date(
+        ...     datetime.datetime.today()
+        ... ).build(default_backend())
+        >>> builder = builder.add_revoked_certificate(revoked_cert)
         >>> crl = builder.sign(
         ...     private_key=private_key, algorithm=hashes.SHA256(),
         ...     backend=default_backend()
         ... )
-        >>> isinstance(crl, x509.CertificateRevocationList)
-        True
+        >>> len(crl)
+        1
 
     .. method:: issuer_name(name)
 
@@ -832,6 +838,15 @@
         :param critical: Set to ``True`` if the extension must be understood and
              handled by whoever reads the CRL.
 
+    .. method:: add_revoked_certificate(revoked_certificate)
+
+        Adds a revoked certificate to this CRL.
+
+        :param revoked_certificate: An instance of
+            :class:`~cryptography.x509.RevokedCertificate`. These can be
+            obtained from an existing CRL or created with
+            :class:`~cryptography.x509.RevokedCertificateBuilder`.
+
     .. method:: sign(private_key, algorithm, backend)
 
         Sign this CRL using the CA's private key.
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py
index b58a1a2..eb6dd28 100644
--- a/src/_cffi_src/openssl/x509.py
+++ b/src/_cffi_src/openssl/x509.py
@@ -184,6 +184,7 @@
 ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *);
 
 X509_REVOKED *X509_REVOKED_new(void);
+X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *);
 void X509_REVOKED_free(X509_REVOKED *);
 
 int X509_REVOKED_set_serialNumber(X509_REVOKED *, ASN1_INTEGER *);
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 81316da..295fae1 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -1519,6 +1519,15 @@
             gc=True
         )
 
+        # add revoked certificates
+        for revoked_cert in builder._revoked_certificates:
+            # Duplicating because the X509_CRL takes ownership and will free
+            # this memory when X509_CRL_free is called.
+            revoked = self._lib.X509_REVOKED_dup(revoked_cert._x509_revoked)
+            self.openssl_assert(revoked != self._ffi.NULL)
+            res = self._lib.X509_CRL_add0_revoked(x509_crl, revoked)
+            self.openssl_assert(res == 1)
+
         res = self._lib.X509_CRL_sign(
             x509_crl, private_key._evp_pkey, evp_md
         )
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index e29a310..bc927e8 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -591,6 +591,19 @@
             self._extensions + [extension], self._revoked_certificates
         )
 
+    def add_revoked_certificate(self, revoked_certificate):
+        """
+        Adds a revoked certificate to the CRL.
+        """
+        if not isinstance(revoked_certificate, RevokedCertificate):
+            raise TypeError("Must be an instance of RevokedCertificate")
+
+        return CertificateRevocationListBuilder(
+            self._issuer_name, self._last_update,
+            self._next_update, self._extensions,
+            self._revoked_certificates + [revoked_certificate]
+        )
+
     def sign(self, private_key, algorithm, backend):
         if self._issuer_name is None:
             raise ValueError("A CRL must have an issuer name")
diff --git a/tests/test_x509_crlbuilder.py b/tests/test_x509_crlbuilder.py
index f2db541..de3adcd 100644
--- a/tests/test_x509_crlbuilder.py
+++ b/tests/test_x509_crlbuilder.py
@@ -104,6 +104,12 @@
                 object(), False
             )
 
+    def test_add_invalid_revoked_certificate(self):
+        builder = x509.CertificateRevocationListBuilder()
+
+        with pytest.raises(TypeError):
+            builder.add_revoked_certificate(object())
+
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_no_issuer_name(self, backend):
@@ -338,3 +344,44 @@
 
         with pytest.raises(NotImplementedError):
             builder.sign(private_key, hashes.SHA256(), backend)
+
+    @pytest.mark.requires_backend_interface(interface=RSABackend)
+    @pytest.mark.requires_backend_interface(interface=X509Backend)
+    def test_sign_with_revoked_certificates(self, backend):
+        private_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)
+        revoked_cert0 = x509.RevokedCertificateBuilder().serial_number(
+            38
+        ).revocation_date(
+            datetime.datetime(2011, 1, 1, 1, 1)
+        ).build(backend)
+        revoked_cert1 = x509.RevokedCertificateBuilder().serial_number(
+            2
+        ).revocation_date(
+            datetime.datetime(2012, 1, 1, 1, 1)
+        ).build(backend)
+        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_revoked_certificate(
+            revoked_cert0
+        ).add_revoked_certificate(
+            revoked_cert1
+        )
+
+        crl = builder.sign(private_key, hashes.SHA256(), backend)
+        assert len(crl) == 2
+        assert crl.last_update == last_update
+        assert crl.next_update == next_update
+        assert crl[0].serial_number == revoked_cert0.serial_number
+        assert crl[0].revocation_date == revoked_cert0.revocation_date
+        assert len(crl[0].extensions) == 0
+        assert crl[1].serial_number == revoked_cert1.serial_number
+        assert crl[1].revocation_date == revoked_cert1.revocation_date
+        assert len(crl[1].extensions) == 0