Unverified Commit 5fffb2b2 authored by Josh Robson Chase's avatar Josh Robson Chase
Browse files

Add higher-level bindings to the API CRLs

parent bf20ebeb
Loading
Loading
Loading
Loading
+151 −0
Original line number Diff line number Diff line
@@ -1296,6 +1296,136 @@ impl X509ReqRef {
    }
}

foreign_type_and_impl_send_sync! {
    type CType = ffi::X509_CRL;
    fn drop = ffi::X509_CRL_free;

    /// An `X509` certificate request.
    pub struct X509Crl;
    /// Reference to `X509Crl`.
    pub struct X509CrlRef;
}

impl X509Crl {
    from_pem! {
        /// Deserializes a PEM-encoded Certificate Revocation List
        ///
        /// The input should have a header of `-----BEGIN X509 CRL-----`.
        ///
        /// This corresponds to [`PEM_read_bio_X509_CRL`].
        ///
        /// [`PEM_read_bio_X509_CRL`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509_REQ.html
        from_pem,
        X509Crl,
        ffi::PEM_read_bio_X509_CRL
    }

    from_der! {
        /// Deserializes a DER-encoded Certificate Revocation List
        ///
        /// This corresponds to [`d2i_X509_CRL`].
        ///
        /// [`d2i_X509_CRL`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_X509_REQ.html
        from_der,
        X509Crl,
        ffi::d2i_X509_CRL
    }
}

impl X509CrlRef {
    to_pem! {
        /// Serializes the certificate request to a PEM-encoded Certificate Revocation List.
        ///
        /// The output will have a header of `-----BEGIN X509 CRL-----`.
        ///
        /// This corresponds to [`PEM_write_bio_X509_CRL`].
        ///
        /// [`PEM_write_bio_X509_CRL`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509_REQ.html
        to_pem,
        ffi::PEM_write_bio_X509_CRL
    }

    to_der! {
        /// Serializes the certificate request to a DER-encoded Certificate Revocation List.
        ///
        /// This corresponds to [`i2d_X509_CRL`].
        ///
        /// [`i2d_X509_CRL`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_X509_REQ.html
        to_der,
        ffi::i2d_X509_CRL
    }

    /// Returns the CRL's `lastUpdate` time.
    ///
    /// This corresponds to [`X509_CRL_get0_lastUpdate"]
    ///
    /// [`X509_CRL_get0_lastUpdate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get0_lastUpdate.html
    pub fn last_update(&self) -> &Asn1TimeRef {
        unsafe {
            let date = X509_CRL_get0_lastUpdate(self.as_ptr());
            assert!(!date.is_null());
            Asn1TimeRef::from_ptr(date as *mut _)
        }
    }

    /// Returns the CRL's `nextUpdate` time.
    ///
    /// If the `nextUpdate` field is missing, returns `None`.
    ///
    /// This corresponds to [`X509_CRL_get0_nextUpdate"]
    ///
    /// [`X509_CRL_get0_nextUpdate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get0_nextUpdate.html
    pub fn next_update(&self) -> Option<&Asn1TimeRef> {
        unsafe {
            let date = X509_CRL_get0_nextUpdate(self.as_ptr());
            if date.is_null() {
                None
            } else {
                Some(Asn1TimeRef::from_ptr(date as *mut _))
            }
        }
    }

    /// Check if the provided certificate is in the revocation list.
    pub fn is_revoked(&self, cert: &X509Ref) -> bool {
        unsafe {
            let mut ret = ptr::null_mut::<ffi::X509_REVOKED>();
            ffi::X509_CRL_get0_by_serial(
                self.as_ptr(),
                &mut ret as *mut _,
                cert.serial_number().as_ptr(),
            );
            !ret.is_null()
        }
    }

    /// Get the issuer name from the revocation list.
    pub fn issuer_name(&self) -> &X509NameRef {
        unsafe {
            let name = X509_CRL_get_issuer(self.as_ptr());
            assert!(!name.is_null());
            X509NameRef::from_ptr(name)
        }
    }

    /// Check if the CRL is signed using the given public key.
    ///
    /// Only the signature is checked: no other checks (such as certificate chain validity)
    /// are performed.
    ///
    /// Returns `true` if verification succeeds.
    ///
    /// This corresponds to [`X509_CRL_verify"].
    ///
    /// [`X509_CRL_verify`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_CRL_verify.html
    pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
    where
        T: HasPublic,
    {
        unsafe { cvt_n(ffi::X509_CRL_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
    }
}

/// The result of peer certificate verification.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct X509VerifyResult(c_int);
@@ -1612,3 +1742,24 @@ cfg_if! {
        }
    }
}

cfg_if! {
    if #[cfg(ossl110)] {
        use ffi::{
            X509_CRL_get_issuer, X509_CRL_get0_nextUpdate, X509_CRL_get0_lastUpdate,
        };
    } else {
        #[allow(bad_style)]
        unsafe fn X509_CRL_get0_lastUpdate(x: *const ffi::X509_CRL) -> *mut ffi::ASN1_TIME {
            (*(*x).crl).lastUpdate
        }
        #[allow(bad_style)]
        unsafe fn X509_CRL_get0_nextUpdate(x: *const ffi::X509_CRL) -> *mut ffi::ASN1_TIME {
            (*(*x).crl).nextUpdate
        }
        #[allow(bad_style)]
        unsafe fn X509_CRL_get_issuer(x: *const ffi::X509_CRL) -> *mut ffi::X509_NAME {
            (*(*x).crl).issuer
        }
    }
}