192f3ab15Sopenharmony_ci//! The standard defining the format of public key certificates.
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! An `X509` certificate binds an identity to a public key, and is either
492f3ab15Sopenharmony_ci//! signed by a certificate authority (CA) or self-signed. An entity that gets
592f3ab15Sopenharmony_ci//! a hold of a certificate can both verify your identity (via a CA) and encrypt
692f3ab15Sopenharmony_ci//! data with the included public key. `X509` certificates are used in many
792f3ab15Sopenharmony_ci//! Internet protocols, including SSL/TLS, which is the basis for HTTPS,
892f3ab15Sopenharmony_ci//! the secure protocol for browsing the web.
992f3ab15Sopenharmony_ci
1092f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
1192f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef, Opaque};
1292f3ab15Sopenharmony_ciuse libc::{c_int, c_long, c_uint, c_void};
1392f3ab15Sopenharmony_ciuse std::cmp::{self, Ordering};
1492f3ab15Sopenharmony_ciuse std::convert::{TryFrom, TryInto};
1592f3ab15Sopenharmony_ciuse std::error::Error;
1692f3ab15Sopenharmony_ciuse std::ffi::{CStr, CString};
1792f3ab15Sopenharmony_ciuse std::fmt;
1892f3ab15Sopenharmony_ciuse std::marker::PhantomData;
1992f3ab15Sopenharmony_ciuse std::mem;
2092f3ab15Sopenharmony_ciuse std::net::IpAddr;
2192f3ab15Sopenharmony_ciuse std::path::Path;
2292f3ab15Sopenharmony_ciuse std::ptr;
2392f3ab15Sopenharmony_ciuse std::slice;
2492f3ab15Sopenharmony_ciuse std::str;
2592f3ab15Sopenharmony_ci
2692f3ab15Sopenharmony_ciuse crate::asn1::{
2792f3ab15Sopenharmony_ci    Asn1BitStringRef, Asn1Enumerated, Asn1IntegerRef, Asn1Object, Asn1ObjectRef,
2892f3ab15Sopenharmony_ci    Asn1OctetStringRef, Asn1StringRef, Asn1TimeRef, Asn1Type,
2992f3ab15Sopenharmony_ci};
3092f3ab15Sopenharmony_ciuse crate::bio::MemBioSlice;
3192f3ab15Sopenharmony_ciuse crate::conf::ConfRef;
3292f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
3392f3ab15Sopenharmony_ciuse crate::ex_data::Index;
3492f3ab15Sopenharmony_ciuse crate::hash::{DigestBytes, MessageDigest};
3592f3ab15Sopenharmony_ciuse crate::nid::Nid;
3692f3ab15Sopenharmony_ciuse crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
3792f3ab15Sopenharmony_ciuse crate::ssl::SslRef;
3892f3ab15Sopenharmony_ciuse crate::stack::{Stack, StackRef, Stackable};
3992f3ab15Sopenharmony_ciuse crate::string::OpensslString;
4092f3ab15Sopenharmony_ciuse crate::util::{ForeignTypeExt, ForeignTypeRefExt};
4192f3ab15Sopenharmony_ciuse crate::{cvt, cvt_n, cvt_p};
4292f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
4392f3ab15Sopenharmony_ci
4492f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))]
4592f3ab15Sopenharmony_cipub mod verify;
4692f3ab15Sopenharmony_ci
4792f3ab15Sopenharmony_cipub mod extension;
4892f3ab15Sopenharmony_cipub mod store;
4992f3ab15Sopenharmony_ci
5092f3ab15Sopenharmony_ci#[cfg(test)]
5192f3ab15Sopenharmony_cimod tests;
5292f3ab15Sopenharmony_ci
5392f3ab15Sopenharmony_ci/// A type of X509 extension.
5492f3ab15Sopenharmony_ci///
5592f3ab15Sopenharmony_ci/// # Safety
5692f3ab15Sopenharmony_ci/// The value of NID and Output must match those in OpenSSL so that
5792f3ab15Sopenharmony_ci/// `Output::from_ptr_opt(*_get_ext_d2i(*, NID, ...))` is valid.
5892f3ab15Sopenharmony_cipub unsafe trait ExtensionType {
5992f3ab15Sopenharmony_ci    const NID: Nid;
6092f3ab15Sopenharmony_ci    type Output: ForeignType;
6192f3ab15Sopenharmony_ci}
6292f3ab15Sopenharmony_ci
6392f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
6492f3ab15Sopenharmony_ci    type CType = ffi::X509_STORE_CTX;
6592f3ab15Sopenharmony_ci    fn drop = ffi::X509_STORE_CTX_free;
6692f3ab15Sopenharmony_ci
6792f3ab15Sopenharmony_ci    /// An `X509` certificate store context.
6892f3ab15Sopenharmony_ci    pub struct X509StoreContext;
6992f3ab15Sopenharmony_ci
7092f3ab15Sopenharmony_ci    /// A reference to an [`X509StoreContext`].
7192f3ab15Sopenharmony_ci    pub struct X509StoreContextRef;
7292f3ab15Sopenharmony_ci}
7392f3ab15Sopenharmony_ci
7492f3ab15Sopenharmony_ciimpl X509StoreContext {
7592f3ab15Sopenharmony_ci    /// Returns the index which can be used to obtain a reference to the `Ssl` associated with a
7692f3ab15Sopenharmony_ci    /// context.
7792f3ab15Sopenharmony_ci    #[corresponds(SSL_get_ex_data_X509_STORE_CTX_idx)]
7892f3ab15Sopenharmony_ci    pub fn ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack> {
7992f3ab15Sopenharmony_ci        unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) }
8092f3ab15Sopenharmony_ci    }
8192f3ab15Sopenharmony_ci
8292f3ab15Sopenharmony_ci    /// Creates a new `X509StoreContext` instance.
8392f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_new)]
8492f3ab15Sopenharmony_ci    pub fn new() -> Result<X509StoreContext, ErrorStack> {
8592f3ab15Sopenharmony_ci        unsafe {
8692f3ab15Sopenharmony_ci            ffi::init();
8792f3ab15Sopenharmony_ci            cvt_p(ffi::X509_STORE_CTX_new()).map(X509StoreContext)
8892f3ab15Sopenharmony_ci        }
8992f3ab15Sopenharmony_ci    }
9092f3ab15Sopenharmony_ci}
9192f3ab15Sopenharmony_ci
9292f3ab15Sopenharmony_ciimpl X509StoreContextRef {
9392f3ab15Sopenharmony_ci    /// Returns application data pertaining to an `X509` store context.
9492f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_get_ex_data)]
9592f3ab15Sopenharmony_ci    pub fn ex_data<T>(&self, index: Index<X509StoreContext, T>) -> Option<&T> {
9692f3ab15Sopenharmony_ci        unsafe {
9792f3ab15Sopenharmony_ci            let data = ffi::X509_STORE_CTX_get_ex_data(self.as_ptr(), index.as_raw());
9892f3ab15Sopenharmony_ci            if data.is_null() {
9992f3ab15Sopenharmony_ci                None
10092f3ab15Sopenharmony_ci            } else {
10192f3ab15Sopenharmony_ci                Some(&*(data as *const T))
10292f3ab15Sopenharmony_ci            }
10392f3ab15Sopenharmony_ci        }
10492f3ab15Sopenharmony_ci    }
10592f3ab15Sopenharmony_ci
10692f3ab15Sopenharmony_ci    /// Returns the error code of the context.
10792f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_get_error)]
10892f3ab15Sopenharmony_ci    pub fn error(&self) -> X509VerifyResult {
10992f3ab15Sopenharmony_ci        unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) }
11092f3ab15Sopenharmony_ci    }
11192f3ab15Sopenharmony_ci
11292f3ab15Sopenharmony_ci    /// Initializes this context with the given certificate, certificates chain and certificate
11392f3ab15Sopenharmony_ci    /// store. After initializing the context, the `with_context` closure is called with the prepared
11492f3ab15Sopenharmony_ci    /// context. As long as the closure is running, the context stays initialized and can be used
11592f3ab15Sopenharmony_ci    /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished.
11692f3ab15Sopenharmony_ci    ///
11792f3ab15Sopenharmony_ci    /// * `trust` - The certificate store with the trusted certificates.
11892f3ab15Sopenharmony_ci    /// * `cert` - The certificate that should be verified.
11992f3ab15Sopenharmony_ci    /// * `cert_chain` - The certificates chain.
12092f3ab15Sopenharmony_ci    /// * `with_context` - The closure that is called with the initialized context.
12192f3ab15Sopenharmony_ci    ///
12292f3ab15Sopenharmony_ci    /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to
12392f3ab15Sopenharmony_ci    /// [`X509_STORE_CTX_cleanup`] after calling `with_context`.
12492f3ab15Sopenharmony_ci    ///
12592f3ab15Sopenharmony_ci    /// [`X509_STORE_CTX_init`]:  https://www.openssl.org/docs/manmaster/crypto/X509_STORE_CTX_init.html
12692f3ab15Sopenharmony_ci    /// [`X509_STORE_CTX_cleanup`]:  https://www.openssl.org/docs/manmaster/crypto/X509_STORE_CTX_cleanup.html
12792f3ab15Sopenharmony_ci    pub fn init<F, T>(
12892f3ab15Sopenharmony_ci        &mut self,
12992f3ab15Sopenharmony_ci        trust: &store::X509StoreRef,
13092f3ab15Sopenharmony_ci        cert: &X509Ref,
13192f3ab15Sopenharmony_ci        cert_chain: &StackRef<X509>,
13292f3ab15Sopenharmony_ci        with_context: F,
13392f3ab15Sopenharmony_ci    ) -> Result<T, ErrorStack>
13492f3ab15Sopenharmony_ci    where
13592f3ab15Sopenharmony_ci        F: FnOnce(&mut X509StoreContextRef) -> Result<T, ErrorStack>,
13692f3ab15Sopenharmony_ci    {
13792f3ab15Sopenharmony_ci        struct Cleanup<'a>(&'a mut X509StoreContextRef);
13892f3ab15Sopenharmony_ci
13992f3ab15Sopenharmony_ci        impl<'a> Drop for Cleanup<'a> {
14092f3ab15Sopenharmony_ci            fn drop(&mut self) {
14192f3ab15Sopenharmony_ci                unsafe {
14292f3ab15Sopenharmony_ci                    ffi::X509_STORE_CTX_cleanup(self.0.as_ptr());
14392f3ab15Sopenharmony_ci                }
14492f3ab15Sopenharmony_ci            }
14592f3ab15Sopenharmony_ci        }
14692f3ab15Sopenharmony_ci
14792f3ab15Sopenharmony_ci        unsafe {
14892f3ab15Sopenharmony_ci            cvt(ffi::X509_STORE_CTX_init(
14992f3ab15Sopenharmony_ci                self.as_ptr(),
15092f3ab15Sopenharmony_ci                trust.as_ptr(),
15192f3ab15Sopenharmony_ci                cert.as_ptr(),
15292f3ab15Sopenharmony_ci                cert_chain.as_ptr(),
15392f3ab15Sopenharmony_ci            ))?;
15492f3ab15Sopenharmony_ci
15592f3ab15Sopenharmony_ci            let cleanup = Cleanup(self);
15692f3ab15Sopenharmony_ci            with_context(cleanup.0)
15792f3ab15Sopenharmony_ci        }
15892f3ab15Sopenharmony_ci    }
15992f3ab15Sopenharmony_ci
16092f3ab15Sopenharmony_ci    /// Verifies the stored certificate.
16192f3ab15Sopenharmony_ci    ///
16292f3ab15Sopenharmony_ci    /// Returns `true` if verification succeeds. The `error` method will return the specific
16392f3ab15Sopenharmony_ci    /// validation error if the certificate was not valid.
16492f3ab15Sopenharmony_ci    ///
16592f3ab15Sopenharmony_ci    /// This will only work inside of a call to `init`.
16692f3ab15Sopenharmony_ci    #[corresponds(X509_verify_cert)]
16792f3ab15Sopenharmony_ci    pub fn verify_cert(&mut self) -> Result<bool, ErrorStack> {
16892f3ab15Sopenharmony_ci        unsafe { cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0) }
16992f3ab15Sopenharmony_ci    }
17092f3ab15Sopenharmony_ci
17192f3ab15Sopenharmony_ci    /// Set the error code of the context.
17292f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_set_error)]
17392f3ab15Sopenharmony_ci    pub fn set_error(&mut self, result: X509VerifyResult) {
17492f3ab15Sopenharmony_ci        unsafe {
17592f3ab15Sopenharmony_ci            ffi::X509_STORE_CTX_set_error(self.as_ptr(), result.as_raw());
17692f3ab15Sopenharmony_ci        }
17792f3ab15Sopenharmony_ci    }
17892f3ab15Sopenharmony_ci
17992f3ab15Sopenharmony_ci    /// Returns a reference to the certificate which caused the error or None if
18092f3ab15Sopenharmony_ci    /// no certificate is relevant to the error.
18192f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_get_current_cert)]
18292f3ab15Sopenharmony_ci    pub fn current_cert(&self) -> Option<&X509Ref> {
18392f3ab15Sopenharmony_ci        unsafe {
18492f3ab15Sopenharmony_ci            let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr());
18592f3ab15Sopenharmony_ci            X509Ref::from_const_ptr_opt(ptr)
18692f3ab15Sopenharmony_ci        }
18792f3ab15Sopenharmony_ci    }
18892f3ab15Sopenharmony_ci
18992f3ab15Sopenharmony_ci    /// Returns a non-negative integer representing the depth in the certificate
19092f3ab15Sopenharmony_ci    /// chain where the error occurred. If it is zero it occurred in the end
19192f3ab15Sopenharmony_ci    /// entity certificate, one if it is the certificate which signed the end
19292f3ab15Sopenharmony_ci    /// entity certificate and so on.
19392f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_get_error_depth)]
19492f3ab15Sopenharmony_ci    pub fn error_depth(&self) -> u32 {
19592f3ab15Sopenharmony_ci        unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 }
19692f3ab15Sopenharmony_ci    }
19792f3ab15Sopenharmony_ci
19892f3ab15Sopenharmony_ci    /// Returns a reference to a complete valid `X509` certificate chain.
19992f3ab15Sopenharmony_ci    #[corresponds(X509_STORE_CTX_get0_chain)]
20092f3ab15Sopenharmony_ci    pub fn chain(&self) -> Option<&StackRef<X509>> {
20192f3ab15Sopenharmony_ci        unsafe {
20292f3ab15Sopenharmony_ci            let chain = X509_STORE_CTX_get0_chain(self.as_ptr());
20392f3ab15Sopenharmony_ci
20492f3ab15Sopenharmony_ci            if chain.is_null() {
20592f3ab15Sopenharmony_ci                None
20692f3ab15Sopenharmony_ci            } else {
20792f3ab15Sopenharmony_ci                Some(StackRef::from_ptr(chain))
20892f3ab15Sopenharmony_ci            }
20992f3ab15Sopenharmony_ci        }
21092f3ab15Sopenharmony_ci    }
21192f3ab15Sopenharmony_ci}
21292f3ab15Sopenharmony_ci
21392f3ab15Sopenharmony_ci/// A builder used to construct an `X509`.
21492f3ab15Sopenharmony_cipub struct X509Builder(X509);
21592f3ab15Sopenharmony_ci
21692f3ab15Sopenharmony_ciimpl X509Builder {
21792f3ab15Sopenharmony_ci    /// Creates a new builder.
21892f3ab15Sopenharmony_ci    #[corresponds(X509_new)]
21992f3ab15Sopenharmony_ci    pub fn new() -> Result<X509Builder, ErrorStack> {
22092f3ab15Sopenharmony_ci        unsafe {
22192f3ab15Sopenharmony_ci            ffi::init();
22292f3ab15Sopenharmony_ci            cvt_p(ffi::X509_new()).map(|p| X509Builder(X509(p)))
22392f3ab15Sopenharmony_ci        }
22492f3ab15Sopenharmony_ci    }
22592f3ab15Sopenharmony_ci
22692f3ab15Sopenharmony_ci    /// Sets the notAfter constraint on the certificate.
22792f3ab15Sopenharmony_ci    #[corresponds(X509_set1_notAfter)]
22892f3ab15Sopenharmony_ci    pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
22992f3ab15Sopenharmony_ci        unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
23092f3ab15Sopenharmony_ci    }
23192f3ab15Sopenharmony_ci
23292f3ab15Sopenharmony_ci    /// Sets the notBefore constraint on the certificate.
23392f3ab15Sopenharmony_ci    #[corresponds(X509_set1_notBefore)]
23492f3ab15Sopenharmony_ci    pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
23592f3ab15Sopenharmony_ci        unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
23692f3ab15Sopenharmony_ci    }
23792f3ab15Sopenharmony_ci
23892f3ab15Sopenharmony_ci    /// Sets the version of the certificate.
23992f3ab15Sopenharmony_ci    ///
24092f3ab15Sopenharmony_ci    /// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of
24192f3ab15Sopenharmony_ci    /// the X.509 standard should pass `2` to this method.
24292f3ab15Sopenharmony_ci    #[corresponds(X509_set_version)]
24392f3ab15Sopenharmony_ci    #[allow(clippy::useless_conversion)]
24492f3ab15Sopenharmony_ci    pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
24592f3ab15Sopenharmony_ci        unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version as c_long)).map(|_| ()) }
24692f3ab15Sopenharmony_ci    }
24792f3ab15Sopenharmony_ci
24892f3ab15Sopenharmony_ci    /// Sets the serial number of the certificate.
24992f3ab15Sopenharmony_ci    #[corresponds(X509_set_serialNumber)]
25092f3ab15Sopenharmony_ci    pub fn set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack> {
25192f3ab15Sopenharmony_ci        unsafe {
25292f3ab15Sopenharmony_ci            cvt(ffi::X509_set_serialNumber(
25392f3ab15Sopenharmony_ci                self.0.as_ptr(),
25492f3ab15Sopenharmony_ci                serial_number.as_ptr(),
25592f3ab15Sopenharmony_ci            ))
25692f3ab15Sopenharmony_ci            .map(|_| ())
25792f3ab15Sopenharmony_ci        }
25892f3ab15Sopenharmony_ci    }
25992f3ab15Sopenharmony_ci
26092f3ab15Sopenharmony_ci    /// Sets the issuer name of the certificate.
26192f3ab15Sopenharmony_ci    #[corresponds(X509_set_issuer_name)]
26292f3ab15Sopenharmony_ci    pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> {
26392f3ab15Sopenharmony_ci        unsafe {
26492f3ab15Sopenharmony_ci            cvt(ffi::X509_set_issuer_name(
26592f3ab15Sopenharmony_ci                self.0.as_ptr(),
26692f3ab15Sopenharmony_ci                issuer_name.as_ptr(),
26792f3ab15Sopenharmony_ci            ))
26892f3ab15Sopenharmony_ci            .map(|_| ())
26992f3ab15Sopenharmony_ci        }
27092f3ab15Sopenharmony_ci    }
27192f3ab15Sopenharmony_ci
27292f3ab15Sopenharmony_ci    /// Sets the subject name of the certificate.
27392f3ab15Sopenharmony_ci    ///
27492f3ab15Sopenharmony_ci    /// When building certificates, the `C`, `ST`, and `O` options are common when using the openssl command line tools.
27592f3ab15Sopenharmony_ci    /// The `CN` field is used for the common name, such as a DNS name.
27692f3ab15Sopenharmony_ci    ///
27792f3ab15Sopenharmony_ci    /// ```
27892f3ab15Sopenharmony_ci    /// use openssl::x509::{X509, X509NameBuilder};
27992f3ab15Sopenharmony_ci    ///
28092f3ab15Sopenharmony_ci    /// let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap();
28192f3ab15Sopenharmony_ci    /// x509_name.append_entry_by_text("C", "US").unwrap();
28292f3ab15Sopenharmony_ci    /// x509_name.append_entry_by_text("ST", "CA").unwrap();
28392f3ab15Sopenharmony_ci    /// x509_name.append_entry_by_text("O", "Some organization").unwrap();
28492f3ab15Sopenharmony_ci    /// x509_name.append_entry_by_text("CN", "www.example.com").unwrap();
28592f3ab15Sopenharmony_ci    /// let x509_name = x509_name.build();
28692f3ab15Sopenharmony_ci    ///
28792f3ab15Sopenharmony_ci    /// let mut x509 = openssl::x509::X509::builder().unwrap();
28892f3ab15Sopenharmony_ci    /// x509.set_subject_name(&x509_name).unwrap();
28992f3ab15Sopenharmony_ci    /// ```
29092f3ab15Sopenharmony_ci    #[corresponds(X509_set_subject_name)]
29192f3ab15Sopenharmony_ci    pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
29292f3ab15Sopenharmony_ci        unsafe {
29392f3ab15Sopenharmony_ci            cvt(ffi::X509_set_subject_name(
29492f3ab15Sopenharmony_ci                self.0.as_ptr(),
29592f3ab15Sopenharmony_ci                subject_name.as_ptr(),
29692f3ab15Sopenharmony_ci            ))
29792f3ab15Sopenharmony_ci            .map(|_| ())
29892f3ab15Sopenharmony_ci        }
29992f3ab15Sopenharmony_ci    }
30092f3ab15Sopenharmony_ci
30192f3ab15Sopenharmony_ci    /// Sets the public key associated with the certificate.
30292f3ab15Sopenharmony_ci    #[corresponds(X509_set_pubkey)]
30392f3ab15Sopenharmony_ci    pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
30492f3ab15Sopenharmony_ci    where
30592f3ab15Sopenharmony_ci        T: HasPublic,
30692f3ab15Sopenharmony_ci    {
30792f3ab15Sopenharmony_ci        unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
30892f3ab15Sopenharmony_ci    }
30992f3ab15Sopenharmony_ci
31092f3ab15Sopenharmony_ci    /// Returns a context object which is needed to create certain X509 extension values.
31192f3ab15Sopenharmony_ci    ///
31292f3ab15Sopenharmony_ci    /// Set `issuer` to `None` if the certificate will be self-signed.
31392f3ab15Sopenharmony_ci    #[corresponds(X509V3_set_ctx)]
31492f3ab15Sopenharmony_ci    pub fn x509v3_context<'a>(
31592f3ab15Sopenharmony_ci        &'a self,
31692f3ab15Sopenharmony_ci        issuer: Option<&'a X509Ref>,
31792f3ab15Sopenharmony_ci        conf: Option<&'a ConfRef>,
31892f3ab15Sopenharmony_ci    ) -> X509v3Context<'a> {
31992f3ab15Sopenharmony_ci        unsafe {
32092f3ab15Sopenharmony_ci            let mut ctx = mem::zeroed();
32192f3ab15Sopenharmony_ci
32292f3ab15Sopenharmony_ci            let issuer = match issuer {
32392f3ab15Sopenharmony_ci                Some(issuer) => issuer.as_ptr(),
32492f3ab15Sopenharmony_ci                None => self.0.as_ptr(),
32592f3ab15Sopenharmony_ci            };
32692f3ab15Sopenharmony_ci            let subject = self.0.as_ptr();
32792f3ab15Sopenharmony_ci            ffi::X509V3_set_ctx(
32892f3ab15Sopenharmony_ci                &mut ctx,
32992f3ab15Sopenharmony_ci                issuer,
33092f3ab15Sopenharmony_ci                subject,
33192f3ab15Sopenharmony_ci                ptr::null_mut(),
33292f3ab15Sopenharmony_ci                ptr::null_mut(),
33392f3ab15Sopenharmony_ci                0,
33492f3ab15Sopenharmony_ci            );
33592f3ab15Sopenharmony_ci
33692f3ab15Sopenharmony_ci            // nodb case taken care of since we zeroed ctx above
33792f3ab15Sopenharmony_ci            if let Some(conf) = conf {
33892f3ab15Sopenharmony_ci                ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr());
33992f3ab15Sopenharmony_ci            }
34092f3ab15Sopenharmony_ci
34192f3ab15Sopenharmony_ci            X509v3Context(ctx, PhantomData)
34292f3ab15Sopenharmony_ci        }
34392f3ab15Sopenharmony_ci    }
34492f3ab15Sopenharmony_ci
34592f3ab15Sopenharmony_ci    /// Adds an X509 extension value to the certificate.
34692f3ab15Sopenharmony_ci    ///
34792f3ab15Sopenharmony_ci    /// This works just as `append_extension` except it takes ownership of the `X509Extension`.
34892f3ab15Sopenharmony_ci    pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> {
34992f3ab15Sopenharmony_ci        self.append_extension2(&extension)
35092f3ab15Sopenharmony_ci    }
35192f3ab15Sopenharmony_ci
35292f3ab15Sopenharmony_ci    /// Adds an X509 extension value to the certificate.
35392f3ab15Sopenharmony_ci    #[corresponds(X509_add_ext)]
35492f3ab15Sopenharmony_ci    pub fn append_extension2(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack> {
35592f3ab15Sopenharmony_ci        unsafe {
35692f3ab15Sopenharmony_ci            cvt(ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1))?;
35792f3ab15Sopenharmony_ci            Ok(())
35892f3ab15Sopenharmony_ci        }
35992f3ab15Sopenharmony_ci    }
36092f3ab15Sopenharmony_ci
36192f3ab15Sopenharmony_ci    /// Signs the certificate with a private key.
36292f3ab15Sopenharmony_ci    #[corresponds(X509_sign)]
36392f3ab15Sopenharmony_ci    pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
36492f3ab15Sopenharmony_ci    where
36592f3ab15Sopenharmony_ci        T: HasPrivate,
36692f3ab15Sopenharmony_ci    {
36792f3ab15Sopenharmony_ci        unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) }
36892f3ab15Sopenharmony_ci    }
36992f3ab15Sopenharmony_ci
37092f3ab15Sopenharmony_ci    /// Consumes the builder, returning the certificate.
37192f3ab15Sopenharmony_ci    pub fn build(self) -> X509 {
37292f3ab15Sopenharmony_ci        self.0
37392f3ab15Sopenharmony_ci    }
37492f3ab15Sopenharmony_ci}
37592f3ab15Sopenharmony_ci
37692f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
37792f3ab15Sopenharmony_ci    type CType = ffi::X509;
37892f3ab15Sopenharmony_ci    fn drop = ffi::X509_free;
37992f3ab15Sopenharmony_ci
38092f3ab15Sopenharmony_ci    /// An `X509` public key certificate.
38192f3ab15Sopenharmony_ci    pub struct X509;
38292f3ab15Sopenharmony_ci    /// Reference to `X509`.
38392f3ab15Sopenharmony_ci    pub struct X509Ref;
38492f3ab15Sopenharmony_ci}
38592f3ab15Sopenharmony_ci
38692f3ab15Sopenharmony_ci#[cfg(boringssl)]
38792f3ab15Sopenharmony_citype X509LenTy = c_uint;
38892f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
38992f3ab15Sopenharmony_citype X509LenTy = c_int;
39092f3ab15Sopenharmony_ci
39192f3ab15Sopenharmony_ciimpl X509Ref {
39292f3ab15Sopenharmony_ci    /// Returns this certificate's subject name.
39392f3ab15Sopenharmony_ci    #[corresponds(X509_get_subject_name)]
39492f3ab15Sopenharmony_ci    pub fn subject_name(&self) -> &X509NameRef {
39592f3ab15Sopenharmony_ci        unsafe {
39692f3ab15Sopenharmony_ci            let name = ffi::X509_get_subject_name(self.as_ptr());
39792f3ab15Sopenharmony_ci            X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null")
39892f3ab15Sopenharmony_ci        }
39992f3ab15Sopenharmony_ci    }
40092f3ab15Sopenharmony_ci
40192f3ab15Sopenharmony_ci    /// Returns the hash of the certificates subject
40292f3ab15Sopenharmony_ci    #[corresponds(X509_subject_name_hash)]
40392f3ab15Sopenharmony_ci    pub fn subject_name_hash(&self) -> u32 {
40492f3ab15Sopenharmony_ci        #[allow(clippy::unnecessary_cast)]
40592f3ab15Sopenharmony_ci        unsafe {
40692f3ab15Sopenharmony_ci            ffi::X509_subject_name_hash(self.as_ptr()) as u32
40792f3ab15Sopenharmony_ci        }
40892f3ab15Sopenharmony_ci    }
40992f3ab15Sopenharmony_ci
41092f3ab15Sopenharmony_ci    /// Returns this certificate's issuer name.
41192f3ab15Sopenharmony_ci    #[corresponds(X509_get_issuer_name)]
41292f3ab15Sopenharmony_ci    pub fn issuer_name(&self) -> &X509NameRef {
41392f3ab15Sopenharmony_ci        unsafe {
41492f3ab15Sopenharmony_ci            let name = ffi::X509_get_issuer_name(self.as_ptr());
41592f3ab15Sopenharmony_ci            X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null")
41692f3ab15Sopenharmony_ci        }
41792f3ab15Sopenharmony_ci    }
41892f3ab15Sopenharmony_ci
41992f3ab15Sopenharmony_ci    /// Returns the hash of the certificates issuer
42092f3ab15Sopenharmony_ci    #[corresponds(X509_issuer_name_hash)]
42192f3ab15Sopenharmony_ci    pub fn issuer_name_hash(&self) -> u32 {
42292f3ab15Sopenharmony_ci        #[allow(clippy::unnecessary_cast)]
42392f3ab15Sopenharmony_ci        unsafe {
42492f3ab15Sopenharmony_ci            ffi::X509_issuer_name_hash(self.as_ptr()) as u32
42592f3ab15Sopenharmony_ci        }
42692f3ab15Sopenharmony_ci    }
42792f3ab15Sopenharmony_ci
42892f3ab15Sopenharmony_ci    /// Returns this certificate's subject alternative name entries, if they exist.
42992f3ab15Sopenharmony_ci    #[corresponds(X509_get_ext_d2i)]
43092f3ab15Sopenharmony_ci    pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> {
43192f3ab15Sopenharmony_ci        unsafe {
43292f3ab15Sopenharmony_ci            let stack = ffi::X509_get_ext_d2i(
43392f3ab15Sopenharmony_ci                self.as_ptr(),
43492f3ab15Sopenharmony_ci                ffi::NID_subject_alt_name,
43592f3ab15Sopenharmony_ci                ptr::null_mut(),
43692f3ab15Sopenharmony_ci                ptr::null_mut(),
43792f3ab15Sopenharmony_ci            );
43892f3ab15Sopenharmony_ci            Stack::from_ptr_opt(stack as *mut _)
43992f3ab15Sopenharmony_ci        }
44092f3ab15Sopenharmony_ci    }
44192f3ab15Sopenharmony_ci
44292f3ab15Sopenharmony_ci    /// Returns this certificate's CRL distribution points, if they exist.
44392f3ab15Sopenharmony_ci    #[corresponds(X509_get_ext_d2i)]
44492f3ab15Sopenharmony_ci    pub fn crl_distribution_points(&self) -> Option<Stack<DistPoint>> {
44592f3ab15Sopenharmony_ci        unsafe {
44692f3ab15Sopenharmony_ci            let stack = ffi::X509_get_ext_d2i(
44792f3ab15Sopenharmony_ci                self.as_ptr(),
44892f3ab15Sopenharmony_ci                ffi::NID_crl_distribution_points,
44992f3ab15Sopenharmony_ci                ptr::null_mut(),
45092f3ab15Sopenharmony_ci                ptr::null_mut(),
45192f3ab15Sopenharmony_ci            );
45292f3ab15Sopenharmony_ci            Stack::from_ptr_opt(stack as *mut _)
45392f3ab15Sopenharmony_ci        }
45492f3ab15Sopenharmony_ci    }
45592f3ab15Sopenharmony_ci
45692f3ab15Sopenharmony_ci    /// Returns this certificate's issuer alternative name entries, if they exist.
45792f3ab15Sopenharmony_ci    #[corresponds(X509_get_ext_d2i)]
45892f3ab15Sopenharmony_ci    pub fn issuer_alt_names(&self) -> Option<Stack<GeneralName>> {
45992f3ab15Sopenharmony_ci        unsafe {
46092f3ab15Sopenharmony_ci            let stack = ffi::X509_get_ext_d2i(
46192f3ab15Sopenharmony_ci                self.as_ptr(),
46292f3ab15Sopenharmony_ci                ffi::NID_issuer_alt_name,
46392f3ab15Sopenharmony_ci                ptr::null_mut(),
46492f3ab15Sopenharmony_ci                ptr::null_mut(),
46592f3ab15Sopenharmony_ci            );
46692f3ab15Sopenharmony_ci            Stack::from_ptr_opt(stack as *mut _)
46792f3ab15Sopenharmony_ci        }
46892f3ab15Sopenharmony_ci    }
46992f3ab15Sopenharmony_ci
47092f3ab15Sopenharmony_ci    /// Returns this certificate's [`authority information access`] entries, if they exist.
47192f3ab15Sopenharmony_ci    ///
47292f3ab15Sopenharmony_ci    /// [`authority information access`]: https://tools.ietf.org/html/rfc5280#section-4.2.2.1
47392f3ab15Sopenharmony_ci    #[corresponds(X509_get_ext_d2i)]
47492f3ab15Sopenharmony_ci    pub fn authority_info(&self) -> Option<Stack<AccessDescription>> {
47592f3ab15Sopenharmony_ci        unsafe {
47692f3ab15Sopenharmony_ci            let stack = ffi::X509_get_ext_d2i(
47792f3ab15Sopenharmony_ci                self.as_ptr(),
47892f3ab15Sopenharmony_ci                ffi::NID_info_access,
47992f3ab15Sopenharmony_ci                ptr::null_mut(),
48092f3ab15Sopenharmony_ci                ptr::null_mut(),
48192f3ab15Sopenharmony_ci            );
48292f3ab15Sopenharmony_ci            Stack::from_ptr_opt(stack as *mut _)
48392f3ab15Sopenharmony_ci        }
48492f3ab15Sopenharmony_ci    }
48592f3ab15Sopenharmony_ci
48692f3ab15Sopenharmony_ci    /// Retrieves the path length extension from a certificate, if it exists.
48792f3ab15Sopenharmony_ci    #[corresponds(X509_get_pathlen)]
48892f3ab15Sopenharmony_ci    #[cfg(ossl110)]
48992f3ab15Sopenharmony_ci    pub fn pathlen(&self) -> Option<u32> {
49092f3ab15Sopenharmony_ci        let v = unsafe { ffi::X509_get_pathlen(self.as_ptr()) };
49192f3ab15Sopenharmony_ci        u32::try_from(v).ok()
49292f3ab15Sopenharmony_ci    }
49392f3ab15Sopenharmony_ci
49492f3ab15Sopenharmony_ci    /// Returns this certificate's subject key id, if it exists.
49592f3ab15Sopenharmony_ci    #[corresponds(X509_get0_subject_key_id)]
49692f3ab15Sopenharmony_ci    #[cfg(ossl110)]
49792f3ab15Sopenharmony_ci    pub fn subject_key_id(&self) -> Option<&Asn1OctetStringRef> {
49892f3ab15Sopenharmony_ci        unsafe {
49992f3ab15Sopenharmony_ci            let data = ffi::X509_get0_subject_key_id(self.as_ptr());
50092f3ab15Sopenharmony_ci            Asn1OctetStringRef::from_const_ptr_opt(data)
50192f3ab15Sopenharmony_ci        }
50292f3ab15Sopenharmony_ci    }
50392f3ab15Sopenharmony_ci
50492f3ab15Sopenharmony_ci    /// Returns this certificate's authority key id, if it exists.
50592f3ab15Sopenharmony_ci    #[corresponds(X509_get0_authority_key_id)]
50692f3ab15Sopenharmony_ci    #[cfg(ossl110)]
50792f3ab15Sopenharmony_ci    pub fn authority_key_id(&self) -> Option<&Asn1OctetStringRef> {
50892f3ab15Sopenharmony_ci        unsafe {
50992f3ab15Sopenharmony_ci            let data = ffi::X509_get0_authority_key_id(self.as_ptr());
51092f3ab15Sopenharmony_ci            Asn1OctetStringRef::from_const_ptr_opt(data)
51192f3ab15Sopenharmony_ci        }
51292f3ab15Sopenharmony_ci    }
51392f3ab15Sopenharmony_ci
51492f3ab15Sopenharmony_ci    /// Returns this certificate's authority issuer name entries, if they exist.
51592f3ab15Sopenharmony_ci    #[corresponds(X509_get0_authority_issuer)]
51692f3ab15Sopenharmony_ci    #[cfg(ossl111d)]
51792f3ab15Sopenharmony_ci    pub fn authority_issuer(&self) -> Option<&StackRef<GeneralName>> {
51892f3ab15Sopenharmony_ci        unsafe {
51992f3ab15Sopenharmony_ci            let stack = ffi::X509_get0_authority_issuer(self.as_ptr());
52092f3ab15Sopenharmony_ci            StackRef::from_const_ptr_opt(stack)
52192f3ab15Sopenharmony_ci        }
52292f3ab15Sopenharmony_ci    }
52392f3ab15Sopenharmony_ci
52492f3ab15Sopenharmony_ci    /// Returns this certificate's authority serial number, if it exists.
52592f3ab15Sopenharmony_ci    #[corresponds(X509_get0_authority_serial)]
52692f3ab15Sopenharmony_ci    #[cfg(ossl111d)]
52792f3ab15Sopenharmony_ci    pub fn authority_serial(&self) -> Option<&Asn1IntegerRef> {
52892f3ab15Sopenharmony_ci        unsafe {
52992f3ab15Sopenharmony_ci            let r = ffi::X509_get0_authority_serial(self.as_ptr());
53092f3ab15Sopenharmony_ci            Asn1IntegerRef::from_const_ptr_opt(r)
53192f3ab15Sopenharmony_ci        }
53292f3ab15Sopenharmony_ci    }
53392f3ab15Sopenharmony_ci
53492f3ab15Sopenharmony_ci    #[corresponds(X509_get_pubkey)]
53592f3ab15Sopenharmony_ci    pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
53692f3ab15Sopenharmony_ci        unsafe {
53792f3ab15Sopenharmony_ci            let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?;
53892f3ab15Sopenharmony_ci            Ok(PKey::from_ptr(pkey))
53992f3ab15Sopenharmony_ci        }
54092f3ab15Sopenharmony_ci    }
54192f3ab15Sopenharmony_ci
54292f3ab15Sopenharmony_ci    /// Returns a digest of the DER representation of the certificate.
54392f3ab15Sopenharmony_ci    #[corresponds(X509_digest)]
54492f3ab15Sopenharmony_ci    pub fn digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack> {
54592f3ab15Sopenharmony_ci        unsafe {
54692f3ab15Sopenharmony_ci            let mut digest = DigestBytes {
54792f3ab15Sopenharmony_ci                buf: [0; ffi::EVP_MAX_MD_SIZE as usize],
54892f3ab15Sopenharmony_ci                len: ffi::EVP_MAX_MD_SIZE as usize,
54992f3ab15Sopenharmony_ci            };
55092f3ab15Sopenharmony_ci            let mut len = ffi::EVP_MAX_MD_SIZE as c_uint;
55192f3ab15Sopenharmony_ci            cvt(ffi::X509_digest(
55292f3ab15Sopenharmony_ci                self.as_ptr(),
55392f3ab15Sopenharmony_ci                hash_type.as_ptr(),
55492f3ab15Sopenharmony_ci                digest.buf.as_mut_ptr() as *mut _,
55592f3ab15Sopenharmony_ci                &mut len,
55692f3ab15Sopenharmony_ci            ))?;
55792f3ab15Sopenharmony_ci            digest.len = len as usize;
55892f3ab15Sopenharmony_ci
55992f3ab15Sopenharmony_ci            Ok(digest)
56092f3ab15Sopenharmony_ci        }
56192f3ab15Sopenharmony_ci    }
56292f3ab15Sopenharmony_ci
56392f3ab15Sopenharmony_ci    #[deprecated(since = "0.10.9", note = "renamed to digest")]
56492f3ab15Sopenharmony_ci    pub fn fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack> {
56592f3ab15Sopenharmony_ci        self.digest(hash_type).map(|b| b.to_vec())
56692f3ab15Sopenharmony_ci    }
56792f3ab15Sopenharmony_ci
56892f3ab15Sopenharmony_ci    /// Returns the certificate's Not After validity period.
56992f3ab15Sopenharmony_ci    #[corresponds(X509_getm_notAfter)]
57092f3ab15Sopenharmony_ci    pub fn not_after(&self) -> &Asn1TimeRef {
57192f3ab15Sopenharmony_ci        unsafe {
57292f3ab15Sopenharmony_ci            let date = X509_getm_notAfter(self.as_ptr());
57392f3ab15Sopenharmony_ci            Asn1TimeRef::from_const_ptr_opt(date).expect("not_after must not be null")
57492f3ab15Sopenharmony_ci        }
57592f3ab15Sopenharmony_ci    }
57692f3ab15Sopenharmony_ci
57792f3ab15Sopenharmony_ci    /// Returns the certificate's Not Before validity period.
57892f3ab15Sopenharmony_ci    #[corresponds(X509_getm_notBefore)]
57992f3ab15Sopenharmony_ci    pub fn not_before(&self) -> &Asn1TimeRef {
58092f3ab15Sopenharmony_ci        unsafe {
58192f3ab15Sopenharmony_ci            let date = X509_getm_notBefore(self.as_ptr());
58292f3ab15Sopenharmony_ci            Asn1TimeRef::from_const_ptr_opt(date).expect("not_before must not be null")
58392f3ab15Sopenharmony_ci        }
58492f3ab15Sopenharmony_ci    }
58592f3ab15Sopenharmony_ci
58692f3ab15Sopenharmony_ci    /// Returns the certificate's signature
58792f3ab15Sopenharmony_ci    #[corresponds(X509_get0_signature)]
58892f3ab15Sopenharmony_ci    pub fn signature(&self) -> &Asn1BitStringRef {
58992f3ab15Sopenharmony_ci        unsafe {
59092f3ab15Sopenharmony_ci            let mut signature = ptr::null();
59192f3ab15Sopenharmony_ci            X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr());
59292f3ab15Sopenharmony_ci            Asn1BitStringRef::from_const_ptr_opt(signature).expect("signature must not be null")
59392f3ab15Sopenharmony_ci        }
59492f3ab15Sopenharmony_ci    }
59592f3ab15Sopenharmony_ci
59692f3ab15Sopenharmony_ci    /// Returns the certificate's signature algorithm.
59792f3ab15Sopenharmony_ci    #[corresponds(X509_get0_signature)]
59892f3ab15Sopenharmony_ci    pub fn signature_algorithm(&self) -> &X509AlgorithmRef {
59992f3ab15Sopenharmony_ci        unsafe {
60092f3ab15Sopenharmony_ci            let mut algor = ptr::null();
60192f3ab15Sopenharmony_ci            X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr());
60292f3ab15Sopenharmony_ci            X509AlgorithmRef::from_const_ptr_opt(algor)
60392f3ab15Sopenharmony_ci                .expect("signature algorithm must not be null")
60492f3ab15Sopenharmony_ci        }
60592f3ab15Sopenharmony_ci    }
60692f3ab15Sopenharmony_ci
60792f3ab15Sopenharmony_ci    /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information
60892f3ab15Sopenharmony_ci    /// Access field.
60992f3ab15Sopenharmony_ci    #[corresponds(X509_get1_ocsp)]
61092f3ab15Sopenharmony_ci    pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> {
61192f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p)) }
61292f3ab15Sopenharmony_ci    }
61392f3ab15Sopenharmony_ci
61492f3ab15Sopenharmony_ci    /// Checks that this certificate issued `subject`.
61592f3ab15Sopenharmony_ci    #[corresponds(X509_check_issued)]
61692f3ab15Sopenharmony_ci    pub fn issued(&self, subject: &X509Ref) -> X509VerifyResult {
61792f3ab15Sopenharmony_ci        unsafe {
61892f3ab15Sopenharmony_ci            let r = ffi::X509_check_issued(self.as_ptr(), subject.as_ptr());
61992f3ab15Sopenharmony_ci            X509VerifyResult::from_raw(r)
62092f3ab15Sopenharmony_ci        }
62192f3ab15Sopenharmony_ci    }
62292f3ab15Sopenharmony_ci
62392f3ab15Sopenharmony_ci    /// Returns certificate version. If this certificate has no explicit version set, it defaults to
62492f3ab15Sopenharmony_ci    /// version 1.
62592f3ab15Sopenharmony_ci    ///
62692f3ab15Sopenharmony_ci    /// Note that `0` return value stands for version 1, `1` for version 2 and so on.
62792f3ab15Sopenharmony_ci    #[corresponds(X509_get_version)]
62892f3ab15Sopenharmony_ci    #[cfg(ossl110)]
62992f3ab15Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
63092f3ab15Sopenharmony_ci    pub fn version(&self) -> i32 {
63192f3ab15Sopenharmony_ci        unsafe { ffi::X509_get_version(self.as_ptr()) as i32 }
63292f3ab15Sopenharmony_ci    }
63392f3ab15Sopenharmony_ci
63492f3ab15Sopenharmony_ci    /// Check if the certificate is signed using the given public key.
63592f3ab15Sopenharmony_ci    ///
63692f3ab15Sopenharmony_ci    /// Only the signature is checked: no other checks (such as certificate chain validity)
63792f3ab15Sopenharmony_ci    /// are performed.
63892f3ab15Sopenharmony_ci    ///
63992f3ab15Sopenharmony_ci    /// Returns `true` if verification succeeds.
64092f3ab15Sopenharmony_ci    #[corresponds(X509_verify)]
64192f3ab15Sopenharmony_ci    pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
64292f3ab15Sopenharmony_ci    where
64392f3ab15Sopenharmony_ci        T: HasPublic,
64492f3ab15Sopenharmony_ci    {
64592f3ab15Sopenharmony_ci        unsafe { cvt_n(ffi::X509_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
64692f3ab15Sopenharmony_ci    }
64792f3ab15Sopenharmony_ci
64892f3ab15Sopenharmony_ci    /// Returns this certificate's serial number.
64992f3ab15Sopenharmony_ci    #[corresponds(X509_get_serialNumber)]
65092f3ab15Sopenharmony_ci    pub fn serial_number(&self) -> &Asn1IntegerRef {
65192f3ab15Sopenharmony_ci        unsafe {
65292f3ab15Sopenharmony_ci            let r = ffi::X509_get_serialNumber(self.as_ptr());
65392f3ab15Sopenharmony_ci            Asn1IntegerRef::from_const_ptr_opt(r).expect("serial number must not be null")
65492f3ab15Sopenharmony_ci        }
65592f3ab15Sopenharmony_ci    }
65692f3ab15Sopenharmony_ci
65792f3ab15Sopenharmony_ci    to_pem! {
65892f3ab15Sopenharmony_ci        /// Serializes the certificate into a PEM-encoded X509 structure.
65992f3ab15Sopenharmony_ci        ///
66092f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN CERTIFICATE-----`.
66192f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_X509)]
66292f3ab15Sopenharmony_ci        to_pem,
66392f3ab15Sopenharmony_ci        ffi::PEM_write_bio_X509
66492f3ab15Sopenharmony_ci    }
66592f3ab15Sopenharmony_ci
66692f3ab15Sopenharmony_ci    to_der! {
66792f3ab15Sopenharmony_ci        /// Serializes the certificate into a DER-encoded X509 structure.
66892f3ab15Sopenharmony_ci        #[corresponds(i2d_X509)]
66992f3ab15Sopenharmony_ci        to_der,
67092f3ab15Sopenharmony_ci        ffi::i2d_X509
67192f3ab15Sopenharmony_ci    }
67292f3ab15Sopenharmony_ci
67392f3ab15Sopenharmony_ci    to_pem! {
67492f3ab15Sopenharmony_ci        /// Converts the certificate to human readable text.
67592f3ab15Sopenharmony_ci        #[corresponds(X509_print)]
67692f3ab15Sopenharmony_ci        to_text,
67792f3ab15Sopenharmony_ci        ffi::X509_print
67892f3ab15Sopenharmony_ci    }
67992f3ab15Sopenharmony_ci}
68092f3ab15Sopenharmony_ci
68192f3ab15Sopenharmony_ciimpl ToOwned for X509Ref {
68292f3ab15Sopenharmony_ci    type Owned = X509;
68392f3ab15Sopenharmony_ci
68492f3ab15Sopenharmony_ci    fn to_owned(&self) -> X509 {
68592f3ab15Sopenharmony_ci        unsafe {
68692f3ab15Sopenharmony_ci            X509_up_ref(self.as_ptr());
68792f3ab15Sopenharmony_ci            X509::from_ptr(self.as_ptr())
68892f3ab15Sopenharmony_ci        }
68992f3ab15Sopenharmony_ci    }
69092f3ab15Sopenharmony_ci}
69192f3ab15Sopenharmony_ci
69292f3ab15Sopenharmony_ciimpl Ord for X509Ref {
69392f3ab15Sopenharmony_ci    fn cmp(&self, other: &Self) -> cmp::Ordering {
69492f3ab15Sopenharmony_ci        // X509_cmp returns a number <0 for less than, 0 for equal and >0 for greater than.
69592f3ab15Sopenharmony_ci        // It can't fail if both pointers are valid, which we know is true.
69692f3ab15Sopenharmony_ci        let cmp = unsafe { ffi::X509_cmp(self.as_ptr(), other.as_ptr()) };
69792f3ab15Sopenharmony_ci        cmp.cmp(&0)
69892f3ab15Sopenharmony_ci    }
69992f3ab15Sopenharmony_ci}
70092f3ab15Sopenharmony_ci
70192f3ab15Sopenharmony_ciimpl PartialOrd for X509Ref {
70292f3ab15Sopenharmony_ci    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
70392f3ab15Sopenharmony_ci        Some(self.cmp(other))
70492f3ab15Sopenharmony_ci    }
70592f3ab15Sopenharmony_ci}
70692f3ab15Sopenharmony_ci
70792f3ab15Sopenharmony_ciimpl PartialOrd<X509> for X509Ref {
70892f3ab15Sopenharmony_ci    fn partial_cmp(&self, other: &X509) -> Option<cmp::Ordering> {
70992f3ab15Sopenharmony_ci        <X509Ref as PartialOrd<X509Ref>>::partial_cmp(self, other)
71092f3ab15Sopenharmony_ci    }
71192f3ab15Sopenharmony_ci}
71292f3ab15Sopenharmony_ci
71392f3ab15Sopenharmony_ciimpl PartialEq for X509Ref {
71492f3ab15Sopenharmony_ci    fn eq(&self, other: &Self) -> bool {
71592f3ab15Sopenharmony_ci        self.cmp(other) == cmp::Ordering::Equal
71692f3ab15Sopenharmony_ci    }
71792f3ab15Sopenharmony_ci}
71892f3ab15Sopenharmony_ci
71992f3ab15Sopenharmony_ciimpl PartialEq<X509> for X509Ref {
72092f3ab15Sopenharmony_ci    fn eq(&self, other: &X509) -> bool {
72192f3ab15Sopenharmony_ci        <X509Ref as PartialEq<X509Ref>>::eq(self, other)
72292f3ab15Sopenharmony_ci    }
72392f3ab15Sopenharmony_ci}
72492f3ab15Sopenharmony_ci
72592f3ab15Sopenharmony_ciimpl Eq for X509Ref {}
72692f3ab15Sopenharmony_ci
72792f3ab15Sopenharmony_ciimpl X509 {
72892f3ab15Sopenharmony_ci    /// Returns a new builder.
72992f3ab15Sopenharmony_ci    pub fn builder() -> Result<X509Builder, ErrorStack> {
73092f3ab15Sopenharmony_ci        X509Builder::new()
73192f3ab15Sopenharmony_ci    }
73292f3ab15Sopenharmony_ci
73392f3ab15Sopenharmony_ci    from_pem! {
73492f3ab15Sopenharmony_ci        /// Deserializes a PEM-encoded X509 structure.
73592f3ab15Sopenharmony_ci        ///
73692f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN CERTIFICATE-----`.
73792f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_X509)]
73892f3ab15Sopenharmony_ci        from_pem,
73992f3ab15Sopenharmony_ci        X509,
74092f3ab15Sopenharmony_ci        ffi::PEM_read_bio_X509
74192f3ab15Sopenharmony_ci    }
74292f3ab15Sopenharmony_ci
74392f3ab15Sopenharmony_ci    from_der! {
74492f3ab15Sopenharmony_ci        /// Deserializes a DER-encoded X509 structure.
74592f3ab15Sopenharmony_ci        #[corresponds(d2i_X509)]
74692f3ab15Sopenharmony_ci        from_der,
74792f3ab15Sopenharmony_ci        X509,
74892f3ab15Sopenharmony_ci        ffi::d2i_X509
74992f3ab15Sopenharmony_ci    }
75092f3ab15Sopenharmony_ci
75192f3ab15Sopenharmony_ci    /// Deserializes a list of PEM-formatted certificates.
75292f3ab15Sopenharmony_ci    #[corresponds(PEM_read_bio_X509)]
75392f3ab15Sopenharmony_ci    pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> {
75492f3ab15Sopenharmony_ci        unsafe {
75592f3ab15Sopenharmony_ci            ffi::init();
75692f3ab15Sopenharmony_ci            let bio = MemBioSlice::new(pem)?;
75792f3ab15Sopenharmony_ci
75892f3ab15Sopenharmony_ci            let mut certs = vec![];
75992f3ab15Sopenharmony_ci            loop {
76092f3ab15Sopenharmony_ci                let r =
76192f3ab15Sopenharmony_ci                    ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut());
76292f3ab15Sopenharmony_ci                if r.is_null() {
76392f3ab15Sopenharmony_ci                    let err = ffi::ERR_peek_last_error();
76492f3ab15Sopenharmony_ci                    if ffi::ERR_GET_LIB(err) as X509LenTy == ffi::ERR_LIB_PEM
76592f3ab15Sopenharmony_ci                        && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE
76692f3ab15Sopenharmony_ci                    {
76792f3ab15Sopenharmony_ci                        ffi::ERR_clear_error();
76892f3ab15Sopenharmony_ci                        break;
76992f3ab15Sopenharmony_ci                    }
77092f3ab15Sopenharmony_ci
77192f3ab15Sopenharmony_ci                    return Err(ErrorStack::get());
77292f3ab15Sopenharmony_ci                } else {
77392f3ab15Sopenharmony_ci                    certs.push(X509(r));
77492f3ab15Sopenharmony_ci                }
77592f3ab15Sopenharmony_ci            }
77692f3ab15Sopenharmony_ci
77792f3ab15Sopenharmony_ci            Ok(certs)
77892f3ab15Sopenharmony_ci        }
77992f3ab15Sopenharmony_ci    }
78092f3ab15Sopenharmony_ci}
78192f3ab15Sopenharmony_ci
78292f3ab15Sopenharmony_ciimpl Clone for X509 {
78392f3ab15Sopenharmony_ci    fn clone(&self) -> X509 {
78492f3ab15Sopenharmony_ci        X509Ref::to_owned(self)
78592f3ab15Sopenharmony_ci    }
78692f3ab15Sopenharmony_ci}
78792f3ab15Sopenharmony_ci
78892f3ab15Sopenharmony_ciimpl fmt::Debug for X509 {
78992f3ab15Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
79092f3ab15Sopenharmony_ci        let serial = match &self.serial_number().to_bn() {
79192f3ab15Sopenharmony_ci            Ok(bn) => match bn.to_hex_str() {
79292f3ab15Sopenharmony_ci                Ok(hex) => hex.to_string(),
79392f3ab15Sopenharmony_ci                Err(_) => "".to_string(),
79492f3ab15Sopenharmony_ci            },
79592f3ab15Sopenharmony_ci            Err(_) => "".to_string(),
79692f3ab15Sopenharmony_ci        };
79792f3ab15Sopenharmony_ci        let mut debug_struct = formatter.debug_struct("X509");
79892f3ab15Sopenharmony_ci        debug_struct.field("serial_number", &serial);
79992f3ab15Sopenharmony_ci        debug_struct.field("signature_algorithm", &self.signature_algorithm().object());
80092f3ab15Sopenharmony_ci        debug_struct.field("issuer", &self.issuer_name());
80192f3ab15Sopenharmony_ci        debug_struct.field("subject", &self.subject_name());
80292f3ab15Sopenharmony_ci        if let Some(subject_alt_names) = &self.subject_alt_names() {
80392f3ab15Sopenharmony_ci            debug_struct.field("subject_alt_names", subject_alt_names);
80492f3ab15Sopenharmony_ci        }
80592f3ab15Sopenharmony_ci        debug_struct.field("not_before", &self.not_before());
80692f3ab15Sopenharmony_ci        debug_struct.field("not_after", &self.not_after());
80792f3ab15Sopenharmony_ci
80892f3ab15Sopenharmony_ci        if let Ok(public_key) = &self.public_key() {
80992f3ab15Sopenharmony_ci            debug_struct.field("public_key", public_key);
81092f3ab15Sopenharmony_ci        };
81192f3ab15Sopenharmony_ci        // TODO: Print extensions once they are supported on the X509 struct.
81292f3ab15Sopenharmony_ci
81392f3ab15Sopenharmony_ci        debug_struct.finish()
81492f3ab15Sopenharmony_ci    }
81592f3ab15Sopenharmony_ci}
81692f3ab15Sopenharmony_ci
81792f3ab15Sopenharmony_ciimpl AsRef<X509Ref> for X509Ref {
81892f3ab15Sopenharmony_ci    fn as_ref(&self) -> &X509Ref {
81992f3ab15Sopenharmony_ci        self
82092f3ab15Sopenharmony_ci    }
82192f3ab15Sopenharmony_ci}
82292f3ab15Sopenharmony_ci
82392f3ab15Sopenharmony_ciimpl Stackable for X509 {
82492f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_X509;
82592f3ab15Sopenharmony_ci}
82692f3ab15Sopenharmony_ci
82792f3ab15Sopenharmony_ciimpl Ord for X509 {
82892f3ab15Sopenharmony_ci    fn cmp(&self, other: &Self) -> cmp::Ordering {
82992f3ab15Sopenharmony_ci        X509Ref::cmp(self, other)
83092f3ab15Sopenharmony_ci    }
83192f3ab15Sopenharmony_ci}
83292f3ab15Sopenharmony_ci
83392f3ab15Sopenharmony_ciimpl PartialOrd for X509 {
83492f3ab15Sopenharmony_ci    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
83592f3ab15Sopenharmony_ci        X509Ref::partial_cmp(self, other)
83692f3ab15Sopenharmony_ci    }
83792f3ab15Sopenharmony_ci}
83892f3ab15Sopenharmony_ci
83992f3ab15Sopenharmony_ciimpl PartialOrd<X509Ref> for X509 {
84092f3ab15Sopenharmony_ci    fn partial_cmp(&self, other: &X509Ref) -> Option<cmp::Ordering> {
84192f3ab15Sopenharmony_ci        X509Ref::partial_cmp(self, other)
84292f3ab15Sopenharmony_ci    }
84392f3ab15Sopenharmony_ci}
84492f3ab15Sopenharmony_ci
84592f3ab15Sopenharmony_ciimpl PartialEq for X509 {
84692f3ab15Sopenharmony_ci    fn eq(&self, other: &Self) -> bool {
84792f3ab15Sopenharmony_ci        X509Ref::eq(self, other)
84892f3ab15Sopenharmony_ci    }
84992f3ab15Sopenharmony_ci}
85092f3ab15Sopenharmony_ci
85192f3ab15Sopenharmony_ciimpl PartialEq<X509Ref> for X509 {
85292f3ab15Sopenharmony_ci    fn eq(&self, other: &X509Ref) -> bool {
85392f3ab15Sopenharmony_ci        X509Ref::eq(self, other)
85492f3ab15Sopenharmony_ci    }
85592f3ab15Sopenharmony_ci}
85692f3ab15Sopenharmony_ci
85792f3ab15Sopenharmony_ciimpl Eq for X509 {}
85892f3ab15Sopenharmony_ci
85992f3ab15Sopenharmony_ci/// A context object required to construct certain `X509` extension values.
86092f3ab15Sopenharmony_cipub struct X509v3Context<'a>(ffi::X509V3_CTX, PhantomData<(&'a X509Ref, &'a ConfRef)>);
86192f3ab15Sopenharmony_ci
86292f3ab15Sopenharmony_ciimpl<'a> X509v3Context<'a> {
86392f3ab15Sopenharmony_ci    pub fn as_ptr(&self) -> *mut ffi::X509V3_CTX {
86492f3ab15Sopenharmony_ci        &self.0 as *const _ as *mut _
86592f3ab15Sopenharmony_ci    }
86692f3ab15Sopenharmony_ci}
86792f3ab15Sopenharmony_ci
86892f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
86992f3ab15Sopenharmony_ci    type CType = ffi::X509_EXTENSION;
87092f3ab15Sopenharmony_ci    fn drop = ffi::X509_EXTENSION_free;
87192f3ab15Sopenharmony_ci
87292f3ab15Sopenharmony_ci    /// Permit additional fields to be added to an `X509` v3 certificate.
87392f3ab15Sopenharmony_ci    pub struct X509Extension;
87492f3ab15Sopenharmony_ci    /// Reference to `X509Extension`.
87592f3ab15Sopenharmony_ci    pub struct X509ExtensionRef;
87692f3ab15Sopenharmony_ci}
87792f3ab15Sopenharmony_ci
87892f3ab15Sopenharmony_ciimpl Stackable for X509Extension {
87992f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_X509_EXTENSION;
88092f3ab15Sopenharmony_ci}
88192f3ab15Sopenharmony_ci
88292f3ab15Sopenharmony_ciimpl X509Extension {
88392f3ab15Sopenharmony_ci    /// Constructs an X509 extension value. See `man x509v3_config` for information on supported
88492f3ab15Sopenharmony_ci    /// names and their value formats.
88592f3ab15Sopenharmony_ci    ///
88692f3ab15Sopenharmony_ci    /// Some extension types, such as `subjectAlternativeName`, require an `X509v3Context` to be
88792f3ab15Sopenharmony_ci    /// provided.
88892f3ab15Sopenharmony_ci    ///
88992f3ab15Sopenharmony_ci    /// DO NOT CALL THIS WITH UNTRUSTED `value`: `value` is an OpenSSL
89092f3ab15Sopenharmony_ci    /// mini-language that can read arbitrary files.
89192f3ab15Sopenharmony_ci    ///
89292f3ab15Sopenharmony_ci    /// See the extension module for builder types which will construct certain common extensions.
89392f3ab15Sopenharmony_ci    ///
89492f3ab15Sopenharmony_ci    /// This function is deprecated, `X509Extension::new_from_der` or the
89592f3ab15Sopenharmony_ci    /// types in `x509::extension` should be used in its place.
89692f3ab15Sopenharmony_ci    #[deprecated(
89792f3ab15Sopenharmony_ci        note = "Use x509::extension types or new_from_der instead",
89892f3ab15Sopenharmony_ci        since = "0.10.51"
89992f3ab15Sopenharmony_ci    )]
90092f3ab15Sopenharmony_ci    pub fn new(
90192f3ab15Sopenharmony_ci        conf: Option<&ConfRef>,
90292f3ab15Sopenharmony_ci        context: Option<&X509v3Context<'_>>,
90392f3ab15Sopenharmony_ci        name: &str,
90492f3ab15Sopenharmony_ci        value: &str,
90592f3ab15Sopenharmony_ci    ) -> Result<X509Extension, ErrorStack> {
90692f3ab15Sopenharmony_ci        let name = CString::new(name).unwrap();
90792f3ab15Sopenharmony_ci        let value = CString::new(value).unwrap();
90892f3ab15Sopenharmony_ci        let mut ctx;
90992f3ab15Sopenharmony_ci        unsafe {
91092f3ab15Sopenharmony_ci            ffi::init();
91192f3ab15Sopenharmony_ci            let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr);
91292f3ab15Sopenharmony_ci            let context_ptr = match context {
91392f3ab15Sopenharmony_ci                Some(c) => c.as_ptr(),
91492f3ab15Sopenharmony_ci                None => {
91592f3ab15Sopenharmony_ci                    ctx = mem::zeroed();
91692f3ab15Sopenharmony_ci
91792f3ab15Sopenharmony_ci                    ffi::X509V3_set_ctx(
91892f3ab15Sopenharmony_ci                        &mut ctx,
91992f3ab15Sopenharmony_ci                        ptr::null_mut(),
92092f3ab15Sopenharmony_ci                        ptr::null_mut(),
92192f3ab15Sopenharmony_ci                        ptr::null_mut(),
92292f3ab15Sopenharmony_ci                        ptr::null_mut(),
92392f3ab15Sopenharmony_ci                        0,
92492f3ab15Sopenharmony_ci                    );
92592f3ab15Sopenharmony_ci                    &mut ctx
92692f3ab15Sopenharmony_ci                }
92792f3ab15Sopenharmony_ci            };
92892f3ab15Sopenharmony_ci            let name = name.as_ptr() as *mut _;
92992f3ab15Sopenharmony_ci            let value = value.as_ptr() as *mut _;
93092f3ab15Sopenharmony_ci
93192f3ab15Sopenharmony_ci            cvt_p(ffi::X509V3_EXT_nconf(conf, context_ptr, name, value)).map(X509Extension)
93292f3ab15Sopenharmony_ci        }
93392f3ab15Sopenharmony_ci    }
93492f3ab15Sopenharmony_ci
93592f3ab15Sopenharmony_ci    /// Constructs an X509 extension value. See `man x509v3_config` for information on supported
93692f3ab15Sopenharmony_ci    /// extensions and their value formats.
93792f3ab15Sopenharmony_ci    ///
93892f3ab15Sopenharmony_ci    /// Some extension types, such as `nid::SUBJECT_ALTERNATIVE_NAME`, require an `X509v3Context` to
93992f3ab15Sopenharmony_ci    /// be provided.
94092f3ab15Sopenharmony_ci    ///
94192f3ab15Sopenharmony_ci    /// DO NOT CALL THIS WITH UNTRUSTED `value`: `value` is an OpenSSL
94292f3ab15Sopenharmony_ci    /// mini-language that can read arbitrary files.
94392f3ab15Sopenharmony_ci    ///
94492f3ab15Sopenharmony_ci    /// See the extension module for builder types which will construct certain common extensions.
94592f3ab15Sopenharmony_ci    ///
94692f3ab15Sopenharmony_ci    /// This function is deprecated, `X509Extension::new_from_der` or the
94792f3ab15Sopenharmony_ci    /// types in `x509::extension` should be used in its place.
94892f3ab15Sopenharmony_ci    #[deprecated(
94992f3ab15Sopenharmony_ci        note = "Use x509::extension types or new_from_der instead",
95092f3ab15Sopenharmony_ci        since = "0.10.51"
95192f3ab15Sopenharmony_ci    )]
95292f3ab15Sopenharmony_ci    pub fn new_nid(
95392f3ab15Sopenharmony_ci        conf: Option<&ConfRef>,
95492f3ab15Sopenharmony_ci        context: Option<&X509v3Context<'_>>,
95592f3ab15Sopenharmony_ci        name: Nid,
95692f3ab15Sopenharmony_ci        value: &str,
95792f3ab15Sopenharmony_ci    ) -> Result<X509Extension, ErrorStack> {
95892f3ab15Sopenharmony_ci        let value = CString::new(value).unwrap();
95992f3ab15Sopenharmony_ci        let mut ctx;
96092f3ab15Sopenharmony_ci        unsafe {
96192f3ab15Sopenharmony_ci            ffi::init();
96292f3ab15Sopenharmony_ci            let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr);
96392f3ab15Sopenharmony_ci            let context_ptr = match context {
96492f3ab15Sopenharmony_ci                Some(c) => c.as_ptr(),
96592f3ab15Sopenharmony_ci                None => {
96692f3ab15Sopenharmony_ci                    ctx = mem::zeroed();
96792f3ab15Sopenharmony_ci
96892f3ab15Sopenharmony_ci                    ffi::X509V3_set_ctx(
96992f3ab15Sopenharmony_ci                        &mut ctx,
97092f3ab15Sopenharmony_ci                        ptr::null_mut(),
97192f3ab15Sopenharmony_ci                        ptr::null_mut(),
97292f3ab15Sopenharmony_ci                        ptr::null_mut(),
97392f3ab15Sopenharmony_ci                        ptr::null_mut(),
97492f3ab15Sopenharmony_ci                        0,
97592f3ab15Sopenharmony_ci                    );
97692f3ab15Sopenharmony_ci                    &mut ctx
97792f3ab15Sopenharmony_ci                }
97892f3ab15Sopenharmony_ci            };
97992f3ab15Sopenharmony_ci            let name = name.as_raw();
98092f3ab15Sopenharmony_ci            let value = value.as_ptr() as *mut _;
98192f3ab15Sopenharmony_ci
98292f3ab15Sopenharmony_ci            cvt_p(ffi::X509V3_EXT_nconf_nid(conf, context_ptr, name, value)).map(X509Extension)
98392f3ab15Sopenharmony_ci        }
98492f3ab15Sopenharmony_ci    }
98592f3ab15Sopenharmony_ci
98692f3ab15Sopenharmony_ci    /// Constructs a new X509 extension value from its OID, whether it's
98792f3ab15Sopenharmony_ci    /// critical, and its DER contents.
98892f3ab15Sopenharmony_ci    ///
98992f3ab15Sopenharmony_ci    /// The extent structure of the DER value will vary based on the
99092f3ab15Sopenharmony_ci    /// extension type, and can generally be found in the RFC defining the
99192f3ab15Sopenharmony_ci    /// extension.
99292f3ab15Sopenharmony_ci    ///
99392f3ab15Sopenharmony_ci    /// For common extension types, there are Rust APIs provided in
99492f3ab15Sopenharmony_ci    /// `openssl::x509::extensions` which are more ergonomic.
99592f3ab15Sopenharmony_ci    pub fn new_from_der(
99692f3ab15Sopenharmony_ci        oid: &Asn1ObjectRef,
99792f3ab15Sopenharmony_ci        critical: bool,
99892f3ab15Sopenharmony_ci        der_contents: &Asn1OctetStringRef,
99992f3ab15Sopenharmony_ci    ) -> Result<X509Extension, ErrorStack> {
100092f3ab15Sopenharmony_ci        unsafe {
100192f3ab15Sopenharmony_ci            cvt_p(ffi::X509_EXTENSION_create_by_OBJ(
100292f3ab15Sopenharmony_ci                ptr::null_mut(),
100392f3ab15Sopenharmony_ci                oid.as_ptr(),
100492f3ab15Sopenharmony_ci                critical as _,
100592f3ab15Sopenharmony_ci                der_contents.as_ptr(),
100692f3ab15Sopenharmony_ci            ))
100792f3ab15Sopenharmony_ci            .map(X509Extension)
100892f3ab15Sopenharmony_ci        }
100992f3ab15Sopenharmony_ci    }
101092f3ab15Sopenharmony_ci
101192f3ab15Sopenharmony_ci    pub(crate) unsafe fn new_internal(
101292f3ab15Sopenharmony_ci        nid: Nid,
101392f3ab15Sopenharmony_ci        critical: bool,
101492f3ab15Sopenharmony_ci        value: *mut c_void,
101592f3ab15Sopenharmony_ci    ) -> Result<X509Extension, ErrorStack> {
101692f3ab15Sopenharmony_ci        ffi::init();
101792f3ab15Sopenharmony_ci        cvt_p(ffi::X509V3_EXT_i2d(nid.as_raw(), critical as _, value)).map(X509Extension)
101892f3ab15Sopenharmony_ci    }
101992f3ab15Sopenharmony_ci
102092f3ab15Sopenharmony_ci    /// Adds an alias for an extension
102192f3ab15Sopenharmony_ci    ///
102292f3ab15Sopenharmony_ci    /// # Safety
102392f3ab15Sopenharmony_ci    ///
102492f3ab15Sopenharmony_ci    /// This method modifies global state without locking and therefore is not thread safe
102592f3ab15Sopenharmony_ci    #[corresponds(X509V3_EXT_add_alias)]
102692f3ab15Sopenharmony_ci    #[deprecated(
102792f3ab15Sopenharmony_ci        note = "Use x509::extension types or new_from_der and then this is not necessary",
102892f3ab15Sopenharmony_ci        since = "0.10.51"
102992f3ab15Sopenharmony_ci    )]
103092f3ab15Sopenharmony_ci    pub unsafe fn add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack> {
103192f3ab15Sopenharmony_ci        ffi::init();
103292f3ab15Sopenharmony_ci        cvt(ffi::X509V3_EXT_add_alias(to.as_raw(), from.as_raw())).map(|_| ())
103392f3ab15Sopenharmony_ci    }
103492f3ab15Sopenharmony_ci}
103592f3ab15Sopenharmony_ci
103692f3ab15Sopenharmony_ciimpl X509ExtensionRef {
103792f3ab15Sopenharmony_ci    to_der! {
103892f3ab15Sopenharmony_ci        /// Serializes the Extension to its standard DER encoding.
103992f3ab15Sopenharmony_ci        #[corresponds(i2d_X509_EXTENSION)]
104092f3ab15Sopenharmony_ci        to_der,
104192f3ab15Sopenharmony_ci        ffi::i2d_X509_EXTENSION
104292f3ab15Sopenharmony_ci    }
104392f3ab15Sopenharmony_ci}
104492f3ab15Sopenharmony_ci
104592f3ab15Sopenharmony_ci/// A builder used to construct an `X509Name`.
104692f3ab15Sopenharmony_cipub struct X509NameBuilder(X509Name);
104792f3ab15Sopenharmony_ci
104892f3ab15Sopenharmony_ciimpl X509NameBuilder {
104992f3ab15Sopenharmony_ci    /// Creates a new builder.
105092f3ab15Sopenharmony_ci    pub fn new() -> Result<X509NameBuilder, ErrorStack> {
105192f3ab15Sopenharmony_ci        unsafe {
105292f3ab15Sopenharmony_ci            ffi::init();
105392f3ab15Sopenharmony_ci            cvt_p(ffi::X509_NAME_new()).map(|p| X509NameBuilder(X509Name(p)))
105492f3ab15Sopenharmony_ci        }
105592f3ab15Sopenharmony_ci    }
105692f3ab15Sopenharmony_ci
105792f3ab15Sopenharmony_ci    /// Add a name entry
105892f3ab15Sopenharmony_ci    #[corresponds(X509_NAME_add_entry)]
105992f3ab15Sopenharmony_ci    #[cfg(any(ossl101, libressl350))]
106092f3ab15Sopenharmony_ci    pub fn append_entry(&mut self, ne: &X509NameEntryRef) -> std::result::Result<(), ErrorStack> {
106192f3ab15Sopenharmony_ci        unsafe {
106292f3ab15Sopenharmony_ci            cvt(ffi::X509_NAME_add_entry(
106392f3ab15Sopenharmony_ci                self.0.as_ptr(),
106492f3ab15Sopenharmony_ci                ne.as_ptr(),
106592f3ab15Sopenharmony_ci                -1,
106692f3ab15Sopenharmony_ci                0,
106792f3ab15Sopenharmony_ci            ))
106892f3ab15Sopenharmony_ci            .map(|_| ())
106992f3ab15Sopenharmony_ci        }
107092f3ab15Sopenharmony_ci    }
107192f3ab15Sopenharmony_ci
107292f3ab15Sopenharmony_ci    /// Add a field entry by str.
107392f3ab15Sopenharmony_ci    ///
107492f3ab15Sopenharmony_ci    /// This corresponds to [`X509_NAME_add_entry_by_txt`].
107592f3ab15Sopenharmony_ci    ///
107692f3ab15Sopenharmony_ci    /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_add_entry_by_txt.html
107792f3ab15Sopenharmony_ci    pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
107892f3ab15Sopenharmony_ci        unsafe {
107992f3ab15Sopenharmony_ci            let field = CString::new(field).unwrap();
108092f3ab15Sopenharmony_ci            assert!(value.len() <= crate::SLenType::max_value() as usize);
108192f3ab15Sopenharmony_ci            cvt(ffi::X509_NAME_add_entry_by_txt(
108292f3ab15Sopenharmony_ci                self.0.as_ptr(),
108392f3ab15Sopenharmony_ci                field.as_ptr() as *mut _,
108492f3ab15Sopenharmony_ci                ffi::MBSTRING_UTF8,
108592f3ab15Sopenharmony_ci                value.as_ptr(),
108692f3ab15Sopenharmony_ci                value.len() as crate::SLenType,
108792f3ab15Sopenharmony_ci                -1,
108892f3ab15Sopenharmony_ci                0,
108992f3ab15Sopenharmony_ci            ))
109092f3ab15Sopenharmony_ci            .map(|_| ())
109192f3ab15Sopenharmony_ci        }
109292f3ab15Sopenharmony_ci    }
109392f3ab15Sopenharmony_ci
109492f3ab15Sopenharmony_ci    /// Add a field entry by str with a specific type.
109592f3ab15Sopenharmony_ci    ///
109692f3ab15Sopenharmony_ci    /// This corresponds to [`X509_NAME_add_entry_by_txt`].
109792f3ab15Sopenharmony_ci    ///
109892f3ab15Sopenharmony_ci    /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_add_entry_by_txt.html
109992f3ab15Sopenharmony_ci    pub fn append_entry_by_text_with_type(
110092f3ab15Sopenharmony_ci        &mut self,
110192f3ab15Sopenharmony_ci        field: &str,
110292f3ab15Sopenharmony_ci        value: &str,
110392f3ab15Sopenharmony_ci        ty: Asn1Type,
110492f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
110592f3ab15Sopenharmony_ci        unsafe {
110692f3ab15Sopenharmony_ci            let field = CString::new(field).unwrap();
110792f3ab15Sopenharmony_ci            assert!(value.len() <= crate::SLenType::max_value() as usize);
110892f3ab15Sopenharmony_ci            cvt(ffi::X509_NAME_add_entry_by_txt(
110992f3ab15Sopenharmony_ci                self.0.as_ptr(),
111092f3ab15Sopenharmony_ci                field.as_ptr() as *mut _,
111192f3ab15Sopenharmony_ci                ty.as_raw(),
111292f3ab15Sopenharmony_ci                value.as_ptr(),
111392f3ab15Sopenharmony_ci                value.len() as crate::SLenType,
111492f3ab15Sopenharmony_ci                -1,
111592f3ab15Sopenharmony_ci                0,
111692f3ab15Sopenharmony_ci            ))
111792f3ab15Sopenharmony_ci            .map(|_| ())
111892f3ab15Sopenharmony_ci        }
111992f3ab15Sopenharmony_ci    }
112092f3ab15Sopenharmony_ci
112192f3ab15Sopenharmony_ci    /// Add a field entry by NID.
112292f3ab15Sopenharmony_ci    ///
112392f3ab15Sopenharmony_ci    /// This corresponds to [`X509_NAME_add_entry_by_NID`].
112492f3ab15Sopenharmony_ci    ///
112592f3ab15Sopenharmony_ci    /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_add_entry_by_NID.html
112692f3ab15Sopenharmony_ci    pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
112792f3ab15Sopenharmony_ci        unsafe {
112892f3ab15Sopenharmony_ci            assert!(value.len() <= crate::SLenType::max_value() as usize);
112992f3ab15Sopenharmony_ci            cvt(ffi::X509_NAME_add_entry_by_NID(
113092f3ab15Sopenharmony_ci                self.0.as_ptr(),
113192f3ab15Sopenharmony_ci                field.as_raw(),
113292f3ab15Sopenharmony_ci                ffi::MBSTRING_UTF8,
113392f3ab15Sopenharmony_ci                value.as_ptr() as *mut _,
113492f3ab15Sopenharmony_ci                value.len() as crate::SLenType,
113592f3ab15Sopenharmony_ci                -1,
113692f3ab15Sopenharmony_ci                0,
113792f3ab15Sopenharmony_ci            ))
113892f3ab15Sopenharmony_ci            .map(|_| ())
113992f3ab15Sopenharmony_ci        }
114092f3ab15Sopenharmony_ci    }
114192f3ab15Sopenharmony_ci
114292f3ab15Sopenharmony_ci    /// Add a field entry by NID with a specific type.
114392f3ab15Sopenharmony_ci    ///
114492f3ab15Sopenharmony_ci    /// This corresponds to [`X509_NAME_add_entry_by_NID`].
114592f3ab15Sopenharmony_ci    ///
114692f3ab15Sopenharmony_ci    /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_add_entry_by_NID.html
114792f3ab15Sopenharmony_ci    pub fn append_entry_by_nid_with_type(
114892f3ab15Sopenharmony_ci        &mut self,
114992f3ab15Sopenharmony_ci        field: Nid,
115092f3ab15Sopenharmony_ci        value: &str,
115192f3ab15Sopenharmony_ci        ty: Asn1Type,
115292f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
115392f3ab15Sopenharmony_ci        unsafe {
115492f3ab15Sopenharmony_ci            assert!(value.len() <= crate::SLenType::max_value() as usize);
115592f3ab15Sopenharmony_ci            cvt(ffi::X509_NAME_add_entry_by_NID(
115692f3ab15Sopenharmony_ci                self.0.as_ptr(),
115792f3ab15Sopenharmony_ci                field.as_raw(),
115892f3ab15Sopenharmony_ci                ty.as_raw(),
115992f3ab15Sopenharmony_ci                value.as_ptr() as *mut _,
116092f3ab15Sopenharmony_ci                value.len() as crate::SLenType,
116192f3ab15Sopenharmony_ci                -1,
116292f3ab15Sopenharmony_ci                0,
116392f3ab15Sopenharmony_ci            ))
116492f3ab15Sopenharmony_ci            .map(|_| ())
116592f3ab15Sopenharmony_ci        }
116692f3ab15Sopenharmony_ci    }
116792f3ab15Sopenharmony_ci
116892f3ab15Sopenharmony_ci    /// Return an `X509Name`.
116992f3ab15Sopenharmony_ci    pub fn build(self) -> X509Name {
117092f3ab15Sopenharmony_ci        // Round-trip through bytes because OpenSSL is not const correct and
117192f3ab15Sopenharmony_ci        // names in a "modified" state compute various things lazily. This can
117292f3ab15Sopenharmony_ci        // lead to data-races because OpenSSL doesn't have locks or anything.
117392f3ab15Sopenharmony_ci        X509Name::from_der(&self.0.to_der().unwrap()).unwrap()
117492f3ab15Sopenharmony_ci    }
117592f3ab15Sopenharmony_ci}
117692f3ab15Sopenharmony_ci
117792f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
117892f3ab15Sopenharmony_ci    type CType = ffi::X509_NAME;
117992f3ab15Sopenharmony_ci    fn drop = ffi::X509_NAME_free;
118092f3ab15Sopenharmony_ci
118192f3ab15Sopenharmony_ci    /// The names of an `X509` certificate.
118292f3ab15Sopenharmony_ci    pub struct X509Name;
118392f3ab15Sopenharmony_ci    /// Reference to `X509Name`.
118492f3ab15Sopenharmony_ci    pub struct X509NameRef;
118592f3ab15Sopenharmony_ci}
118692f3ab15Sopenharmony_ci
118792f3ab15Sopenharmony_ciimpl X509Name {
118892f3ab15Sopenharmony_ci    /// Returns a new builder.
118992f3ab15Sopenharmony_ci    pub fn builder() -> Result<X509NameBuilder, ErrorStack> {
119092f3ab15Sopenharmony_ci        X509NameBuilder::new()
119192f3ab15Sopenharmony_ci    }
119292f3ab15Sopenharmony_ci
119392f3ab15Sopenharmony_ci    /// Loads subject names from a file containing PEM-formatted certificates.
119492f3ab15Sopenharmony_ci    ///
119592f3ab15Sopenharmony_ci    /// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
119692f3ab15Sopenharmony_ci    pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> {
119792f3ab15Sopenharmony_ci        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
119892f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p)) }
119992f3ab15Sopenharmony_ci    }
120092f3ab15Sopenharmony_ci
120192f3ab15Sopenharmony_ci    from_der! {
120292f3ab15Sopenharmony_ci        /// Deserializes a DER-encoded X509 name structure.
120392f3ab15Sopenharmony_ci        ///
120492f3ab15Sopenharmony_ci        /// This corresponds to [`d2i_X509_NAME`].
120592f3ab15Sopenharmony_ci        ///
120692f3ab15Sopenharmony_ci        /// [`d2i_X509_NAME`]: https://www.openssl.org/docs/manmaster/man3/d2i_X509_NAME.html
120792f3ab15Sopenharmony_ci        from_der,
120892f3ab15Sopenharmony_ci        X509Name,
120992f3ab15Sopenharmony_ci        ffi::d2i_X509_NAME
121092f3ab15Sopenharmony_ci    }
121192f3ab15Sopenharmony_ci}
121292f3ab15Sopenharmony_ci
121392f3ab15Sopenharmony_ciimpl Stackable for X509Name {
121492f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_X509_NAME;
121592f3ab15Sopenharmony_ci}
121692f3ab15Sopenharmony_ci
121792f3ab15Sopenharmony_ciimpl X509NameRef {
121892f3ab15Sopenharmony_ci    /// Returns the name entries by the nid.
121992f3ab15Sopenharmony_ci    pub fn entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_> {
122092f3ab15Sopenharmony_ci        X509NameEntries {
122192f3ab15Sopenharmony_ci            name: self,
122292f3ab15Sopenharmony_ci            nid: Some(nid),
122392f3ab15Sopenharmony_ci            loc: -1,
122492f3ab15Sopenharmony_ci        }
122592f3ab15Sopenharmony_ci    }
122692f3ab15Sopenharmony_ci
122792f3ab15Sopenharmony_ci    /// Returns an iterator over all `X509NameEntry` values
122892f3ab15Sopenharmony_ci    pub fn entries(&self) -> X509NameEntries<'_> {
122992f3ab15Sopenharmony_ci        X509NameEntries {
123092f3ab15Sopenharmony_ci            name: self,
123192f3ab15Sopenharmony_ci            nid: None,
123292f3ab15Sopenharmony_ci            loc: -1,
123392f3ab15Sopenharmony_ci        }
123492f3ab15Sopenharmony_ci    }
123592f3ab15Sopenharmony_ci
123692f3ab15Sopenharmony_ci    /// Compare two names, like [`Ord`] but it may fail.
123792f3ab15Sopenharmony_ci    ///
123892f3ab15Sopenharmony_ci    /// With OpenSSL versions from 3.0.0 this may return an error if the underlying `X509_NAME_cmp`
123992f3ab15Sopenharmony_ci    /// call fails.
124092f3ab15Sopenharmony_ci    /// For OpenSSL versions before 3.0.0 it will never return an error, but due to a bug it may
124192f3ab15Sopenharmony_ci    /// spuriously return `Ordering::Less` if the `X509_NAME_cmp` call fails.
124292f3ab15Sopenharmony_ci    #[corresponds(X509_NAME_cmp)]
124392f3ab15Sopenharmony_ci    pub fn try_cmp(&self, other: &X509NameRef) -> Result<Ordering, ErrorStack> {
124492f3ab15Sopenharmony_ci        let cmp = unsafe { ffi::X509_NAME_cmp(self.as_ptr(), other.as_ptr()) };
124592f3ab15Sopenharmony_ci        if cfg!(ossl300) && cmp == -2 {
124692f3ab15Sopenharmony_ci            return Err(ErrorStack::get());
124792f3ab15Sopenharmony_ci        }
124892f3ab15Sopenharmony_ci        Ok(cmp.cmp(&0))
124992f3ab15Sopenharmony_ci    }
125092f3ab15Sopenharmony_ci
125192f3ab15Sopenharmony_ci    /// Copies the name to a new `X509Name`.
125292f3ab15Sopenharmony_ci    #[corresponds(X509_NAME_dup)]
125392f3ab15Sopenharmony_ci    #[cfg(any(boringssl, ossl110, libressl270))]
125492f3ab15Sopenharmony_ci    pub fn to_owned(&self) -> Result<X509Name, ErrorStack> {
125592f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::X509_NAME_dup(self.as_ptr())).map(|n| X509Name::from_ptr(n)) }
125692f3ab15Sopenharmony_ci    }
125792f3ab15Sopenharmony_ci
125892f3ab15Sopenharmony_ci    to_der! {
125992f3ab15Sopenharmony_ci        /// Serializes the certificate into a DER-encoded X509 name structure.
126092f3ab15Sopenharmony_ci        ///
126192f3ab15Sopenharmony_ci        /// This corresponds to [`i2d_X509_NAME`].
126292f3ab15Sopenharmony_ci        ///
126392f3ab15Sopenharmony_ci        /// [`i2d_X509_NAME`]: https://www.openssl.org/docs/manmaster/crypto/i2d_X509_NAME.html
126492f3ab15Sopenharmony_ci        to_der,
126592f3ab15Sopenharmony_ci        ffi::i2d_X509_NAME
126692f3ab15Sopenharmony_ci    }
126792f3ab15Sopenharmony_ci}
126892f3ab15Sopenharmony_ci
126992f3ab15Sopenharmony_ciimpl fmt::Debug for X509NameRef {
127092f3ab15Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
127192f3ab15Sopenharmony_ci        formatter.debug_list().entries(self.entries()).finish()
127292f3ab15Sopenharmony_ci    }
127392f3ab15Sopenharmony_ci}
127492f3ab15Sopenharmony_ci
127592f3ab15Sopenharmony_ci/// A type to destructure and examine an `X509Name`.
127692f3ab15Sopenharmony_cipub struct X509NameEntries<'a> {
127792f3ab15Sopenharmony_ci    name: &'a X509NameRef,
127892f3ab15Sopenharmony_ci    nid: Option<Nid>,
127992f3ab15Sopenharmony_ci    loc: c_int,
128092f3ab15Sopenharmony_ci}
128192f3ab15Sopenharmony_ci
128292f3ab15Sopenharmony_ciimpl<'a> Iterator for X509NameEntries<'a> {
128392f3ab15Sopenharmony_ci    type Item = &'a X509NameEntryRef;
128492f3ab15Sopenharmony_ci
128592f3ab15Sopenharmony_ci    fn next(&mut self) -> Option<&'a X509NameEntryRef> {
128692f3ab15Sopenharmony_ci        unsafe {
128792f3ab15Sopenharmony_ci            match self.nid {
128892f3ab15Sopenharmony_ci                Some(nid) => {
128992f3ab15Sopenharmony_ci                    // There is a `Nid` specified to search for
129092f3ab15Sopenharmony_ci                    self.loc =
129192f3ab15Sopenharmony_ci                        ffi::X509_NAME_get_index_by_NID(self.name.as_ptr(), nid.as_raw(), self.loc);
129292f3ab15Sopenharmony_ci                    if self.loc == -1 {
129392f3ab15Sopenharmony_ci                        return None;
129492f3ab15Sopenharmony_ci                    }
129592f3ab15Sopenharmony_ci                }
129692f3ab15Sopenharmony_ci                None => {
129792f3ab15Sopenharmony_ci                    // Iterate over all `Nid`s
129892f3ab15Sopenharmony_ci                    self.loc += 1;
129992f3ab15Sopenharmony_ci                    if self.loc >= ffi::X509_NAME_entry_count(self.name.as_ptr()) {
130092f3ab15Sopenharmony_ci                        return None;
130192f3ab15Sopenharmony_ci                    }
130292f3ab15Sopenharmony_ci                }
130392f3ab15Sopenharmony_ci            }
130492f3ab15Sopenharmony_ci
130592f3ab15Sopenharmony_ci            let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc);
130692f3ab15Sopenharmony_ci
130792f3ab15Sopenharmony_ci            Some(X509NameEntryRef::from_const_ptr_opt(entry).expect("entry must not be null"))
130892f3ab15Sopenharmony_ci        }
130992f3ab15Sopenharmony_ci    }
131092f3ab15Sopenharmony_ci}
131192f3ab15Sopenharmony_ci
131292f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
131392f3ab15Sopenharmony_ci    type CType = ffi::X509_NAME_ENTRY;
131492f3ab15Sopenharmony_ci    fn drop = ffi::X509_NAME_ENTRY_free;
131592f3ab15Sopenharmony_ci
131692f3ab15Sopenharmony_ci    /// A name entry associated with a `X509Name`.
131792f3ab15Sopenharmony_ci    pub struct X509NameEntry;
131892f3ab15Sopenharmony_ci    /// Reference to `X509NameEntry`.
131992f3ab15Sopenharmony_ci    pub struct X509NameEntryRef;
132092f3ab15Sopenharmony_ci}
132192f3ab15Sopenharmony_ci
132292f3ab15Sopenharmony_ciimpl X509NameEntryRef {
132392f3ab15Sopenharmony_ci    /// Returns the field value of an `X509NameEntry`.
132492f3ab15Sopenharmony_ci    ///
132592f3ab15Sopenharmony_ci    /// This corresponds to [`X509_NAME_ENTRY_get_data`].
132692f3ab15Sopenharmony_ci    ///
132792f3ab15Sopenharmony_ci    /// [`X509_NAME_ENTRY_get_data`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_ENTRY_get_data.html
132892f3ab15Sopenharmony_ci    pub fn data(&self) -> &Asn1StringRef {
132992f3ab15Sopenharmony_ci        unsafe {
133092f3ab15Sopenharmony_ci            let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr());
133192f3ab15Sopenharmony_ci            Asn1StringRef::from_ptr(data)
133292f3ab15Sopenharmony_ci        }
133392f3ab15Sopenharmony_ci    }
133492f3ab15Sopenharmony_ci
133592f3ab15Sopenharmony_ci    /// Returns the `Asn1Object` value of an `X509NameEntry`.
133692f3ab15Sopenharmony_ci    /// This is useful for finding out about the actual `Nid` when iterating over all `X509NameEntries`.
133792f3ab15Sopenharmony_ci    ///
133892f3ab15Sopenharmony_ci    /// This corresponds to [`X509_NAME_ENTRY_get_object`].
133992f3ab15Sopenharmony_ci    ///
134092f3ab15Sopenharmony_ci    /// [`X509_NAME_ENTRY_get_object`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_ENTRY_get_object.html
134192f3ab15Sopenharmony_ci    pub fn object(&self) -> &Asn1ObjectRef {
134292f3ab15Sopenharmony_ci        unsafe {
134392f3ab15Sopenharmony_ci            let object = ffi::X509_NAME_ENTRY_get_object(self.as_ptr());
134492f3ab15Sopenharmony_ci            Asn1ObjectRef::from_ptr(object)
134592f3ab15Sopenharmony_ci        }
134692f3ab15Sopenharmony_ci    }
134792f3ab15Sopenharmony_ci}
134892f3ab15Sopenharmony_ci
134992f3ab15Sopenharmony_ciimpl fmt::Debug for X509NameEntryRef {
135092f3ab15Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
135192f3ab15Sopenharmony_ci        formatter.write_fmt(format_args!("{:?} = {:?}", self.object(), self.data()))
135292f3ab15Sopenharmony_ci    }
135392f3ab15Sopenharmony_ci}
135492f3ab15Sopenharmony_ci
135592f3ab15Sopenharmony_ci/// A builder used to construct an `X509Req`.
135692f3ab15Sopenharmony_cipub struct X509ReqBuilder(X509Req);
135792f3ab15Sopenharmony_ci
135892f3ab15Sopenharmony_ciimpl X509ReqBuilder {
135992f3ab15Sopenharmony_ci    /// Returns a builder for a certificate request.
136092f3ab15Sopenharmony_ci    ///
136192f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_new`].
136292f3ab15Sopenharmony_ci    ///
136392f3ab15Sopenharmony_ci    ///[`X509_REQ_new`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_new.html
136492f3ab15Sopenharmony_ci    pub fn new() -> Result<X509ReqBuilder, ErrorStack> {
136592f3ab15Sopenharmony_ci        unsafe {
136692f3ab15Sopenharmony_ci            ffi::init();
136792f3ab15Sopenharmony_ci            cvt_p(ffi::X509_REQ_new()).map(|p| X509ReqBuilder(X509Req(p)))
136892f3ab15Sopenharmony_ci        }
136992f3ab15Sopenharmony_ci    }
137092f3ab15Sopenharmony_ci
137192f3ab15Sopenharmony_ci    /// Set the numerical value of the version field.
137292f3ab15Sopenharmony_ci    ///
137392f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_set_version`].
137492f3ab15Sopenharmony_ci    ///
137592f3ab15Sopenharmony_ci    ///[`X509_REQ_set_version`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_set_version.html
137692f3ab15Sopenharmony_ci    #[allow(clippy::useless_conversion)]
137792f3ab15Sopenharmony_ci    pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
137892f3ab15Sopenharmony_ci        unsafe {
137992f3ab15Sopenharmony_ci            cvt(ffi::X509_REQ_set_version(
138092f3ab15Sopenharmony_ci                self.0.as_ptr(),
138192f3ab15Sopenharmony_ci                version as c_long,
138292f3ab15Sopenharmony_ci            ))
138392f3ab15Sopenharmony_ci            .map(|_| ())
138492f3ab15Sopenharmony_ci        }
138592f3ab15Sopenharmony_ci    }
138692f3ab15Sopenharmony_ci
138792f3ab15Sopenharmony_ci    /// Set the issuer name.
138892f3ab15Sopenharmony_ci    ///
138992f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_set_subject_name`].
139092f3ab15Sopenharmony_ci    ///
139192f3ab15Sopenharmony_ci    /// [`X509_REQ_set_subject_name`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_set_subject_name.html
139292f3ab15Sopenharmony_ci    pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
139392f3ab15Sopenharmony_ci        unsafe {
139492f3ab15Sopenharmony_ci            cvt(ffi::X509_REQ_set_subject_name(
139592f3ab15Sopenharmony_ci                self.0.as_ptr(),
139692f3ab15Sopenharmony_ci                subject_name.as_ptr(),
139792f3ab15Sopenharmony_ci            ))
139892f3ab15Sopenharmony_ci            .map(|_| ())
139992f3ab15Sopenharmony_ci        }
140092f3ab15Sopenharmony_ci    }
140192f3ab15Sopenharmony_ci
140292f3ab15Sopenharmony_ci    /// Set the public key.
140392f3ab15Sopenharmony_ci    ///
140492f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_set_pubkey`].
140592f3ab15Sopenharmony_ci    ///
140692f3ab15Sopenharmony_ci    /// [`X509_REQ_set_pubkey`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_set_pubkey.html
140792f3ab15Sopenharmony_ci    pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
140892f3ab15Sopenharmony_ci    where
140992f3ab15Sopenharmony_ci        T: HasPublic,
141092f3ab15Sopenharmony_ci    {
141192f3ab15Sopenharmony_ci        unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
141292f3ab15Sopenharmony_ci    }
141392f3ab15Sopenharmony_ci
141492f3ab15Sopenharmony_ci    /// Return an `X509v3Context`. This context object can be used to construct
141592f3ab15Sopenharmony_ci    /// certain `X509` extensions.
141692f3ab15Sopenharmony_ci    pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> {
141792f3ab15Sopenharmony_ci        unsafe {
141892f3ab15Sopenharmony_ci            let mut ctx = mem::zeroed();
141992f3ab15Sopenharmony_ci
142092f3ab15Sopenharmony_ci            ffi::X509V3_set_ctx(
142192f3ab15Sopenharmony_ci                &mut ctx,
142292f3ab15Sopenharmony_ci                ptr::null_mut(),
142392f3ab15Sopenharmony_ci                ptr::null_mut(),
142492f3ab15Sopenharmony_ci                self.0.as_ptr(),
142592f3ab15Sopenharmony_ci                ptr::null_mut(),
142692f3ab15Sopenharmony_ci                0,
142792f3ab15Sopenharmony_ci            );
142892f3ab15Sopenharmony_ci
142992f3ab15Sopenharmony_ci            // nodb case taken care of since we zeroed ctx above
143092f3ab15Sopenharmony_ci            if let Some(conf) = conf {
143192f3ab15Sopenharmony_ci                ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr());
143292f3ab15Sopenharmony_ci            }
143392f3ab15Sopenharmony_ci
143492f3ab15Sopenharmony_ci            X509v3Context(ctx, PhantomData)
143592f3ab15Sopenharmony_ci        }
143692f3ab15Sopenharmony_ci    }
143792f3ab15Sopenharmony_ci
143892f3ab15Sopenharmony_ci    /// Permits any number of extension fields to be added to the certificate.
143992f3ab15Sopenharmony_ci    pub fn add_extensions(
144092f3ab15Sopenharmony_ci        &mut self,
144192f3ab15Sopenharmony_ci        extensions: &StackRef<X509Extension>,
144292f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
144392f3ab15Sopenharmony_ci        unsafe {
144492f3ab15Sopenharmony_ci            cvt(ffi::X509_REQ_add_extensions(
144592f3ab15Sopenharmony_ci                self.0.as_ptr(),
144692f3ab15Sopenharmony_ci                extensions.as_ptr(),
144792f3ab15Sopenharmony_ci            ))
144892f3ab15Sopenharmony_ci            .map(|_| ())
144992f3ab15Sopenharmony_ci        }
145092f3ab15Sopenharmony_ci    }
145192f3ab15Sopenharmony_ci
145292f3ab15Sopenharmony_ci    /// Sign the request using a private key.
145392f3ab15Sopenharmony_ci    ///
145492f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_sign`].
145592f3ab15Sopenharmony_ci    ///
145692f3ab15Sopenharmony_ci    /// [`X509_REQ_sign`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_sign.html
145792f3ab15Sopenharmony_ci    pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
145892f3ab15Sopenharmony_ci    where
145992f3ab15Sopenharmony_ci        T: HasPrivate,
146092f3ab15Sopenharmony_ci    {
146192f3ab15Sopenharmony_ci        unsafe {
146292f3ab15Sopenharmony_ci            cvt(ffi::X509_REQ_sign(
146392f3ab15Sopenharmony_ci                self.0.as_ptr(),
146492f3ab15Sopenharmony_ci                key.as_ptr(),
146592f3ab15Sopenharmony_ci                hash.as_ptr(),
146692f3ab15Sopenharmony_ci            ))
146792f3ab15Sopenharmony_ci            .map(|_| ())
146892f3ab15Sopenharmony_ci        }
146992f3ab15Sopenharmony_ci    }
147092f3ab15Sopenharmony_ci
147192f3ab15Sopenharmony_ci    /// Returns the `X509Req`.
147292f3ab15Sopenharmony_ci    pub fn build(self) -> X509Req {
147392f3ab15Sopenharmony_ci        self.0
147492f3ab15Sopenharmony_ci    }
147592f3ab15Sopenharmony_ci}
147692f3ab15Sopenharmony_ci
147792f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
147892f3ab15Sopenharmony_ci    type CType = ffi::X509_REQ;
147992f3ab15Sopenharmony_ci    fn drop = ffi::X509_REQ_free;
148092f3ab15Sopenharmony_ci
148192f3ab15Sopenharmony_ci    /// An `X509` certificate request.
148292f3ab15Sopenharmony_ci    pub struct X509Req;
148392f3ab15Sopenharmony_ci    /// Reference to `X509Req`.
148492f3ab15Sopenharmony_ci    pub struct X509ReqRef;
148592f3ab15Sopenharmony_ci}
148692f3ab15Sopenharmony_ci
148792f3ab15Sopenharmony_ciimpl X509Req {
148892f3ab15Sopenharmony_ci    /// A builder for `X509Req`.
148992f3ab15Sopenharmony_ci    pub fn builder() -> Result<X509ReqBuilder, ErrorStack> {
149092f3ab15Sopenharmony_ci        X509ReqBuilder::new()
149192f3ab15Sopenharmony_ci    }
149292f3ab15Sopenharmony_ci
149392f3ab15Sopenharmony_ci    from_pem! {
149492f3ab15Sopenharmony_ci        /// Deserializes a PEM-encoded PKCS#10 certificate request structure.
149592f3ab15Sopenharmony_ci        ///
149692f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
149792f3ab15Sopenharmony_ci        ///
149892f3ab15Sopenharmony_ci        /// This corresponds to [`PEM_read_bio_X509_REQ`].
149992f3ab15Sopenharmony_ci        ///
150092f3ab15Sopenharmony_ci        /// [`PEM_read_bio_X509_REQ`]: https://www.openssl.org/docs/manmaster/crypto/PEM_read_bio_X509_REQ.html
150192f3ab15Sopenharmony_ci        from_pem,
150292f3ab15Sopenharmony_ci        X509Req,
150392f3ab15Sopenharmony_ci        ffi::PEM_read_bio_X509_REQ
150492f3ab15Sopenharmony_ci    }
150592f3ab15Sopenharmony_ci
150692f3ab15Sopenharmony_ci    from_der! {
150792f3ab15Sopenharmony_ci        /// Deserializes a DER-encoded PKCS#10 certificate request structure.
150892f3ab15Sopenharmony_ci        ///
150992f3ab15Sopenharmony_ci        /// This corresponds to [`d2i_X509_REQ`].
151092f3ab15Sopenharmony_ci        ///
151192f3ab15Sopenharmony_ci        /// [`d2i_X509_REQ`]: https://www.openssl.org/docs/manmaster/crypto/d2i_X509_REQ.html
151292f3ab15Sopenharmony_ci        from_der,
151392f3ab15Sopenharmony_ci        X509Req,
151492f3ab15Sopenharmony_ci        ffi::d2i_X509_REQ
151592f3ab15Sopenharmony_ci    }
151692f3ab15Sopenharmony_ci}
151792f3ab15Sopenharmony_ci
151892f3ab15Sopenharmony_ciimpl X509ReqRef {
151992f3ab15Sopenharmony_ci    to_pem! {
152092f3ab15Sopenharmony_ci        /// Serializes the certificate request to a PEM-encoded PKCS#10 structure.
152192f3ab15Sopenharmony_ci        ///
152292f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
152392f3ab15Sopenharmony_ci        ///
152492f3ab15Sopenharmony_ci        /// This corresponds to [`PEM_write_bio_X509_REQ`].
152592f3ab15Sopenharmony_ci        ///
152692f3ab15Sopenharmony_ci        /// [`PEM_write_bio_X509_REQ`]: https://www.openssl.org/docs/manmaster/crypto/PEM_write_bio_X509_REQ.html
152792f3ab15Sopenharmony_ci        to_pem,
152892f3ab15Sopenharmony_ci        ffi::PEM_write_bio_X509_REQ
152992f3ab15Sopenharmony_ci    }
153092f3ab15Sopenharmony_ci
153192f3ab15Sopenharmony_ci    to_der! {
153292f3ab15Sopenharmony_ci        /// Serializes the certificate request to a DER-encoded PKCS#10 structure.
153392f3ab15Sopenharmony_ci        ///
153492f3ab15Sopenharmony_ci        /// This corresponds to [`i2d_X509_REQ`].
153592f3ab15Sopenharmony_ci        ///
153692f3ab15Sopenharmony_ci        /// [`i2d_X509_REQ`]: https://www.openssl.org/docs/manmaster/crypto/i2d_X509_REQ.html
153792f3ab15Sopenharmony_ci        to_der,
153892f3ab15Sopenharmony_ci        ffi::i2d_X509_REQ
153992f3ab15Sopenharmony_ci    }
154092f3ab15Sopenharmony_ci
154192f3ab15Sopenharmony_ci    to_pem! {
154292f3ab15Sopenharmony_ci        /// Converts the request to human readable text.
154392f3ab15Sopenharmony_ci        #[corresponds(X509_Req_print)]
154492f3ab15Sopenharmony_ci        to_text,
154592f3ab15Sopenharmony_ci        ffi::X509_REQ_print
154692f3ab15Sopenharmony_ci    }
154792f3ab15Sopenharmony_ci
154892f3ab15Sopenharmony_ci    /// Returns the numerical value of the version field of the certificate request.
154992f3ab15Sopenharmony_ci    ///
155092f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_get_version`]
155192f3ab15Sopenharmony_ci    ///
155292f3ab15Sopenharmony_ci    /// [`X509_REQ_get_version`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_get_version.html
155392f3ab15Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
155492f3ab15Sopenharmony_ci    pub fn version(&self) -> i32 {
155592f3ab15Sopenharmony_ci        unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
155692f3ab15Sopenharmony_ci    }
155792f3ab15Sopenharmony_ci
155892f3ab15Sopenharmony_ci    /// Returns the subject name of the certificate request.
155992f3ab15Sopenharmony_ci    ///
156092f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_get_subject_name`]
156192f3ab15Sopenharmony_ci    ///
156292f3ab15Sopenharmony_ci    /// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_get_subject_name.html
156392f3ab15Sopenharmony_ci    pub fn subject_name(&self) -> &X509NameRef {
156492f3ab15Sopenharmony_ci        unsafe {
156592f3ab15Sopenharmony_ci            let name = X509_REQ_get_subject_name(self.as_ptr());
156692f3ab15Sopenharmony_ci            X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null")
156792f3ab15Sopenharmony_ci        }
156892f3ab15Sopenharmony_ci    }
156992f3ab15Sopenharmony_ci
157092f3ab15Sopenharmony_ci    /// Returns the public key of the certificate request.
157192f3ab15Sopenharmony_ci    ///
157292f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_get_pubkey"]
157392f3ab15Sopenharmony_ci    ///
157492f3ab15Sopenharmony_ci    /// [`X509_REQ_get_pubkey`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_get_pubkey.html
157592f3ab15Sopenharmony_ci    pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
157692f3ab15Sopenharmony_ci        unsafe {
157792f3ab15Sopenharmony_ci            let key = cvt_p(ffi::X509_REQ_get_pubkey(self.as_ptr()))?;
157892f3ab15Sopenharmony_ci            Ok(PKey::from_ptr(key))
157992f3ab15Sopenharmony_ci        }
158092f3ab15Sopenharmony_ci    }
158192f3ab15Sopenharmony_ci
158292f3ab15Sopenharmony_ci    /// Check if the certificate request is signed using the given public key.
158392f3ab15Sopenharmony_ci    ///
158492f3ab15Sopenharmony_ci    /// Returns `true` if verification succeeds.
158592f3ab15Sopenharmony_ci    ///
158692f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_verify"].
158792f3ab15Sopenharmony_ci    ///
158892f3ab15Sopenharmony_ci    /// [`X509_REQ_verify`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_verify.html
158992f3ab15Sopenharmony_ci    pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
159092f3ab15Sopenharmony_ci    where
159192f3ab15Sopenharmony_ci        T: HasPublic,
159292f3ab15Sopenharmony_ci    {
159392f3ab15Sopenharmony_ci        unsafe { cvt_n(ffi::X509_REQ_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
159492f3ab15Sopenharmony_ci    }
159592f3ab15Sopenharmony_ci
159692f3ab15Sopenharmony_ci    /// Returns the extensions of the certificate request.
159792f3ab15Sopenharmony_ci    ///
159892f3ab15Sopenharmony_ci    /// This corresponds to [`X509_REQ_get_extensions"]
159992f3ab15Sopenharmony_ci    pub fn extensions(&self) -> Result<Stack<X509Extension>, ErrorStack> {
160092f3ab15Sopenharmony_ci        unsafe {
160192f3ab15Sopenharmony_ci            let extensions = cvt_p(ffi::X509_REQ_get_extensions(self.as_ptr()))?;
160292f3ab15Sopenharmony_ci            Ok(Stack::from_ptr(extensions))
160392f3ab15Sopenharmony_ci        }
160492f3ab15Sopenharmony_ci    }
160592f3ab15Sopenharmony_ci}
160692f3ab15Sopenharmony_ci
160792f3ab15Sopenharmony_ci/// The reason that a certificate was revoked.
160892f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
160992f3ab15Sopenharmony_cipub struct CrlReason(c_int);
161092f3ab15Sopenharmony_ci
161192f3ab15Sopenharmony_ci#[allow(missing_docs)] // no need to document the constants
161292f3ab15Sopenharmony_ciimpl CrlReason {
161392f3ab15Sopenharmony_ci    pub const UNSPECIFIED: CrlReason = CrlReason(ffi::CRL_REASON_UNSPECIFIED);
161492f3ab15Sopenharmony_ci    pub const KEY_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_KEY_COMPROMISE);
161592f3ab15Sopenharmony_ci    pub const CA_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_CA_COMPROMISE);
161692f3ab15Sopenharmony_ci    pub const AFFILIATION_CHANGED: CrlReason = CrlReason(ffi::CRL_REASON_AFFILIATION_CHANGED);
161792f3ab15Sopenharmony_ci    pub const SUPERSEDED: CrlReason = CrlReason(ffi::CRL_REASON_SUPERSEDED);
161892f3ab15Sopenharmony_ci    pub const CESSATION_OF_OPERATION: CrlReason = CrlReason(ffi::CRL_REASON_CESSATION_OF_OPERATION);
161992f3ab15Sopenharmony_ci    pub const CERTIFICATE_HOLD: CrlReason = CrlReason(ffi::CRL_REASON_CERTIFICATE_HOLD);
162092f3ab15Sopenharmony_ci    pub const REMOVE_FROM_CRL: CrlReason = CrlReason(ffi::CRL_REASON_REMOVE_FROM_CRL);
162192f3ab15Sopenharmony_ci    pub const PRIVILEGE_WITHDRAWN: CrlReason = CrlReason(ffi::CRL_REASON_PRIVILEGE_WITHDRAWN);
162292f3ab15Sopenharmony_ci    pub const AA_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_AA_COMPROMISE);
162392f3ab15Sopenharmony_ci
162492f3ab15Sopenharmony_ci    /// Constructs an `CrlReason` from a raw OpenSSL value.
162592f3ab15Sopenharmony_ci    pub const fn from_raw(value: c_int) -> Self {
162692f3ab15Sopenharmony_ci        CrlReason(value)
162792f3ab15Sopenharmony_ci    }
162892f3ab15Sopenharmony_ci
162992f3ab15Sopenharmony_ci    /// Returns the raw OpenSSL value represented by this type.
163092f3ab15Sopenharmony_ci    pub const fn as_raw(&self) -> c_int {
163192f3ab15Sopenharmony_ci        self.0
163292f3ab15Sopenharmony_ci    }
163392f3ab15Sopenharmony_ci}
163492f3ab15Sopenharmony_ci
163592f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
163692f3ab15Sopenharmony_ci    type CType = ffi::X509_REVOKED;
163792f3ab15Sopenharmony_ci    fn drop = ffi::X509_REVOKED_free;
163892f3ab15Sopenharmony_ci
163992f3ab15Sopenharmony_ci    /// An `X509` certificate revocation status.
164092f3ab15Sopenharmony_ci    pub struct X509Revoked;
164192f3ab15Sopenharmony_ci    /// Reference to `X509Revoked`.
164292f3ab15Sopenharmony_ci    pub struct X509RevokedRef;
164392f3ab15Sopenharmony_ci}
164492f3ab15Sopenharmony_ci
164592f3ab15Sopenharmony_ciimpl Stackable for X509Revoked {
164692f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_X509_REVOKED;
164792f3ab15Sopenharmony_ci}
164892f3ab15Sopenharmony_ci
164992f3ab15Sopenharmony_ciimpl X509Revoked {
165092f3ab15Sopenharmony_ci    from_der! {
165192f3ab15Sopenharmony_ci        /// Deserializes a DER-encoded certificate revocation status
165292f3ab15Sopenharmony_ci        #[corresponds(d2i_X509_REVOKED)]
165392f3ab15Sopenharmony_ci        from_der,
165492f3ab15Sopenharmony_ci        X509Revoked,
165592f3ab15Sopenharmony_ci        ffi::d2i_X509_REVOKED
165692f3ab15Sopenharmony_ci    }
165792f3ab15Sopenharmony_ci}
165892f3ab15Sopenharmony_ci
165992f3ab15Sopenharmony_ciimpl X509RevokedRef {
166092f3ab15Sopenharmony_ci    to_der! {
166192f3ab15Sopenharmony_ci        /// Serializes the certificate request to a DER-encoded certificate revocation status
166292f3ab15Sopenharmony_ci        #[corresponds(d2i_X509_REVOKED)]
166392f3ab15Sopenharmony_ci        to_der,
166492f3ab15Sopenharmony_ci        ffi::i2d_X509_REVOKED
166592f3ab15Sopenharmony_ci    }
166692f3ab15Sopenharmony_ci
166792f3ab15Sopenharmony_ci    /// Copies the entry to a new `X509Revoked`.
166892f3ab15Sopenharmony_ci    #[corresponds(X509_NAME_dup)]
166992f3ab15Sopenharmony_ci    #[cfg(any(boringssl, ossl110, libressl270))]
167092f3ab15Sopenharmony_ci    pub fn to_owned(&self) -> Result<X509Revoked, ErrorStack> {
167192f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::X509_REVOKED_dup(self.as_ptr())).map(|n| X509Revoked::from_ptr(n)) }
167292f3ab15Sopenharmony_ci    }
167392f3ab15Sopenharmony_ci
167492f3ab15Sopenharmony_ci    /// Get the date that the certificate was revoked
167592f3ab15Sopenharmony_ci    #[corresponds(X509_REVOKED_get0_revocationDate)]
167692f3ab15Sopenharmony_ci    pub fn revocation_date(&self) -> &Asn1TimeRef {
167792f3ab15Sopenharmony_ci        unsafe {
167892f3ab15Sopenharmony_ci            let r = X509_REVOKED_get0_revocationDate(self.as_ptr() as *const _);
167992f3ab15Sopenharmony_ci            assert!(!r.is_null());
168092f3ab15Sopenharmony_ci            Asn1TimeRef::from_ptr(r as *mut _)
168192f3ab15Sopenharmony_ci        }
168292f3ab15Sopenharmony_ci    }
168392f3ab15Sopenharmony_ci
168492f3ab15Sopenharmony_ci    /// Get the serial number of the revoked certificate
168592f3ab15Sopenharmony_ci    #[corresponds(X509_REVOKED_get0_serialNumber)]
168692f3ab15Sopenharmony_ci    pub fn serial_number(&self) -> &Asn1IntegerRef {
168792f3ab15Sopenharmony_ci        unsafe {
168892f3ab15Sopenharmony_ci            let r = X509_REVOKED_get0_serialNumber(self.as_ptr() as *const _);
168992f3ab15Sopenharmony_ci            assert!(!r.is_null());
169092f3ab15Sopenharmony_ci            Asn1IntegerRef::from_ptr(r as *mut _)
169192f3ab15Sopenharmony_ci        }
169292f3ab15Sopenharmony_ci    }
169392f3ab15Sopenharmony_ci
169492f3ab15Sopenharmony_ci    /// Get the criticality and value of an extension.
169592f3ab15Sopenharmony_ci    ///
169692f3ab15Sopenharmony_ci    /// This returns None if the extension is not present or occurs multiple times.
169792f3ab15Sopenharmony_ci    #[corresponds(X509_REVOKED_get_ext_d2i)]
169892f3ab15Sopenharmony_ci    pub fn extension<T: ExtensionType>(&self) -> Result<Option<(bool, T::Output)>, ErrorStack> {
169992f3ab15Sopenharmony_ci        let mut critical = -1;
170092f3ab15Sopenharmony_ci        let out = unsafe {
170192f3ab15Sopenharmony_ci            // SAFETY: self.as_ptr() is a valid pointer to an X509_REVOKED.
170292f3ab15Sopenharmony_ci            let ext = ffi::X509_REVOKED_get_ext_d2i(
170392f3ab15Sopenharmony_ci                self.as_ptr(),
170492f3ab15Sopenharmony_ci                T::NID.as_raw(),
170592f3ab15Sopenharmony_ci                &mut critical as *mut _,
170692f3ab15Sopenharmony_ci                ptr::null_mut(),
170792f3ab15Sopenharmony_ci            );
170892f3ab15Sopenharmony_ci            // SAFETY: Extensions's contract promises that the type returned by
170992f3ab15Sopenharmony_ci            // OpenSSL here is T::Output.
171092f3ab15Sopenharmony_ci            T::Output::from_ptr_opt(ext as *mut _)
171192f3ab15Sopenharmony_ci        };
171292f3ab15Sopenharmony_ci        match (critical, out) {
171392f3ab15Sopenharmony_ci            (0, Some(out)) => Ok(Some((false, out))),
171492f3ab15Sopenharmony_ci            (1, Some(out)) => Ok(Some((true, out))),
171592f3ab15Sopenharmony_ci            // -1 means the extension wasn't found, -2 means multiple were found.
171692f3ab15Sopenharmony_ci            (-1 | -2, _) => Ok(None),
171792f3ab15Sopenharmony_ci            // A critical value of 0 or 1 suggests success, but a null pointer
171892f3ab15Sopenharmony_ci            // was returned so something went wrong.
171992f3ab15Sopenharmony_ci            (0 | 1, None) => Err(ErrorStack::get()),
172092f3ab15Sopenharmony_ci            (c_int::MIN..=-2 | 2.., _) => panic!("OpenSSL should only return -2, -1, 0, or 1 for an extension's criticality but it returned {}", critical),
172192f3ab15Sopenharmony_ci        }
172292f3ab15Sopenharmony_ci    }
172392f3ab15Sopenharmony_ci}
172492f3ab15Sopenharmony_ci
172592f3ab15Sopenharmony_ci/// The CRL entry extension identifying the reason for revocation see [`CrlReason`],
172692f3ab15Sopenharmony_ci/// this is as defined in RFC 5280 Section 5.3.1.
172792f3ab15Sopenharmony_cipub enum ReasonCode {}
172892f3ab15Sopenharmony_ci
172992f3ab15Sopenharmony_ci// SAFETY: CertificateIssuer is defined to be a stack of GeneralName in the RFC
173092f3ab15Sopenharmony_ci// and in OpenSSL.
173192f3ab15Sopenharmony_ciunsafe impl ExtensionType for ReasonCode {
173292f3ab15Sopenharmony_ci    const NID: Nid = Nid::from_raw(ffi::NID_crl_reason);
173392f3ab15Sopenharmony_ci
173492f3ab15Sopenharmony_ci    type Output = Asn1Enumerated;
173592f3ab15Sopenharmony_ci}
173692f3ab15Sopenharmony_ci
173792f3ab15Sopenharmony_ci/// The CRL entry extension identifying the issuer of a certificate used in
173892f3ab15Sopenharmony_ci/// indirect CRLs, as defined in RFC 5280 Section 5.3.3.
173992f3ab15Sopenharmony_cipub enum CertificateIssuer {}
174092f3ab15Sopenharmony_ci
174192f3ab15Sopenharmony_ci// SAFETY: CertificateIssuer is defined to be a stack of GeneralName in the RFC
174292f3ab15Sopenharmony_ci// and in OpenSSL.
174392f3ab15Sopenharmony_ciunsafe impl ExtensionType for CertificateIssuer {
174492f3ab15Sopenharmony_ci    const NID: Nid = Nid::from_raw(ffi::NID_certificate_issuer);
174592f3ab15Sopenharmony_ci
174692f3ab15Sopenharmony_ci    type Output = Stack<GeneralName>;
174792f3ab15Sopenharmony_ci}
174892f3ab15Sopenharmony_ci
174992f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
175092f3ab15Sopenharmony_ci    type CType = ffi::X509_CRL;
175192f3ab15Sopenharmony_ci    fn drop = ffi::X509_CRL_free;
175292f3ab15Sopenharmony_ci
175392f3ab15Sopenharmony_ci    /// An `X509` certificate revocation list.
175492f3ab15Sopenharmony_ci    pub struct X509Crl;
175592f3ab15Sopenharmony_ci    /// Reference to `X509Crl`.
175692f3ab15Sopenharmony_ci    pub struct X509CrlRef;
175792f3ab15Sopenharmony_ci}
175892f3ab15Sopenharmony_ci
175992f3ab15Sopenharmony_ci/// The status of a certificate in a revoction list
176092f3ab15Sopenharmony_ci///
176192f3ab15Sopenharmony_ci/// Corresponds to the return value from the [`X509_CRL_get0_by_*`] methods.
176292f3ab15Sopenharmony_ci///
176392f3ab15Sopenharmony_ci/// [`X509_CRL_get0_by_*`]: https://www.openssl.org/docs/man1.1.0/man3/X509_CRL_get0_by_serial.html
176492f3ab15Sopenharmony_cipub enum CrlStatus<'a> {
176592f3ab15Sopenharmony_ci    /// The certificate is not present in the list
176692f3ab15Sopenharmony_ci    NotRevoked,
176792f3ab15Sopenharmony_ci    /// The certificate is in the list and is revoked
176892f3ab15Sopenharmony_ci    Revoked(&'a X509RevokedRef),
176992f3ab15Sopenharmony_ci    /// The certificate is in the list, but has the "removeFromCrl" status.
177092f3ab15Sopenharmony_ci    ///
177192f3ab15Sopenharmony_ci    /// This can occur if the certificate was revoked with the "CertificateHold"
177292f3ab15Sopenharmony_ci    /// reason, and has since been unrevoked.
177392f3ab15Sopenharmony_ci    RemoveFromCrl(&'a X509RevokedRef),
177492f3ab15Sopenharmony_ci}
177592f3ab15Sopenharmony_ci
177692f3ab15Sopenharmony_ciimpl<'a> CrlStatus<'a> {
177792f3ab15Sopenharmony_ci    // Helper used by the X509_CRL_get0_by_* methods to convert their return
177892f3ab15Sopenharmony_ci    // value to the status enum.
177992f3ab15Sopenharmony_ci    // Safety note: the returned CrlStatus must not outlive the owner of the
178092f3ab15Sopenharmony_ci    // revoked_entry pointer.
178192f3ab15Sopenharmony_ci    unsafe fn from_ffi_status(
178292f3ab15Sopenharmony_ci        status: c_int,
178392f3ab15Sopenharmony_ci        revoked_entry: *mut ffi::X509_REVOKED,
178492f3ab15Sopenharmony_ci    ) -> CrlStatus<'a> {
178592f3ab15Sopenharmony_ci        match status {
178692f3ab15Sopenharmony_ci            0 => CrlStatus::NotRevoked,
178792f3ab15Sopenharmony_ci            1 => {
178892f3ab15Sopenharmony_ci                assert!(!revoked_entry.is_null());
178992f3ab15Sopenharmony_ci                CrlStatus::Revoked(X509RevokedRef::from_ptr(revoked_entry))
179092f3ab15Sopenharmony_ci            }
179192f3ab15Sopenharmony_ci            2 => {
179292f3ab15Sopenharmony_ci                assert!(!revoked_entry.is_null());
179392f3ab15Sopenharmony_ci                CrlStatus::RemoveFromCrl(X509RevokedRef::from_ptr(revoked_entry))
179492f3ab15Sopenharmony_ci            }
179592f3ab15Sopenharmony_ci            _ => unreachable!(
179692f3ab15Sopenharmony_ci                "{}",
179792f3ab15Sopenharmony_ci                "X509_CRL_get0_by_{{serial,cert}} should only return 0, 1, or 2."
179892f3ab15Sopenharmony_ci            ),
179992f3ab15Sopenharmony_ci        }
180092f3ab15Sopenharmony_ci    }
180192f3ab15Sopenharmony_ci}
180292f3ab15Sopenharmony_ci
180392f3ab15Sopenharmony_ciimpl X509Crl {
180492f3ab15Sopenharmony_ci    from_pem! {
180592f3ab15Sopenharmony_ci        /// Deserializes a PEM-encoded Certificate Revocation List
180692f3ab15Sopenharmony_ci        ///
180792f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN X509 CRL-----`.
180892f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_X509_CRL)]
180992f3ab15Sopenharmony_ci        from_pem,
181092f3ab15Sopenharmony_ci        X509Crl,
181192f3ab15Sopenharmony_ci        ffi::PEM_read_bio_X509_CRL
181292f3ab15Sopenharmony_ci    }
181392f3ab15Sopenharmony_ci
181492f3ab15Sopenharmony_ci    from_der! {
181592f3ab15Sopenharmony_ci        /// Deserializes a DER-encoded Certificate Revocation List
181692f3ab15Sopenharmony_ci        #[corresponds(d2i_X509_CRL)]
181792f3ab15Sopenharmony_ci        from_der,
181892f3ab15Sopenharmony_ci        X509Crl,
181992f3ab15Sopenharmony_ci        ffi::d2i_X509_CRL
182092f3ab15Sopenharmony_ci    }
182192f3ab15Sopenharmony_ci}
182292f3ab15Sopenharmony_ci
182392f3ab15Sopenharmony_ciimpl X509CrlRef {
182492f3ab15Sopenharmony_ci    to_pem! {
182592f3ab15Sopenharmony_ci        /// Serializes the certificate request to a PEM-encoded Certificate Revocation List.
182692f3ab15Sopenharmony_ci        ///
182792f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN X509 CRL-----`.
182892f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_X509_CRL)]
182992f3ab15Sopenharmony_ci        to_pem,
183092f3ab15Sopenharmony_ci        ffi::PEM_write_bio_X509_CRL
183192f3ab15Sopenharmony_ci    }
183292f3ab15Sopenharmony_ci
183392f3ab15Sopenharmony_ci    to_der! {
183492f3ab15Sopenharmony_ci        /// Serializes the certificate request to a DER-encoded Certificate Revocation List.
183592f3ab15Sopenharmony_ci        #[corresponds(i2d_X509_CRL)]
183692f3ab15Sopenharmony_ci        to_der,
183792f3ab15Sopenharmony_ci        ffi::i2d_X509_CRL
183892f3ab15Sopenharmony_ci    }
183992f3ab15Sopenharmony_ci
184092f3ab15Sopenharmony_ci    /// Get the stack of revocation entries
184192f3ab15Sopenharmony_ci    pub fn get_revoked(&self) -> Option<&StackRef<X509Revoked>> {
184292f3ab15Sopenharmony_ci        unsafe {
184392f3ab15Sopenharmony_ci            let revoked = X509_CRL_get_REVOKED(self.as_ptr());
184492f3ab15Sopenharmony_ci            if revoked.is_null() {
184592f3ab15Sopenharmony_ci                None
184692f3ab15Sopenharmony_ci            } else {
184792f3ab15Sopenharmony_ci                Some(StackRef::from_ptr(revoked))
184892f3ab15Sopenharmony_ci            }
184992f3ab15Sopenharmony_ci        }
185092f3ab15Sopenharmony_ci    }
185192f3ab15Sopenharmony_ci
185292f3ab15Sopenharmony_ci    /// Returns the CRL's `lastUpdate` time.
185392f3ab15Sopenharmony_ci    #[corresponds(X509_CRL_get0_lastUpdate)]
185492f3ab15Sopenharmony_ci    pub fn last_update(&self) -> &Asn1TimeRef {
185592f3ab15Sopenharmony_ci        unsafe {
185692f3ab15Sopenharmony_ci            let date = X509_CRL_get0_lastUpdate(self.as_ptr());
185792f3ab15Sopenharmony_ci            assert!(!date.is_null());
185892f3ab15Sopenharmony_ci            Asn1TimeRef::from_ptr(date as *mut _)
185992f3ab15Sopenharmony_ci        }
186092f3ab15Sopenharmony_ci    }
186192f3ab15Sopenharmony_ci
186292f3ab15Sopenharmony_ci    /// Returns the CRL's `nextUpdate` time.
186392f3ab15Sopenharmony_ci    ///
186492f3ab15Sopenharmony_ci    /// If the `nextUpdate` field is missing, returns `None`.
186592f3ab15Sopenharmony_ci    #[corresponds(X509_CRL_get0_nextUpdate)]
186692f3ab15Sopenharmony_ci    pub fn next_update(&self) -> Option<&Asn1TimeRef> {
186792f3ab15Sopenharmony_ci        unsafe {
186892f3ab15Sopenharmony_ci            let date = X509_CRL_get0_nextUpdate(self.as_ptr());
186992f3ab15Sopenharmony_ci            Asn1TimeRef::from_const_ptr_opt(date)
187092f3ab15Sopenharmony_ci        }
187192f3ab15Sopenharmony_ci    }
187292f3ab15Sopenharmony_ci
187392f3ab15Sopenharmony_ci    /// Get the revocation status of a certificate by its serial number
187492f3ab15Sopenharmony_ci    #[corresponds(X509_CRL_get0_by_serial)]
187592f3ab15Sopenharmony_ci    pub fn get_by_serial<'a>(&'a self, serial: &Asn1IntegerRef) -> CrlStatus<'a> {
187692f3ab15Sopenharmony_ci        unsafe {
187792f3ab15Sopenharmony_ci            let mut ret = ptr::null_mut::<ffi::X509_REVOKED>();
187892f3ab15Sopenharmony_ci            let status =
187992f3ab15Sopenharmony_ci                ffi::X509_CRL_get0_by_serial(self.as_ptr(), &mut ret as *mut _, serial.as_ptr());
188092f3ab15Sopenharmony_ci            CrlStatus::from_ffi_status(status, ret)
188192f3ab15Sopenharmony_ci        }
188292f3ab15Sopenharmony_ci    }
188392f3ab15Sopenharmony_ci
188492f3ab15Sopenharmony_ci    /// Get the revocation status of a certificate
188592f3ab15Sopenharmony_ci    #[corresponds(X509_CRL_get0_by_cert)]
188692f3ab15Sopenharmony_ci    pub fn get_by_cert<'a>(&'a self, cert: &X509) -> CrlStatus<'a> {
188792f3ab15Sopenharmony_ci        unsafe {
188892f3ab15Sopenharmony_ci            let mut ret = ptr::null_mut::<ffi::X509_REVOKED>();
188992f3ab15Sopenharmony_ci            let status =
189092f3ab15Sopenharmony_ci                ffi::X509_CRL_get0_by_cert(self.as_ptr(), &mut ret as *mut _, cert.as_ptr());
189192f3ab15Sopenharmony_ci            CrlStatus::from_ffi_status(status, ret)
189292f3ab15Sopenharmony_ci        }
189392f3ab15Sopenharmony_ci    }
189492f3ab15Sopenharmony_ci
189592f3ab15Sopenharmony_ci    /// Get the issuer name from the revocation list.
189692f3ab15Sopenharmony_ci    #[corresponds(X509_CRL_get_issuer)]
189792f3ab15Sopenharmony_ci    pub fn issuer_name(&self) -> &X509NameRef {
189892f3ab15Sopenharmony_ci        unsafe {
189992f3ab15Sopenharmony_ci            let name = X509_CRL_get_issuer(self.as_ptr());
190092f3ab15Sopenharmony_ci            assert!(!name.is_null());
190192f3ab15Sopenharmony_ci            X509NameRef::from_ptr(name)
190292f3ab15Sopenharmony_ci        }
190392f3ab15Sopenharmony_ci    }
190492f3ab15Sopenharmony_ci
190592f3ab15Sopenharmony_ci    /// Check if the CRL is signed using the given public key.
190692f3ab15Sopenharmony_ci    ///
190792f3ab15Sopenharmony_ci    /// Only the signature is checked: no other checks (such as certificate chain validity)
190892f3ab15Sopenharmony_ci    /// are performed.
190992f3ab15Sopenharmony_ci    ///
191092f3ab15Sopenharmony_ci    /// Returns `true` if verification succeeds.
191192f3ab15Sopenharmony_ci    #[corresponds(X509_CRL_verify)]
191292f3ab15Sopenharmony_ci    pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
191392f3ab15Sopenharmony_ci    where
191492f3ab15Sopenharmony_ci        T: HasPublic,
191592f3ab15Sopenharmony_ci    {
191692f3ab15Sopenharmony_ci        unsafe { cvt_n(ffi::X509_CRL_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
191792f3ab15Sopenharmony_ci    }
191892f3ab15Sopenharmony_ci}
191992f3ab15Sopenharmony_ci
192092f3ab15Sopenharmony_ci/// The result of peer certificate verification.
192192f3ab15Sopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq)]
192292f3ab15Sopenharmony_cipub struct X509VerifyResult(c_int);
192392f3ab15Sopenharmony_ci
192492f3ab15Sopenharmony_ciimpl fmt::Debug for X509VerifyResult {
192592f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
192692f3ab15Sopenharmony_ci        fmt.debug_struct("X509VerifyResult")
192792f3ab15Sopenharmony_ci            .field("code", &self.0)
192892f3ab15Sopenharmony_ci            .field("error", &self.error_string())
192992f3ab15Sopenharmony_ci            .finish()
193092f3ab15Sopenharmony_ci    }
193192f3ab15Sopenharmony_ci}
193292f3ab15Sopenharmony_ci
193392f3ab15Sopenharmony_ciimpl fmt::Display for X509VerifyResult {
193492f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
193592f3ab15Sopenharmony_ci        fmt.write_str(self.error_string())
193692f3ab15Sopenharmony_ci    }
193792f3ab15Sopenharmony_ci}
193892f3ab15Sopenharmony_ci
193992f3ab15Sopenharmony_ciimpl Error for X509VerifyResult {}
194092f3ab15Sopenharmony_ci
194192f3ab15Sopenharmony_ciimpl X509VerifyResult {
194292f3ab15Sopenharmony_ci    /// Creates an `X509VerifyResult` from a raw error number.
194392f3ab15Sopenharmony_ci    ///
194492f3ab15Sopenharmony_ci    /// # Safety
194592f3ab15Sopenharmony_ci    ///
194692f3ab15Sopenharmony_ci    /// Some methods on `X509VerifyResult` are not thread safe if the error
194792f3ab15Sopenharmony_ci    /// number is invalid.
194892f3ab15Sopenharmony_ci    pub unsafe fn from_raw(err: c_int) -> X509VerifyResult {
194992f3ab15Sopenharmony_ci        X509VerifyResult(err)
195092f3ab15Sopenharmony_ci    }
195192f3ab15Sopenharmony_ci
195292f3ab15Sopenharmony_ci    /// Return the integer representation of an `X509VerifyResult`.
195392f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
195492f3ab15Sopenharmony_ci    pub fn as_raw(&self) -> c_int {
195592f3ab15Sopenharmony_ci        self.0
195692f3ab15Sopenharmony_ci    }
195792f3ab15Sopenharmony_ci
195892f3ab15Sopenharmony_ci    /// Return a human readable error string from the verification error.
195992f3ab15Sopenharmony_ci    ///
196092f3ab15Sopenharmony_ci    /// This corresponds to [`X509_verify_cert_error_string`].
196192f3ab15Sopenharmony_ci    ///
196292f3ab15Sopenharmony_ci    /// [`X509_verify_cert_error_string`]: https://www.openssl.org/docs/manmaster/crypto/X509_verify_cert_error_string.html
196392f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
196492f3ab15Sopenharmony_ci    pub fn error_string(&self) -> &'static str {
196592f3ab15Sopenharmony_ci        ffi::init();
196692f3ab15Sopenharmony_ci
196792f3ab15Sopenharmony_ci        unsafe {
196892f3ab15Sopenharmony_ci            let s = ffi::X509_verify_cert_error_string(self.0 as c_long);
196992f3ab15Sopenharmony_ci            str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
197092f3ab15Sopenharmony_ci        }
197192f3ab15Sopenharmony_ci    }
197292f3ab15Sopenharmony_ci
197392f3ab15Sopenharmony_ci    /// Successful peer certificate verification.
197492f3ab15Sopenharmony_ci    pub const OK: X509VerifyResult = X509VerifyResult(ffi::X509_V_OK);
197592f3ab15Sopenharmony_ci    /// Application verification failure.
197692f3ab15Sopenharmony_ci    pub const APPLICATION_VERIFICATION: X509VerifyResult =
197792f3ab15Sopenharmony_ci        X509VerifyResult(ffi::X509_V_ERR_APPLICATION_VERIFICATION);
197892f3ab15Sopenharmony_ci}
197992f3ab15Sopenharmony_ci
198092f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
198192f3ab15Sopenharmony_ci    type CType = ffi::GENERAL_NAME;
198292f3ab15Sopenharmony_ci    fn drop = ffi::GENERAL_NAME_free;
198392f3ab15Sopenharmony_ci
198492f3ab15Sopenharmony_ci    /// An `X509` certificate alternative names.
198592f3ab15Sopenharmony_ci    pub struct GeneralName;
198692f3ab15Sopenharmony_ci    /// Reference to `GeneralName`.
198792f3ab15Sopenharmony_ci    pub struct GeneralNameRef;
198892f3ab15Sopenharmony_ci}
198992f3ab15Sopenharmony_ci
199092f3ab15Sopenharmony_ciimpl GeneralName {
199192f3ab15Sopenharmony_ci    unsafe fn new(
199292f3ab15Sopenharmony_ci        type_: c_int,
199392f3ab15Sopenharmony_ci        asn1_type: Asn1Type,
199492f3ab15Sopenharmony_ci        value: &[u8],
199592f3ab15Sopenharmony_ci    ) -> Result<GeneralName, ErrorStack> {
199692f3ab15Sopenharmony_ci        ffi::init();
199792f3ab15Sopenharmony_ci        let gn = GeneralName::from_ptr(cvt_p(ffi::GENERAL_NAME_new())?);
199892f3ab15Sopenharmony_ci        (*gn.as_ptr()).type_ = type_;
199992f3ab15Sopenharmony_ci        let s = cvt_p(ffi::ASN1_STRING_type_new(asn1_type.as_raw()))?;
200092f3ab15Sopenharmony_ci        ffi::ASN1_STRING_set(s, value.as_ptr().cast(), value.len().try_into().unwrap());
200192f3ab15Sopenharmony_ci
200292f3ab15Sopenharmony_ci        #[cfg(boringssl)]
200392f3ab15Sopenharmony_ci        {
200492f3ab15Sopenharmony_ci            (*gn.as_ptr()).d.ptr = s.cast();
200592f3ab15Sopenharmony_ci        }
200692f3ab15Sopenharmony_ci        #[cfg(not(boringssl))]
200792f3ab15Sopenharmony_ci        {
200892f3ab15Sopenharmony_ci            (*gn.as_ptr()).d = s.cast();
200992f3ab15Sopenharmony_ci        }
201092f3ab15Sopenharmony_ci
201192f3ab15Sopenharmony_ci        Ok(gn)
201292f3ab15Sopenharmony_ci    }
201392f3ab15Sopenharmony_ci
201492f3ab15Sopenharmony_ci    pub(crate) fn new_email(email: &[u8]) -> Result<GeneralName, ErrorStack> {
201592f3ab15Sopenharmony_ci        unsafe { GeneralName::new(ffi::GEN_EMAIL, Asn1Type::IA5STRING, email) }
201692f3ab15Sopenharmony_ci    }
201792f3ab15Sopenharmony_ci
201892f3ab15Sopenharmony_ci    pub(crate) fn new_dns(dns: &[u8]) -> Result<GeneralName, ErrorStack> {
201992f3ab15Sopenharmony_ci        unsafe { GeneralName::new(ffi::GEN_DNS, Asn1Type::IA5STRING, dns) }
202092f3ab15Sopenharmony_ci    }
202192f3ab15Sopenharmony_ci
202292f3ab15Sopenharmony_ci    pub(crate) fn new_uri(uri: &[u8]) -> Result<GeneralName, ErrorStack> {
202392f3ab15Sopenharmony_ci        unsafe { GeneralName::new(ffi::GEN_URI, Asn1Type::IA5STRING, uri) }
202492f3ab15Sopenharmony_ci    }
202592f3ab15Sopenharmony_ci
202692f3ab15Sopenharmony_ci    pub(crate) fn new_ip(ip: IpAddr) -> Result<GeneralName, ErrorStack> {
202792f3ab15Sopenharmony_ci        match ip {
202892f3ab15Sopenharmony_ci            IpAddr::V4(addr) => unsafe {
202992f3ab15Sopenharmony_ci                GeneralName::new(ffi::GEN_IPADD, Asn1Type::OCTET_STRING, &addr.octets())
203092f3ab15Sopenharmony_ci            },
203192f3ab15Sopenharmony_ci            IpAddr::V6(addr) => unsafe {
203292f3ab15Sopenharmony_ci                GeneralName::new(ffi::GEN_IPADD, Asn1Type::OCTET_STRING, &addr.octets())
203392f3ab15Sopenharmony_ci            },
203492f3ab15Sopenharmony_ci        }
203592f3ab15Sopenharmony_ci    }
203692f3ab15Sopenharmony_ci
203792f3ab15Sopenharmony_ci    pub(crate) fn new_rid(oid: Asn1Object) -> Result<GeneralName, ErrorStack> {
203892f3ab15Sopenharmony_ci        unsafe {
203992f3ab15Sopenharmony_ci            ffi::init();
204092f3ab15Sopenharmony_ci            let gn = cvt_p(ffi::GENERAL_NAME_new())?;
204192f3ab15Sopenharmony_ci            (*gn).type_ = ffi::GEN_RID;
204292f3ab15Sopenharmony_ci
204392f3ab15Sopenharmony_ci            #[cfg(boringssl)]
204492f3ab15Sopenharmony_ci            {
204592f3ab15Sopenharmony_ci                (*gn).d.registeredID = oid.as_ptr();
204692f3ab15Sopenharmony_ci            }
204792f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
204892f3ab15Sopenharmony_ci            {
204992f3ab15Sopenharmony_ci                (*gn).d = oid.as_ptr().cast();
205092f3ab15Sopenharmony_ci            }
205192f3ab15Sopenharmony_ci
205292f3ab15Sopenharmony_ci            mem::forget(oid);
205392f3ab15Sopenharmony_ci
205492f3ab15Sopenharmony_ci            Ok(GeneralName::from_ptr(gn))
205592f3ab15Sopenharmony_ci        }
205692f3ab15Sopenharmony_ci    }
205792f3ab15Sopenharmony_ci
205892f3ab15Sopenharmony_ci    pub(crate) fn new_other_name(
205992f3ab15Sopenharmony_ci        oid: Asn1Object,
206092f3ab15Sopenharmony_ci        value: &Vec<u8>,
206192f3ab15Sopenharmony_ci    ) -> Result<GeneralName, ErrorStack> {
206292f3ab15Sopenharmony_ci        unsafe {
206392f3ab15Sopenharmony_ci            ffi::init();
206492f3ab15Sopenharmony_ci
206592f3ab15Sopenharmony_ci            let typ = cvt_p(ffi::d2i_ASN1_TYPE(
206692f3ab15Sopenharmony_ci                ptr::null_mut(),
206792f3ab15Sopenharmony_ci                &mut value.as_ptr().cast(),
206892f3ab15Sopenharmony_ci                value.len().try_into().unwrap(),
206992f3ab15Sopenharmony_ci            ))?;
207092f3ab15Sopenharmony_ci
207192f3ab15Sopenharmony_ci            let gn = cvt_p(ffi::GENERAL_NAME_new())?;
207292f3ab15Sopenharmony_ci            (*gn).type_ = ffi::GEN_OTHERNAME;
207392f3ab15Sopenharmony_ci
207492f3ab15Sopenharmony_ci            if let Err(e) = cvt(ffi::GENERAL_NAME_set0_othername(
207592f3ab15Sopenharmony_ci                gn,
207692f3ab15Sopenharmony_ci                oid.as_ptr().cast(),
207792f3ab15Sopenharmony_ci                typ,
207892f3ab15Sopenharmony_ci            )) {
207992f3ab15Sopenharmony_ci                ffi::GENERAL_NAME_free(gn);
208092f3ab15Sopenharmony_ci                return Err(e);
208192f3ab15Sopenharmony_ci            }
208292f3ab15Sopenharmony_ci
208392f3ab15Sopenharmony_ci            mem::forget(oid);
208492f3ab15Sopenharmony_ci
208592f3ab15Sopenharmony_ci            Ok(GeneralName::from_ptr(gn))
208692f3ab15Sopenharmony_ci        }
208792f3ab15Sopenharmony_ci    }
208892f3ab15Sopenharmony_ci}
208992f3ab15Sopenharmony_ci
209092f3ab15Sopenharmony_ciimpl GeneralNameRef {
209192f3ab15Sopenharmony_ci    fn ia5_string(&self, ffi_type: c_int) -> Option<&str> {
209292f3ab15Sopenharmony_ci        unsafe {
209392f3ab15Sopenharmony_ci            if (*self.as_ptr()).type_ != ffi_type {
209492f3ab15Sopenharmony_ci                return None;
209592f3ab15Sopenharmony_ci            }
209692f3ab15Sopenharmony_ci
209792f3ab15Sopenharmony_ci            #[cfg(boringssl)]
209892f3ab15Sopenharmony_ci            let d = (*self.as_ptr()).d.ptr;
209992f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
210092f3ab15Sopenharmony_ci            let d = (*self.as_ptr()).d;
210192f3ab15Sopenharmony_ci
210292f3ab15Sopenharmony_ci            let ptr = ASN1_STRING_get0_data(d as *mut _);
210392f3ab15Sopenharmony_ci            let len = ffi::ASN1_STRING_length(d as *mut _);
210492f3ab15Sopenharmony_ci
210592f3ab15Sopenharmony_ci            let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
210692f3ab15Sopenharmony_ci            // IA5Strings are stated to be ASCII (specifically IA5). Hopefully
210792f3ab15Sopenharmony_ci            // OpenSSL checks that when loading a certificate but if not we'll
210892f3ab15Sopenharmony_ci            // use this instead of from_utf8_unchecked just in case.
210992f3ab15Sopenharmony_ci            str::from_utf8(slice).ok()
211092f3ab15Sopenharmony_ci        }
211192f3ab15Sopenharmony_ci    }
211292f3ab15Sopenharmony_ci
211392f3ab15Sopenharmony_ci    /// Returns the contents of this `GeneralName` if it is an `rfc822Name`.
211492f3ab15Sopenharmony_ci    pub fn email(&self) -> Option<&str> {
211592f3ab15Sopenharmony_ci        self.ia5_string(ffi::GEN_EMAIL)
211692f3ab15Sopenharmony_ci    }
211792f3ab15Sopenharmony_ci
211892f3ab15Sopenharmony_ci    /// Returns the contents of this `GeneralName` if it is a `directoryName`.
211992f3ab15Sopenharmony_ci    pub fn directory_name(&self) -> Option<&X509NameRef> {
212092f3ab15Sopenharmony_ci        unsafe {
212192f3ab15Sopenharmony_ci            if (*self.as_ptr()).type_ != ffi::GEN_DIRNAME {
212292f3ab15Sopenharmony_ci                return None;
212392f3ab15Sopenharmony_ci            }
212492f3ab15Sopenharmony_ci
212592f3ab15Sopenharmony_ci            #[cfg(boringssl)]
212692f3ab15Sopenharmony_ci            let d = (*self.as_ptr()).d.ptr;
212792f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
212892f3ab15Sopenharmony_ci            let d = (*self.as_ptr()).d;
212992f3ab15Sopenharmony_ci
213092f3ab15Sopenharmony_ci            Some(X509NameRef::from_const_ptr(d as *const _))
213192f3ab15Sopenharmony_ci        }
213292f3ab15Sopenharmony_ci    }
213392f3ab15Sopenharmony_ci
213492f3ab15Sopenharmony_ci    /// Returns the contents of this `GeneralName` if it is a `dNSName`.
213592f3ab15Sopenharmony_ci    pub fn dnsname(&self) -> Option<&str> {
213692f3ab15Sopenharmony_ci        self.ia5_string(ffi::GEN_DNS)
213792f3ab15Sopenharmony_ci    }
213892f3ab15Sopenharmony_ci
213992f3ab15Sopenharmony_ci    /// Returns the contents of this `GeneralName` if it is an `uniformResourceIdentifier`.
214092f3ab15Sopenharmony_ci    pub fn uri(&self) -> Option<&str> {
214192f3ab15Sopenharmony_ci        self.ia5_string(ffi::GEN_URI)
214292f3ab15Sopenharmony_ci    }
214392f3ab15Sopenharmony_ci
214492f3ab15Sopenharmony_ci    /// Returns the contents of this `GeneralName` if it is an `iPAddress`.
214592f3ab15Sopenharmony_ci    pub fn ipaddress(&self) -> Option<&[u8]> {
214692f3ab15Sopenharmony_ci        unsafe {
214792f3ab15Sopenharmony_ci            if (*self.as_ptr()).type_ != ffi::GEN_IPADD {
214892f3ab15Sopenharmony_ci                return None;
214992f3ab15Sopenharmony_ci            }
215092f3ab15Sopenharmony_ci            #[cfg(boringssl)]
215192f3ab15Sopenharmony_ci            let d: *const ffi::ASN1_STRING = std::mem::transmute((*self.as_ptr()).d);
215292f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
215392f3ab15Sopenharmony_ci            let d = (*self.as_ptr()).d;
215492f3ab15Sopenharmony_ci
215592f3ab15Sopenharmony_ci            let ptr = ASN1_STRING_get0_data(d as *mut _);
215692f3ab15Sopenharmony_ci            let len = ffi::ASN1_STRING_length(d as *mut _);
215792f3ab15Sopenharmony_ci
215892f3ab15Sopenharmony_ci            Some(slice::from_raw_parts(ptr as *const u8, len as usize))
215992f3ab15Sopenharmony_ci        }
216092f3ab15Sopenharmony_ci    }
216192f3ab15Sopenharmony_ci}
216292f3ab15Sopenharmony_ci
216392f3ab15Sopenharmony_ciimpl fmt::Debug for GeneralNameRef {
216492f3ab15Sopenharmony_ci    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
216592f3ab15Sopenharmony_ci        if let Some(email) = self.email() {
216692f3ab15Sopenharmony_ci            formatter.write_str(email)
216792f3ab15Sopenharmony_ci        } else if let Some(dnsname) = self.dnsname() {
216892f3ab15Sopenharmony_ci            formatter.write_str(dnsname)
216992f3ab15Sopenharmony_ci        } else if let Some(uri) = self.uri() {
217092f3ab15Sopenharmony_ci            formatter.write_str(uri)
217192f3ab15Sopenharmony_ci        } else if let Some(ipaddress) = self.ipaddress() {
217292f3ab15Sopenharmony_ci            let address = <[u8; 16]>::try_from(ipaddress)
217392f3ab15Sopenharmony_ci                .map(IpAddr::from)
217492f3ab15Sopenharmony_ci                .or_else(|_| <[u8; 4]>::try_from(ipaddress).map(IpAddr::from));
217592f3ab15Sopenharmony_ci            match address {
217692f3ab15Sopenharmony_ci                Ok(a) => fmt::Debug::fmt(&a, formatter),
217792f3ab15Sopenharmony_ci                Err(_) => fmt::Debug::fmt(ipaddress, formatter),
217892f3ab15Sopenharmony_ci            }
217992f3ab15Sopenharmony_ci        } else {
218092f3ab15Sopenharmony_ci            formatter.write_str("(empty)")
218192f3ab15Sopenharmony_ci        }
218292f3ab15Sopenharmony_ci    }
218392f3ab15Sopenharmony_ci}
218492f3ab15Sopenharmony_ci
218592f3ab15Sopenharmony_ciimpl Stackable for GeneralName {
218692f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_GENERAL_NAME;
218792f3ab15Sopenharmony_ci}
218892f3ab15Sopenharmony_ci
218992f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
219092f3ab15Sopenharmony_ci    type CType = ffi::DIST_POINT;
219192f3ab15Sopenharmony_ci    fn drop = ffi::DIST_POINT_free;
219292f3ab15Sopenharmony_ci
219392f3ab15Sopenharmony_ci    /// A `X509` distribution point.
219492f3ab15Sopenharmony_ci    pub struct DistPoint;
219592f3ab15Sopenharmony_ci    /// Reference to `DistPoint`.
219692f3ab15Sopenharmony_ci    pub struct DistPointRef;
219792f3ab15Sopenharmony_ci}
219892f3ab15Sopenharmony_ci
219992f3ab15Sopenharmony_ciimpl DistPointRef {
220092f3ab15Sopenharmony_ci    /// Returns the name of this distribution point if it exists
220192f3ab15Sopenharmony_ci    pub fn distpoint(&self) -> Option<&DistPointNameRef> {
220292f3ab15Sopenharmony_ci        unsafe { DistPointNameRef::from_const_ptr_opt((*self.as_ptr()).distpoint) }
220392f3ab15Sopenharmony_ci    }
220492f3ab15Sopenharmony_ci}
220592f3ab15Sopenharmony_ci
220692f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
220792f3ab15Sopenharmony_ci    type CType = ffi::DIST_POINT_NAME;
220892f3ab15Sopenharmony_ci    fn drop = ffi::DIST_POINT_NAME_free;
220992f3ab15Sopenharmony_ci
221092f3ab15Sopenharmony_ci    /// A `X509` distribution point.
221192f3ab15Sopenharmony_ci    pub struct DistPointName;
221292f3ab15Sopenharmony_ci    /// Reference to `DistPointName`.
221392f3ab15Sopenharmony_ci    pub struct DistPointNameRef;
221492f3ab15Sopenharmony_ci}
221592f3ab15Sopenharmony_ci
221692f3ab15Sopenharmony_ciimpl DistPointNameRef {
221792f3ab15Sopenharmony_ci    /// Returns the contents of this DistPointName if it is a fullname.
221892f3ab15Sopenharmony_ci    pub fn fullname(&self) -> Option<&StackRef<GeneralName>> {
221992f3ab15Sopenharmony_ci        unsafe {
222092f3ab15Sopenharmony_ci            if (*self.as_ptr()).type_ != 0 {
222192f3ab15Sopenharmony_ci                return None;
222292f3ab15Sopenharmony_ci            }
222392f3ab15Sopenharmony_ci            StackRef::from_const_ptr_opt((*self.as_ptr()).name.fullname)
222492f3ab15Sopenharmony_ci        }
222592f3ab15Sopenharmony_ci    }
222692f3ab15Sopenharmony_ci}
222792f3ab15Sopenharmony_ci
222892f3ab15Sopenharmony_ciimpl Stackable for DistPoint {
222992f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_DIST_POINT;
223092f3ab15Sopenharmony_ci}
223192f3ab15Sopenharmony_ci
223292f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
223392f3ab15Sopenharmony_ci    type CType = ffi::ACCESS_DESCRIPTION;
223492f3ab15Sopenharmony_ci    fn drop = ffi::ACCESS_DESCRIPTION_free;
223592f3ab15Sopenharmony_ci
223692f3ab15Sopenharmony_ci    /// `AccessDescription` of certificate authority information.
223792f3ab15Sopenharmony_ci    pub struct AccessDescription;
223892f3ab15Sopenharmony_ci    /// Reference to `AccessDescription`.
223992f3ab15Sopenharmony_ci    pub struct AccessDescriptionRef;
224092f3ab15Sopenharmony_ci}
224192f3ab15Sopenharmony_ci
224292f3ab15Sopenharmony_ciimpl AccessDescriptionRef {
224392f3ab15Sopenharmony_ci    /// Returns the access method OID.
224492f3ab15Sopenharmony_ci    pub fn method(&self) -> &Asn1ObjectRef {
224592f3ab15Sopenharmony_ci        unsafe { Asn1ObjectRef::from_ptr((*self.as_ptr()).method) }
224692f3ab15Sopenharmony_ci    }
224792f3ab15Sopenharmony_ci
224892f3ab15Sopenharmony_ci    // Returns the access location.
224992f3ab15Sopenharmony_ci    pub fn location(&self) -> &GeneralNameRef {
225092f3ab15Sopenharmony_ci        unsafe { GeneralNameRef::from_ptr((*self.as_ptr()).location) }
225192f3ab15Sopenharmony_ci    }
225292f3ab15Sopenharmony_ci}
225392f3ab15Sopenharmony_ci
225492f3ab15Sopenharmony_ciimpl Stackable for AccessDescription {
225592f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_ACCESS_DESCRIPTION;
225692f3ab15Sopenharmony_ci}
225792f3ab15Sopenharmony_ci
225892f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
225992f3ab15Sopenharmony_ci    type CType = ffi::X509_ALGOR;
226092f3ab15Sopenharmony_ci    fn drop = ffi::X509_ALGOR_free;
226192f3ab15Sopenharmony_ci
226292f3ab15Sopenharmony_ci    /// An `X509` certificate signature algorithm.
226392f3ab15Sopenharmony_ci    pub struct X509Algorithm;
226492f3ab15Sopenharmony_ci    /// Reference to `X509Algorithm`.
226592f3ab15Sopenharmony_ci    pub struct X509AlgorithmRef;
226692f3ab15Sopenharmony_ci}
226792f3ab15Sopenharmony_ci
226892f3ab15Sopenharmony_ciimpl X509AlgorithmRef {
226992f3ab15Sopenharmony_ci    /// Returns the ASN.1 OID of this algorithm.
227092f3ab15Sopenharmony_ci    pub fn object(&self) -> &Asn1ObjectRef {
227192f3ab15Sopenharmony_ci        unsafe {
227292f3ab15Sopenharmony_ci            let mut oid = ptr::null();
227392f3ab15Sopenharmony_ci            X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr());
227492f3ab15Sopenharmony_ci            Asn1ObjectRef::from_const_ptr_opt(oid).expect("algorithm oid must not be null")
227592f3ab15Sopenharmony_ci        }
227692f3ab15Sopenharmony_ci    }
227792f3ab15Sopenharmony_ci}
227892f3ab15Sopenharmony_ci
227992f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
228092f3ab15Sopenharmony_ci    type CType = ffi::X509_OBJECT;
228192f3ab15Sopenharmony_ci    fn drop = X509_OBJECT_free;
228292f3ab15Sopenharmony_ci
228392f3ab15Sopenharmony_ci    /// An `X509` or an X509 certificate revocation list.
228492f3ab15Sopenharmony_ci    pub struct X509Object;
228592f3ab15Sopenharmony_ci    /// Reference to `X509Object`
228692f3ab15Sopenharmony_ci    pub struct X509ObjectRef;
228792f3ab15Sopenharmony_ci}
228892f3ab15Sopenharmony_ci
228992f3ab15Sopenharmony_ciimpl X509ObjectRef {
229092f3ab15Sopenharmony_ci    pub fn x509(&self) -> Option<&X509Ref> {
229192f3ab15Sopenharmony_ci        unsafe {
229292f3ab15Sopenharmony_ci            let ptr = X509_OBJECT_get0_X509(self.as_ptr());
229392f3ab15Sopenharmony_ci            X509Ref::from_const_ptr_opt(ptr)
229492f3ab15Sopenharmony_ci        }
229592f3ab15Sopenharmony_ci    }
229692f3ab15Sopenharmony_ci}
229792f3ab15Sopenharmony_ci
229892f3ab15Sopenharmony_ciimpl Stackable for X509Object {
229992f3ab15Sopenharmony_ci    type StackType = ffi::stack_st_X509_OBJECT;
230092f3ab15Sopenharmony_ci}
230192f3ab15Sopenharmony_ci
230292f3ab15Sopenharmony_cicfg_if! {
230392f3ab15Sopenharmony_ci    if #[cfg(any(boringssl, ossl110, libressl273))] {
230492f3ab15Sopenharmony_ci        use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature};
230592f3ab15Sopenharmony_ci    } else {
230692f3ab15Sopenharmony_ci        #[allow(bad_style)]
230792f3ab15Sopenharmony_ci        unsafe fn X509_getm_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
230892f3ab15Sopenharmony_ci            (*(*(*x).cert_info).validity).notAfter
230992f3ab15Sopenharmony_ci        }
231092f3ab15Sopenharmony_ci
231192f3ab15Sopenharmony_ci        #[allow(bad_style)]
231292f3ab15Sopenharmony_ci        unsafe fn X509_getm_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
231392f3ab15Sopenharmony_ci            (*(*(*x).cert_info).validity).notBefore
231492f3ab15Sopenharmony_ci        }
231592f3ab15Sopenharmony_ci
231692f3ab15Sopenharmony_ci        #[allow(bad_style)]
231792f3ab15Sopenharmony_ci        unsafe fn X509_up_ref(x: *mut ffi::X509) {
231892f3ab15Sopenharmony_ci            ffi::CRYPTO_add_lock(
231992f3ab15Sopenharmony_ci                &mut (*x).references,
232092f3ab15Sopenharmony_ci                1,
232192f3ab15Sopenharmony_ci                ffi::CRYPTO_LOCK_X509,
232292f3ab15Sopenharmony_ci                "mod.rs\0".as_ptr() as *const _,
232392f3ab15Sopenharmony_ci                line!() as c_int,
232492f3ab15Sopenharmony_ci            );
232592f3ab15Sopenharmony_ci        }
232692f3ab15Sopenharmony_ci
232792f3ab15Sopenharmony_ci        #[allow(bad_style)]
232892f3ab15Sopenharmony_ci        unsafe fn X509_get0_signature(
232992f3ab15Sopenharmony_ci            psig: *mut *const ffi::ASN1_BIT_STRING,
233092f3ab15Sopenharmony_ci            palg: *mut *const ffi::X509_ALGOR,
233192f3ab15Sopenharmony_ci            x: *const ffi::X509,
233292f3ab15Sopenharmony_ci        ) {
233392f3ab15Sopenharmony_ci            if !psig.is_null() {
233492f3ab15Sopenharmony_ci                *psig = (*x).signature;
233592f3ab15Sopenharmony_ci            }
233692f3ab15Sopenharmony_ci            if !palg.is_null() {
233792f3ab15Sopenharmony_ci                *palg = (*x).sig_alg;
233892f3ab15Sopenharmony_ci            }
233992f3ab15Sopenharmony_ci        }
234092f3ab15Sopenharmony_ci    }
234192f3ab15Sopenharmony_ci}
234292f3ab15Sopenharmony_ci
234392f3ab15Sopenharmony_cicfg_if! {
234492f3ab15Sopenharmony_ci    if #[cfg(any(boringssl, ossl110, libressl350))] {
234592f3ab15Sopenharmony_ci        use ffi::{
234692f3ab15Sopenharmony_ci            X509_ALGOR_get0, ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter,
234792f3ab15Sopenharmony_ci            X509_set1_notBefore, X509_REQ_get_version, X509_REQ_get_subject_name,
234892f3ab15Sopenharmony_ci        };
234992f3ab15Sopenharmony_ci    } else {
235092f3ab15Sopenharmony_ci        use ffi::{
235192f3ab15Sopenharmony_ci            ASN1_STRING_data as ASN1_STRING_get0_data,
235292f3ab15Sopenharmony_ci            X509_STORE_CTX_get_chain as X509_STORE_CTX_get0_chain,
235392f3ab15Sopenharmony_ci            X509_set_notAfter as X509_set1_notAfter,
235492f3ab15Sopenharmony_ci            X509_set_notBefore as X509_set1_notBefore,
235592f3ab15Sopenharmony_ci        };
235692f3ab15Sopenharmony_ci
235792f3ab15Sopenharmony_ci        #[allow(bad_style)]
235892f3ab15Sopenharmony_ci        unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long {
235992f3ab15Sopenharmony_ci            ffi::ASN1_INTEGER_get((*(*x).req_info).version)
236092f3ab15Sopenharmony_ci        }
236192f3ab15Sopenharmony_ci
236292f3ab15Sopenharmony_ci        #[allow(bad_style)]
236392f3ab15Sopenharmony_ci        unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME {
236492f3ab15Sopenharmony_ci            (*(*x).req_info).subject
236592f3ab15Sopenharmony_ci        }
236692f3ab15Sopenharmony_ci
236792f3ab15Sopenharmony_ci        #[allow(bad_style)]
236892f3ab15Sopenharmony_ci        unsafe fn X509_ALGOR_get0(
236992f3ab15Sopenharmony_ci            paobj: *mut *const ffi::ASN1_OBJECT,
237092f3ab15Sopenharmony_ci            pptype: *mut c_int,
237192f3ab15Sopenharmony_ci            pval: *mut *mut ::libc::c_void,
237292f3ab15Sopenharmony_ci            alg: *const ffi::X509_ALGOR,
237392f3ab15Sopenharmony_ci        ) {
237492f3ab15Sopenharmony_ci            if !paobj.is_null() {
237592f3ab15Sopenharmony_ci                *paobj = (*alg).algorithm;
237692f3ab15Sopenharmony_ci            }
237792f3ab15Sopenharmony_ci            assert!(pptype.is_null());
237892f3ab15Sopenharmony_ci            assert!(pval.is_null());
237992f3ab15Sopenharmony_ci        }
238092f3ab15Sopenharmony_ci    }
238192f3ab15Sopenharmony_ci}
238292f3ab15Sopenharmony_ci
238392f3ab15Sopenharmony_cicfg_if! {
238492f3ab15Sopenharmony_ci    if #[cfg(any(ossl110, boringssl, libressl270))] {
238592f3ab15Sopenharmony_ci        use ffi::X509_OBJECT_get0_X509;
238692f3ab15Sopenharmony_ci    } else {
238792f3ab15Sopenharmony_ci        #[allow(bad_style)]
238892f3ab15Sopenharmony_ci        unsafe fn X509_OBJECT_get0_X509(x: *mut ffi::X509_OBJECT) -> *mut ffi::X509 {
238992f3ab15Sopenharmony_ci            if (*x).type_ == ffi::X509_LU_X509 {
239092f3ab15Sopenharmony_ci                (*x).data.x509
239192f3ab15Sopenharmony_ci            } else {
239292f3ab15Sopenharmony_ci                ptr::null_mut()
239392f3ab15Sopenharmony_ci            }
239492f3ab15Sopenharmony_ci        }
239592f3ab15Sopenharmony_ci    }
239692f3ab15Sopenharmony_ci}
239792f3ab15Sopenharmony_ci
239892f3ab15Sopenharmony_cicfg_if! {
239992f3ab15Sopenharmony_ci    if #[cfg(any(ossl110, libressl350))] {
240092f3ab15Sopenharmony_ci        use ffi::X509_OBJECT_free;
240192f3ab15Sopenharmony_ci    } else if #[cfg(boringssl)] {
240292f3ab15Sopenharmony_ci        use ffi::X509_OBJECT_free_contents as X509_OBJECT_free;
240392f3ab15Sopenharmony_ci    } else {
240492f3ab15Sopenharmony_ci        #[allow(bad_style)]
240592f3ab15Sopenharmony_ci        unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) {
240692f3ab15Sopenharmony_ci            ffi::X509_OBJECT_free_contents(x);
240792f3ab15Sopenharmony_ci            ffi::CRYPTO_free(x as *mut libc::c_void);
240892f3ab15Sopenharmony_ci        }
240992f3ab15Sopenharmony_ci    }
241092f3ab15Sopenharmony_ci}
241192f3ab15Sopenharmony_ci
241292f3ab15Sopenharmony_cicfg_if! {
241392f3ab15Sopenharmony_ci    if #[cfg(any(ossl110, libressl350, boringssl))] {
241492f3ab15Sopenharmony_ci        use ffi::{
241592f3ab15Sopenharmony_ci            X509_CRL_get_issuer, X509_CRL_get0_nextUpdate, X509_CRL_get0_lastUpdate,
241692f3ab15Sopenharmony_ci            X509_CRL_get_REVOKED,
241792f3ab15Sopenharmony_ci            X509_REVOKED_get0_revocationDate, X509_REVOKED_get0_serialNumber,
241892f3ab15Sopenharmony_ci        };
241992f3ab15Sopenharmony_ci    } else {
242092f3ab15Sopenharmony_ci        #[allow(bad_style)]
242192f3ab15Sopenharmony_ci        unsafe fn X509_CRL_get0_lastUpdate(x: *const ffi::X509_CRL) -> *mut ffi::ASN1_TIME {
242292f3ab15Sopenharmony_ci            (*(*x).crl).lastUpdate
242392f3ab15Sopenharmony_ci        }
242492f3ab15Sopenharmony_ci        #[allow(bad_style)]
242592f3ab15Sopenharmony_ci        unsafe fn X509_CRL_get0_nextUpdate(x: *const ffi::X509_CRL) -> *mut ffi::ASN1_TIME {
242692f3ab15Sopenharmony_ci            (*(*x).crl).nextUpdate
242792f3ab15Sopenharmony_ci        }
242892f3ab15Sopenharmony_ci        #[allow(bad_style)]
242992f3ab15Sopenharmony_ci        unsafe fn X509_CRL_get_issuer(x: *const ffi::X509_CRL) -> *mut ffi::X509_NAME {
243092f3ab15Sopenharmony_ci            (*(*x).crl).issuer
243192f3ab15Sopenharmony_ci        }
243292f3ab15Sopenharmony_ci        #[allow(bad_style)]
243392f3ab15Sopenharmony_ci        unsafe fn X509_CRL_get_REVOKED(x: *const ffi::X509_CRL) -> *mut ffi::stack_st_X509_REVOKED {
243492f3ab15Sopenharmony_ci            (*(*x).crl).revoked
243592f3ab15Sopenharmony_ci        }
243692f3ab15Sopenharmony_ci        #[allow(bad_style)]
243792f3ab15Sopenharmony_ci        unsafe fn X509_REVOKED_get0_serialNumber(x: *const ffi::X509_REVOKED) -> *mut ffi::ASN1_INTEGER {
243892f3ab15Sopenharmony_ci            (*x).serialNumber
243992f3ab15Sopenharmony_ci        }
244092f3ab15Sopenharmony_ci        #[allow(bad_style)]
244192f3ab15Sopenharmony_ci        unsafe fn X509_REVOKED_get0_revocationDate(x: *const ffi::X509_REVOKED) -> *mut ffi::ASN1_TIME {
244292f3ab15Sopenharmony_ci            (*x).revocationDate
244392f3ab15Sopenharmony_ci        }
244492f3ab15Sopenharmony_ci    }
244592f3ab15Sopenharmony_ci}
244692f3ab15Sopenharmony_ci
244792f3ab15Sopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq)]
244892f3ab15Sopenharmony_cipub struct X509PurposeId(c_int);
244992f3ab15Sopenharmony_ci
245092f3ab15Sopenharmony_ciimpl X509PurposeId {
245192f3ab15Sopenharmony_ci    pub const SSL_CLIENT: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SSL_CLIENT);
245292f3ab15Sopenharmony_ci    pub const SSL_SERVER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SSL_SERVER);
245392f3ab15Sopenharmony_ci    pub const NS_SSL_SERVER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_NS_SSL_SERVER);
245492f3ab15Sopenharmony_ci    pub const SMIME_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SMIME_SIGN);
245592f3ab15Sopenharmony_ci    pub const SMIME_ENCRYPT: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_SMIME_ENCRYPT);
245692f3ab15Sopenharmony_ci    pub const CRL_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_CRL_SIGN);
245792f3ab15Sopenharmony_ci    pub const ANY: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_ANY);
245892f3ab15Sopenharmony_ci    pub const OCSP_HELPER: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_OCSP_HELPER);
245992f3ab15Sopenharmony_ci    pub const TIMESTAMP_SIGN: X509PurposeId = X509PurposeId(ffi::X509_PURPOSE_TIMESTAMP_SIGN);
246092f3ab15Sopenharmony_ci
246192f3ab15Sopenharmony_ci    /// Constructs an `X509PurposeId` from a raw OpenSSL value.
246292f3ab15Sopenharmony_ci    pub fn from_raw(id: c_int) -> Self {
246392f3ab15Sopenharmony_ci        X509PurposeId(id)
246492f3ab15Sopenharmony_ci    }
246592f3ab15Sopenharmony_ci
246692f3ab15Sopenharmony_ci    /// Returns the raw OpenSSL value represented by this type.
246792f3ab15Sopenharmony_ci    pub fn as_raw(&self) -> c_int {
246892f3ab15Sopenharmony_ci        self.0
246992f3ab15Sopenharmony_ci    }
247092f3ab15Sopenharmony_ci}
247192f3ab15Sopenharmony_ci
247292f3ab15Sopenharmony_ci/// A reference to an [`X509_PURPOSE`].
247392f3ab15Sopenharmony_cipub struct X509PurposeRef(Opaque);
247492f3ab15Sopenharmony_ci
247592f3ab15Sopenharmony_ci/// Implements a wrapper type for the static `X509_PURPOSE` table in OpenSSL.
247692f3ab15Sopenharmony_ciimpl ForeignTypeRef for X509PurposeRef {
247792f3ab15Sopenharmony_ci    type CType = ffi::X509_PURPOSE;
247892f3ab15Sopenharmony_ci}
247992f3ab15Sopenharmony_ci
248092f3ab15Sopenharmony_ciimpl X509PurposeRef {
248192f3ab15Sopenharmony_ci    /// Get the internal table index of an X509_PURPOSE for a given short name. Valid short
248292f3ab15Sopenharmony_ci    /// names include
248392f3ab15Sopenharmony_ci    ///  - "sslclient",
248492f3ab15Sopenharmony_ci    ///  - "sslserver",
248592f3ab15Sopenharmony_ci    ///  - "nssslserver",
248692f3ab15Sopenharmony_ci    ///  - "smimesign",
248792f3ab15Sopenharmony_ci    ///  - "smimeencrypt",
248892f3ab15Sopenharmony_ci    ///  - "crlsign",
248992f3ab15Sopenharmony_ci    ///  - "any",
249092f3ab15Sopenharmony_ci    ///  - "ocsphelper",
249192f3ab15Sopenharmony_ci    ///  - "timestampsign"
249292f3ab15Sopenharmony_ci    /// The index can be used with `X509PurposeRef::from_idx()` to get the purpose.
249392f3ab15Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
249492f3ab15Sopenharmony_ci    pub fn get_by_sname(sname: &str) -> Result<c_int, ErrorStack> {
249592f3ab15Sopenharmony_ci        unsafe {
249692f3ab15Sopenharmony_ci            let sname = CString::new(sname).unwrap();
249792f3ab15Sopenharmony_ci            cfg_if! {
249892f3ab15Sopenharmony_ci                if #[cfg(any(ossl110, libressl280))] {
249992f3ab15Sopenharmony_ci                    let purpose = cvt_n(ffi::X509_PURPOSE_get_by_sname(sname.as_ptr() as *const _))?;
250092f3ab15Sopenharmony_ci                } else {
250192f3ab15Sopenharmony_ci                    let purpose = cvt_n(ffi::X509_PURPOSE_get_by_sname(sname.as_ptr() as *mut _))?;
250292f3ab15Sopenharmony_ci                }
250392f3ab15Sopenharmony_ci            }
250492f3ab15Sopenharmony_ci            Ok(purpose)
250592f3ab15Sopenharmony_ci        }
250692f3ab15Sopenharmony_ci    }
250792f3ab15Sopenharmony_ci    /// Get an `X509PurposeRef` for a given index value. The index can be obtained from e.g.
250892f3ab15Sopenharmony_ci    /// `X509PurposeRef::get_by_sname()`.
250992f3ab15Sopenharmony_ci    #[corresponds(X509_PURPOSE_get0)]
251092f3ab15Sopenharmony_ci    pub fn from_idx(idx: c_int) -> Result<&'static X509PurposeRef, ErrorStack> {
251192f3ab15Sopenharmony_ci        unsafe {
251292f3ab15Sopenharmony_ci            let ptr = cvt_p(ffi::X509_PURPOSE_get0(idx))?;
251392f3ab15Sopenharmony_ci            Ok(X509PurposeRef::from_ptr(ptr))
251492f3ab15Sopenharmony_ci        }
251592f3ab15Sopenharmony_ci    }
251692f3ab15Sopenharmony_ci
251792f3ab15Sopenharmony_ci    /// Get the purpose value from an X509Purpose structure. This value is one of
251892f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_SSL_CLIENT`
251992f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_SSL_SERVER`
252092f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_NS_SSL_SERVER`
252192f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_SMIME_SIGN`
252292f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_SMIME_ENCRYPT`
252392f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_CRL_SIGN`
252492f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_ANY`
252592f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_OCSP_HELPER`
252692f3ab15Sopenharmony_ci    /// - `X509_PURPOSE_TIMESTAMP_SIGN`
252792f3ab15Sopenharmony_ci    pub fn purpose(&self) -> X509PurposeId {
252892f3ab15Sopenharmony_ci        unsafe {
252992f3ab15Sopenharmony_ci            let x509_purpose: *mut ffi::X509_PURPOSE = self.as_ptr();
253092f3ab15Sopenharmony_ci            X509PurposeId::from_raw((*x509_purpose).purpose)
253192f3ab15Sopenharmony_ci        }
253292f3ab15Sopenharmony_ci    }
253392f3ab15Sopenharmony_ci}
2534