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