• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! The standard defining the format of public key certificates.
2 //!
3 //! An `X509` certificate binds an identity to a public key, and is either
4 //! signed by a certificate authority (CA) or self-signed. An entity that gets
5 //! a hold of a certificate can both verify your identity (via a CA) and encrypt
6 //! data with the included public key. `X509` certificates are used in many
7 //! Internet protocols, including SSL/TLS, which is the basis for HTTPS,
8 //! the secure protocol for browsing the web.
9 
10 use cfg_if::cfg_if;
11 use foreign_types::{ForeignType, ForeignTypeRef};
12 use libc::{c_int, c_long, c_uint};
13 use std::cmp::{self, Ordering};
14 use std::error::Error;
15 use std::ffi::{CStr, CString};
16 use std::fmt;
17 use std::marker::PhantomData;
18 use std::mem;
19 use std::path::Path;
20 use std::ptr;
21 use std::slice;
22 use std::str;
23 
24 use crate::asn1::{
25     Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef, Asn1Type,
26 };
27 use crate::bio::MemBioSlice;
28 use crate::conf::ConfRef;
29 use crate::error::ErrorStack;
30 use crate::ex_data::Index;
31 use crate::hash::{DigestBytes, MessageDigest};
32 use crate::nid::Nid;
33 use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
34 use crate::ssl::SslRef;
35 use crate::stack::{Stack, StackRef, Stackable};
36 use crate::string::OpensslString;
37 use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
38 use crate::{cvt, cvt_n, cvt_p};
39 use openssl_macros::corresponds;
40 
41 #[cfg(any(ossl102, libressl261))]
42 pub mod verify;
43 
44 pub mod extension;
45 pub mod store;
46 
47 #[cfg(test)]
48 mod tests;
49 
50 foreign_type_and_impl_send_sync! {
51     type CType = ffi::X509_STORE_CTX;
52     fn drop = ffi::X509_STORE_CTX_free;
53 
54     /// An `X509` certificate store context.
55     pub struct X509StoreContext;
56 
57     /// A reference to an [`X509StoreContext`].
58     pub struct X509StoreContextRef;
59 }
60 
61 impl X509StoreContext {
62     /// Returns the index which can be used to obtain a reference to the `Ssl` associated with a
63     /// context.
64     #[corresponds(SSL_get_ex_data_X509_STORE_CTX_idx)]
ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack>65     pub fn ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack> {
66         unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) }
67     }
68 
69     /// Creates a new `X509StoreContext` instance.
70     #[corresponds(X509_STORE_CTX_new)]
new() -> Result<X509StoreContext, ErrorStack>71     pub fn new() -> Result<X509StoreContext, ErrorStack> {
72         unsafe {
73             ffi::init();
74             cvt_p(ffi::X509_STORE_CTX_new()).map(X509StoreContext)
75         }
76     }
77 }
78 
79 impl X509StoreContextRef {
80     /// Returns application data pertaining to an `X509` store context.
81     #[corresponds(X509_STORE_CTX_get_ex_data)]
ex_data<T>(&self, index: Index<X509StoreContext, T>) -> Option<&T>82     pub fn ex_data<T>(&self, index: Index<X509StoreContext, T>) -> Option<&T> {
83         unsafe {
84             let data = ffi::X509_STORE_CTX_get_ex_data(self.as_ptr(), index.as_raw());
85             if data.is_null() {
86                 None
87             } else {
88                 Some(&*(data as *const T))
89             }
90         }
91     }
92 
93     /// Returns the error code of the context.
94     #[corresponds(X509_STORE_CTX_get_error)]
error(&self) -> X509VerifyResult95     pub fn error(&self) -> X509VerifyResult {
96         unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) }
97     }
98 
99     /// Initializes this context with the given certificate, certificates chain and certificate
100     /// store. After initializing the context, the `with_context` closure is called with the prepared
101     /// context. As long as the closure is running, the context stays initialized and can be used
102     /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished.
103     ///
104     /// * `trust` - The certificate store with the trusted certificates.
105     /// * `cert` - The certificate that should be verified.
106     /// * `cert_chain` - The certificates chain.
107     /// * `with_context` - The closure that is called with the initialized context.
108     ///
109     /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to
110     /// [`X509_STORE_CTX_cleanup`] after calling `with_context`.
111     ///
112     /// [`X509_STORE_CTX_init`]:  https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_init.html
113     /// [`X509_STORE_CTX_cleanup`]:  https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html
init<F, T>( &mut self, trust: &store::X509StoreRef, cert: &X509Ref, cert_chain: &StackRef<X509>, with_context: F, ) -> Result<T, ErrorStack> where F: FnOnce(&mut X509StoreContextRef) -> Result<T, ErrorStack>,114     pub fn init<F, T>(
115         &mut self,
116         trust: &store::X509StoreRef,
117         cert: &X509Ref,
118         cert_chain: &StackRef<X509>,
119         with_context: F,
120     ) -> Result<T, ErrorStack>
121     where
122         F: FnOnce(&mut X509StoreContextRef) -> Result<T, ErrorStack>,
123     {
124         struct Cleanup<'a>(&'a mut X509StoreContextRef);
125 
126         impl<'a> Drop for Cleanup<'a> {
127             fn drop(&mut self) {
128                 unsafe {
129                     ffi::X509_STORE_CTX_cleanup(self.0.as_ptr());
130                 }
131             }
132         }
133 
134         unsafe {
135             cvt(ffi::X509_STORE_CTX_init(
136                 self.as_ptr(),
137                 trust.as_ptr(),
138                 cert.as_ptr(),
139                 cert_chain.as_ptr(),
140             ))?;
141 
142             let cleanup = Cleanup(self);
143             with_context(cleanup.0)
144         }
145     }
146 
147     /// Verifies the stored certificate.
148     ///
149     /// Returns `true` if verification succeeds. The `error` method will return the specific
150     /// validation error if the certificate was not valid.
151     ///
152     /// This will only work inside of a call to `init`.
153     #[corresponds(X509_verify_cert)]
verify_cert(&mut self) -> Result<bool, ErrorStack>154     pub fn verify_cert(&mut self) -> Result<bool, ErrorStack> {
155         unsafe { cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0) }
156     }
157 
158     /// Set the error code of the context.
159     #[corresponds(X509_STORE_CTX_set_error)]
set_error(&mut self, result: X509VerifyResult)160     pub fn set_error(&mut self, result: X509VerifyResult) {
161         unsafe {
162             ffi::X509_STORE_CTX_set_error(self.as_ptr(), result.as_raw());
163         }
164     }
165 
166     /// Returns a reference to the certificate which caused the error or None if
167     /// no certificate is relevant to the error.
168     #[corresponds(X509_STORE_CTX_get_current_cert)]
current_cert(&self) -> Option<&X509Ref>169     pub fn current_cert(&self) -> Option<&X509Ref> {
170         unsafe {
171             let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr());
172             X509Ref::from_const_ptr_opt(ptr)
173         }
174     }
175 
176     /// Returns a non-negative integer representing the depth in the certificate
177     /// chain where the error occurred. If it is zero it occurred in the end
178     /// entity certificate, one if it is the certificate which signed the end
179     /// entity certificate and so on.
180     #[corresponds(X509_STORE_CTX_get_error_depth)]
error_depth(&self) -> u32181     pub fn error_depth(&self) -> u32 {
182         unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 }
183     }
184 
185     /// Returns a reference to a complete valid `X509` certificate chain.
186     #[corresponds(X509_STORE_CTX_get0_chain)]
chain(&self) -> Option<&StackRef<X509>>187     pub fn chain(&self) -> Option<&StackRef<X509>> {
188         unsafe {
189             let chain = X509_STORE_CTX_get0_chain(self.as_ptr());
190 
191             if chain.is_null() {
192                 None
193             } else {
194                 Some(StackRef::from_ptr(chain))
195             }
196         }
197     }
198 }
199 
200 /// A builder used to construct an `X509`.
201 pub struct X509Builder(X509);
202 
203 impl X509Builder {
204     /// Creates a new builder.
205     #[corresponds(X509_new)]
new() -> Result<X509Builder, ErrorStack>206     pub fn new() -> Result<X509Builder, ErrorStack> {
207         unsafe {
208             ffi::init();
209             cvt_p(ffi::X509_new()).map(|p| X509Builder(X509(p)))
210         }
211     }
212 
213     /// Sets the notAfter constraint on the certificate.
214     #[corresponds(X509_set1_notAfter)]
set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack>215     pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
216         unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
217     }
218 
219     /// Sets the notBefore constraint on the certificate.
220     #[corresponds(X509_set1_notBefore)]
set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack>221     pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
222         unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
223     }
224 
225     /// Sets the version of the certificate.
226     ///
227     /// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of
228     /// the X.509 standard should pass `2` to this method.
229     #[corresponds(X509_set_version)]
set_version(&mut self, version: i32) -> Result<(), ErrorStack>230     pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
231         unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version as c_long)).map(|_| ()) }
232     }
233 
234     /// Sets the serial number of the certificate.
235     #[corresponds(X509_set_serialNumber)]
set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack>236     pub fn set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack> {
237         unsafe {
238             cvt(ffi::X509_set_serialNumber(
239                 self.0.as_ptr(),
240                 serial_number.as_ptr(),
241             ))
242             .map(|_| ())
243         }
244     }
245 
246     /// Sets the issuer name of the certificate.
247     #[corresponds(X509_set_issuer_name)]
set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack>248     pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> {
249         unsafe {
250             cvt(ffi::X509_set_issuer_name(
251                 self.0.as_ptr(),
252                 issuer_name.as_ptr(),
253             ))
254             .map(|_| ())
255         }
256     }
257 
258     /// Sets the subject name of the certificate.
259     ///
260     /// When building certificates, the `C`, `ST`, and `O` options are common when using the openssl command line tools.
261     /// The `CN` field is used for the common name, such as a DNS name.
262     ///
263     /// ```
264     /// use openssl::x509::{X509, X509NameBuilder};
265     ///
266     /// let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap();
267     /// x509_name.append_entry_by_text("C", "US").unwrap();
268     /// x509_name.append_entry_by_text("ST", "CA").unwrap();
269     /// x509_name.append_entry_by_text("O", "Some organization").unwrap();
270     /// x509_name.append_entry_by_text("CN", "www.example.com").unwrap();
271     /// let x509_name = x509_name.build();
272     ///
273     /// let mut x509 = openssl::x509::X509::builder().unwrap();
274     /// x509.set_subject_name(&x509_name).unwrap();
275     /// ```
276     #[corresponds(X509_set_subject_name)]
set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack>277     pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
278         unsafe {
279             cvt(ffi::X509_set_subject_name(
280                 self.0.as_ptr(),
281                 subject_name.as_ptr(),
282             ))
283             .map(|_| ())
284         }
285     }
286 
287     /// Sets the public key associated with the certificate.
288     #[corresponds(X509_set_pubkey)]
set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPublic,289     pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
290     where
291         T: HasPublic,
292     {
293         unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
294     }
295 
296     /// Returns a context object which is needed to create certain X509 extension values.
297     ///
298     /// Set `issuer` to `None` if the certificate will be self-signed.
299     #[corresponds(X509V3_set_ctx)]
x509v3_context<'a>( &'a self, issuer: Option<&'a X509Ref>, conf: Option<&'a ConfRef>, ) -> X509v3Context<'a>300     pub fn x509v3_context<'a>(
301         &'a self,
302         issuer: Option<&'a X509Ref>,
303         conf: Option<&'a ConfRef>,
304     ) -> X509v3Context<'a> {
305         unsafe {
306             let mut ctx = mem::zeroed();
307 
308             let issuer = match issuer {
309                 Some(issuer) => issuer.as_ptr(),
310                 None => self.0.as_ptr(),
311             };
312             let subject = self.0.as_ptr();
313             ffi::X509V3_set_ctx(
314                 &mut ctx,
315                 issuer,
316                 subject,
317                 ptr::null_mut(),
318                 ptr::null_mut(),
319                 0,
320             );
321 
322             // nodb case taken care of since we zeroed ctx above
323             if let Some(conf) = conf {
324                 ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr());
325             }
326 
327             X509v3Context(ctx, PhantomData)
328         }
329     }
330 
331     /// Adds an X509 extension value to the certificate.
332     ///
333     /// This works just as `append_extension` except it takes ownership of the `X509Extension`.
append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack>334     pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> {
335         self.append_extension2(&extension)
336     }
337 
338     /// Adds an X509 extension value to the certificate.
339     #[corresponds(X509_add_ext)]
append_extension2(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack>340     pub fn append_extension2(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack> {
341         unsafe {
342             cvt(ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1))?;
343             Ok(())
344         }
345     }
346 
347     /// Signs the certificate with a private key.
348     #[corresponds(X509_sign)]
sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> where T: HasPrivate,349     pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
350     where
351         T: HasPrivate,
352     {
353         unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) }
354     }
355 
356     /// Signs the certificate with a private key but without a digest.
357     ///
358     /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null
359     /// message digest.
360     #[cfg(boringssl)]
361     #[corresponds(X509_sign)]
sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPrivate,362     pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
363     where
364         T: HasPrivate,
365     {
366         unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), ptr::null())).map(|_| ()) }
367     }
368 
369     /// Consumes the builder, returning the certificate.
build(self) -> X509370     pub fn build(self) -> X509 {
371         self.0
372     }
373 }
374 
375 foreign_type_and_impl_send_sync! {
376     type CType = ffi::X509;
377     fn drop = ffi::X509_free;
378 
379     /// An `X509` public key certificate.
380     pub struct X509;
381     /// Reference to `X509`.
382     pub struct X509Ref;
383 }
384 
385 #[cfg(boringssl)]
386 type X509LenTy = c_uint;
387 #[cfg(not(boringssl))]
388 type X509LenTy = c_int;
389 
390 impl X509Ref {
391     /// Returns this certificate's subject name.
392     #[corresponds(X509_get_subject_name)]
subject_name(&self) -> &X509NameRef393     pub fn subject_name(&self) -> &X509NameRef {
394         unsafe {
395             let name = ffi::X509_get_subject_name(self.as_ptr());
396             X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null")
397         }
398     }
399 
400     /// Returns the hash of the certificates subject
401     #[corresponds(X509_subject_name_hash)]
subject_name_hash(&self) -> u32402     pub fn subject_name_hash(&self) -> u32 {
403         unsafe { ffi::X509_subject_name_hash(self.as_ptr()) as u32 }
404     }
405 
406     /// Returns this certificate's issuer name.
407     #[corresponds(X509_get_issuer_name)]
issuer_name(&self) -> &X509NameRef408     pub fn issuer_name(&self) -> &X509NameRef {
409         unsafe {
410             let name = ffi::X509_get_issuer_name(self.as_ptr());
411             X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null")
412         }
413     }
414 
415     /// Returns the hash of the certificates issuer
416     #[corresponds(X509_issuer_name_hash)]
issuer_name_hash(&self) -> u32417     pub fn issuer_name_hash(&self) -> u32 {
418         unsafe { ffi::X509_issuer_name_hash(self.as_ptr()) as u32 }
419     }
420 
421     /// Returns this certificate's subject alternative name entries, if they exist.
422     #[corresponds(X509_get_ext_d2i)]
subject_alt_names(&self) -> Option<Stack<GeneralName>>423     pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> {
424         unsafe {
425             let stack = ffi::X509_get_ext_d2i(
426                 self.as_ptr(),
427                 ffi::NID_subject_alt_name,
428                 ptr::null_mut(),
429                 ptr::null_mut(),
430             );
431             Stack::from_ptr_opt(stack as *mut _)
432         }
433     }
434 
435     /// Returns this certificate's issuer alternative name entries, if they exist.
436     #[corresponds(X509_get_ext_d2i)]
issuer_alt_names(&self) -> Option<Stack<GeneralName>>437     pub fn issuer_alt_names(&self) -> Option<Stack<GeneralName>> {
438         unsafe {
439             let stack = ffi::X509_get_ext_d2i(
440                 self.as_ptr(),
441                 ffi::NID_issuer_alt_name,
442                 ptr::null_mut(),
443                 ptr::null_mut(),
444             );
445             Stack::from_ptr_opt(stack as *mut _)
446         }
447     }
448 
449     /// Returns this certificate's [`authority information access`] entries, if they exist.
450     ///
451     /// [`authority information access`]: https://tools.ietf.org/html/rfc5280#section-4.2.2.1
452     #[corresponds(X509_get_ext_d2i)]
authority_info(&self) -> Option<Stack<AccessDescription>>453     pub fn authority_info(&self) -> Option<Stack<AccessDescription>> {
454         unsafe {
455             let stack = ffi::X509_get_ext_d2i(
456                 self.as_ptr(),
457                 ffi::NID_info_access,
458                 ptr::null_mut(),
459                 ptr::null_mut(),
460             );
461             Stack::from_ptr_opt(stack as *mut _)
462         }
463     }
464 
465     #[corresponds(X509_get_pubkey)]
public_key(&self) -> Result<PKey<Public>, ErrorStack>466     pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
467         unsafe {
468             let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?;
469             Ok(PKey::from_ptr(pkey))
470         }
471     }
472 
473     /// Returns a digest of the DER representation of the certificate.
474     #[corresponds(X509_digest)]
digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack>475     pub fn digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack> {
476         unsafe {
477             let mut digest = DigestBytes {
478                 buf: [0; ffi::EVP_MAX_MD_SIZE as usize],
479                 len: ffi::EVP_MAX_MD_SIZE as usize,
480             };
481             let mut len = ffi::EVP_MAX_MD_SIZE as c_uint;
482             cvt(ffi::X509_digest(
483                 self.as_ptr(),
484                 hash_type.as_ptr(),
485                 digest.buf.as_mut_ptr() as *mut _,
486                 &mut len,
487             ))?;
488             digest.len = len as usize;
489 
490             Ok(digest)
491         }
492     }
493 
494     #[deprecated(since = "0.10.9", note = "renamed to digest")]
fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack>495     pub fn fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack> {
496         self.digest(hash_type).map(|b| b.to_vec())
497     }
498 
499     /// Returns the certificate's Not After validity period.
500     #[corresponds(X509_getm_notAfter)]
not_after(&self) -> &Asn1TimeRef501     pub fn not_after(&self) -> &Asn1TimeRef {
502         unsafe {
503             let date = X509_getm_notAfter(self.as_ptr());
504             Asn1TimeRef::from_const_ptr_opt(date).expect("not_after must not be null")
505         }
506     }
507 
508     /// Returns the certificate's Not Before validity period.
509     #[corresponds(X509_getm_notBefore)]
not_before(&self) -> &Asn1TimeRef510     pub fn not_before(&self) -> &Asn1TimeRef {
511         unsafe {
512             let date = X509_getm_notBefore(self.as_ptr());
513             Asn1TimeRef::from_const_ptr_opt(date).expect("not_before must not be null")
514         }
515     }
516 
517     /// Returns the certificate's signature
518     #[corresponds(X509_get0_signature)]
signature(&self) -> &Asn1BitStringRef519     pub fn signature(&self) -> &Asn1BitStringRef {
520         unsafe {
521             let mut signature = ptr::null();
522             X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr());
523             Asn1BitStringRef::from_const_ptr_opt(signature).expect("signature must not be null")
524         }
525     }
526 
527     /// Returns the certificate's signature algorithm.
528     #[corresponds(X509_get0_signature)]
signature_algorithm(&self) -> &X509AlgorithmRef529     pub fn signature_algorithm(&self) -> &X509AlgorithmRef {
530         unsafe {
531             let mut algor = ptr::null();
532             X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr());
533             X509AlgorithmRef::from_const_ptr_opt(algor)
534                 .expect("signature algorithm must not be null")
535         }
536     }
537 
538     /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information
539     /// Access field.
540     #[corresponds(X509_get1_ocsp)]
ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack>541     pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> {
542         unsafe { cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p)) }
543     }
544 
545     /// Checks that this certificate issued `subject`.
546     #[corresponds(X509_check_issued)]
issued(&self, subject: &X509Ref) -> X509VerifyResult547     pub fn issued(&self, subject: &X509Ref) -> X509VerifyResult {
548         unsafe {
549             let r = ffi::X509_check_issued(self.as_ptr(), subject.as_ptr());
550             X509VerifyResult::from_raw(r)
551         }
552     }
553 
554     /// Returns certificate version. If this certificate has no explicit version set, it defaults to
555     /// version 1.
556     ///
557     /// Note that `0` return value stands for version 1, `1` for version 2 and so on.
558     #[corresponds(X509_get_version)]
559     #[cfg(ossl110)]
version(&self) -> i32560     pub fn version(&self) -> i32 {
561         unsafe { ffi::X509_get_version(self.as_ptr()) as i32 }
562     }
563 
564     /// Check if the certificate is signed using the given public key.
565     ///
566     /// Only the signature is checked: no other checks (such as certificate chain validity)
567     /// are performed.
568     ///
569     /// Returns `true` if verification succeeds.
570     #[corresponds(X509_verify)]
verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack> where T: HasPublic,571     pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
572     where
573         T: HasPublic,
574     {
575         unsafe { cvt_n(ffi::X509_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
576     }
577 
578     /// Returns this certificate's serial number.
579     #[corresponds(X509_get_serialNumber)]
serial_number(&self) -> &Asn1IntegerRef580     pub fn serial_number(&self) -> &Asn1IntegerRef {
581         unsafe {
582             let r = ffi::X509_get_serialNumber(self.as_ptr());
583             Asn1IntegerRef::from_const_ptr_opt(r).expect("serial number must not be null")
584         }
585     }
586 
587     to_pem! {
588         /// Serializes the certificate into a PEM-encoded X509 structure.
589         ///
590         /// The output will have a header of `-----BEGIN CERTIFICATE-----`.
591         #[corresponds(PEM_write_bio_X509)]
592         to_pem,
593         ffi::PEM_write_bio_X509
594     }
595 
596     to_der! {
597         /// Serializes the certificate into a DER-encoded X509 structure.
598         #[corresponds(i2d_X509)]
599         to_der,
600         ffi::i2d_X509
601     }
602 
603     to_pem! {
604         /// Converts the certificate to human readable text.
605         #[corresponds(X509_print)]
606         to_text,
607         ffi::X509_print
608     }
609 }
610 
611 impl ToOwned for X509Ref {
612     type Owned = X509;
613 
to_owned(&self) -> X509614     fn to_owned(&self) -> X509 {
615         unsafe {
616             X509_up_ref(self.as_ptr());
617             X509::from_ptr(self.as_ptr())
618         }
619     }
620 }
621 
622 impl Ord for X509Ref {
cmp(&self, other: &Self) -> cmp::Ordering623     fn cmp(&self, other: &Self) -> cmp::Ordering {
624         // X509_cmp returns a number <0 for less than, 0 for equal and >0 for greater than.
625         // It can't fail if both pointers are valid, which we know is true.
626         let cmp = unsafe { ffi::X509_cmp(self.as_ptr(), other.as_ptr()) };
627         cmp.cmp(&0)
628     }
629 }
630 
631 impl PartialOrd for X509Ref {
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>632     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
633         Some(self.cmp(other))
634     }
635 }
636 
637 impl PartialOrd<X509> for X509Ref {
partial_cmp(&self, other: &X509) -> Option<cmp::Ordering>638     fn partial_cmp(&self, other: &X509) -> Option<cmp::Ordering> {
639         <X509Ref as PartialOrd<X509Ref>>::partial_cmp(self, other)
640     }
641 }
642 
643 impl PartialEq for X509Ref {
eq(&self, other: &Self) -> bool644     fn eq(&self, other: &Self) -> bool {
645         self.cmp(other) == cmp::Ordering::Equal
646     }
647 }
648 
649 impl PartialEq<X509> for X509Ref {
eq(&self, other: &X509) -> bool650     fn eq(&self, other: &X509) -> bool {
651         <X509Ref as PartialEq<X509Ref>>::eq(self, other)
652     }
653 }
654 
655 impl Eq for X509Ref {}
656 
657 impl X509 {
658     /// Returns a new builder.
builder() -> Result<X509Builder, ErrorStack>659     pub fn builder() -> Result<X509Builder, ErrorStack> {
660         X509Builder::new()
661     }
662 
663     from_pem! {
664         /// Deserializes a PEM-encoded X509 structure.
665         ///
666         /// The input should have a header of `-----BEGIN CERTIFICATE-----`.
667         #[corresponds(PEM_read_bio_X509)]
668         from_pem,
669         X509,
670         ffi::PEM_read_bio_X509
671     }
672 
673     from_der! {
674         /// Deserializes a DER-encoded X509 structure.
675         #[corresponds(d2i_X509)]
676         from_der,
677         X509,
678         ffi::d2i_X509
679     }
680 
681     /// Deserializes a list of PEM-formatted certificates.
682     #[corresponds(PEM_read_bio_X509)]
stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack>683     pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> {
684         unsafe {
685             ffi::init();
686             let bio = MemBioSlice::new(pem)?;
687 
688             let mut certs = vec![];
689             loop {
690                 let r =
691                     ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut());
692                 if r.is_null() {
693                     let err = ffi::ERR_peek_last_error();
694                     if ffi::ERR_GET_LIB(err) as X509LenTy == ffi::ERR_LIB_PEM
695                         && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE
696                     {
697                         ffi::ERR_clear_error();
698                         break;
699                     }
700 
701                     return Err(ErrorStack::get());
702                 } else {
703                     certs.push(X509(r));
704                 }
705             }
706 
707             Ok(certs)
708         }
709     }
710 }
711 
712 impl Clone for X509 {
clone(&self) -> X509713     fn clone(&self) -> X509 {
714         X509Ref::to_owned(self)
715     }
716 }
717 
718 impl fmt::Debug for X509 {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result719     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
720         let serial = match &self.serial_number().to_bn() {
721             Ok(bn) => match bn.to_hex_str() {
722                 Ok(hex) => hex.to_string(),
723                 Err(_) => "".to_string(),
724             },
725             Err(_) => "".to_string(),
726         };
727         let mut debug_struct = formatter.debug_struct("X509");
728         debug_struct.field("serial_number", &serial);
729         debug_struct.field("signature_algorithm", &self.signature_algorithm().object());
730         debug_struct.field("issuer", &self.issuer_name());
731         debug_struct.field("subject", &self.subject_name());
732         if let Some(subject_alt_names) = &self.subject_alt_names() {
733             debug_struct.field("subject_alt_names", subject_alt_names);
734         }
735         debug_struct.field("not_before", &self.not_before());
736         debug_struct.field("not_after", &self.not_after());
737 
738         if let Ok(public_key) = &self.public_key() {
739             debug_struct.field("public_key", public_key);
740         };
741         // TODO: Print extensions once they are supported on the X509 struct.
742 
743         debug_struct.finish()
744     }
745 }
746 
747 impl AsRef<X509Ref> for X509Ref {
as_ref(&self) -> &X509Ref748     fn as_ref(&self) -> &X509Ref {
749         self
750     }
751 }
752 
753 impl Stackable for X509 {
754     type StackType = ffi::stack_st_X509;
755 }
756 
757 impl Ord for X509 {
cmp(&self, other: &Self) -> cmp::Ordering758     fn cmp(&self, other: &Self) -> cmp::Ordering {
759         X509Ref::cmp(self, other)
760     }
761 }
762 
763 impl PartialOrd for X509 {
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>764     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
765         X509Ref::partial_cmp(self, other)
766     }
767 }
768 
769 impl PartialOrd<X509Ref> for X509 {
partial_cmp(&self, other: &X509Ref) -> Option<cmp::Ordering>770     fn partial_cmp(&self, other: &X509Ref) -> Option<cmp::Ordering> {
771         X509Ref::partial_cmp(self, other)
772     }
773 }
774 
775 impl PartialEq for X509 {
eq(&self, other: &Self) -> bool776     fn eq(&self, other: &Self) -> bool {
777         X509Ref::eq(self, other)
778     }
779 }
780 
781 impl PartialEq<X509Ref> for X509 {
eq(&self, other: &X509Ref) -> bool782     fn eq(&self, other: &X509Ref) -> bool {
783         X509Ref::eq(self, other)
784     }
785 }
786 
787 impl Eq for X509 {}
788 
789 /// A context object required to construct certain `X509` extension values.
790 pub struct X509v3Context<'a>(ffi::X509V3_CTX, PhantomData<(&'a X509Ref, &'a ConfRef)>);
791 
792 impl<'a> X509v3Context<'a> {
as_ptr(&self) -> *mut ffi::X509V3_CTX793     pub fn as_ptr(&self) -> *mut ffi::X509V3_CTX {
794         &self.0 as *const _ as *mut _
795     }
796 }
797 
798 foreign_type_and_impl_send_sync! {
799     type CType = ffi::X509_EXTENSION;
800     fn drop = ffi::X509_EXTENSION_free;
801 
802     /// Permit additional fields to be added to an `X509` v3 certificate.
803     pub struct X509Extension;
804     /// Reference to `X509Extension`.
805     pub struct X509ExtensionRef;
806 }
807 
808 impl Stackable for X509Extension {
809     type StackType = ffi::stack_st_X509_EXTENSION;
810 }
811 
812 impl X509Extension {
813     /// Constructs an X509 extension value. See `man x509v3_config` for information on supported
814     /// names and their value formats.
815     ///
816     /// Some extension types, such as `subjectAlternativeName`, require an `X509v3Context` to be
817     /// provided.
818     ///
819     /// See the extension module for builder types which will construct certain common extensions.
new( conf: Option<&ConfRef>, context: Option<&X509v3Context<'_>>, name: &str, value: &str, ) -> Result<X509Extension, ErrorStack>820     pub fn new(
821         conf: Option<&ConfRef>,
822         context: Option<&X509v3Context<'_>>,
823         name: &str,
824         value: &str,
825     ) -> Result<X509Extension, ErrorStack> {
826         let name = CString::new(name).unwrap();
827         let value = CString::new(value).unwrap();
828         unsafe {
829             ffi::init();
830             let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr);
831             let context = context.map_or(ptr::null_mut(), X509v3Context::as_ptr);
832             let name = name.as_ptr() as *mut _;
833             let value = value.as_ptr() as *mut _;
834 
835             cvt_p(ffi::X509V3_EXT_nconf(conf, context, name, value)).map(X509Extension)
836         }
837     }
838 
839     /// Constructs an X509 extension value. See `man x509v3_config` for information on supported
840     /// extensions and their value formats.
841     ///
842     /// Some extension types, such as `nid::SUBJECT_ALTERNATIVE_NAME`, require an `X509v3Context` to
843     /// be provided.
844     ///
845     /// See the extension module for builder types which will construct certain common extensions.
new_nid( conf: Option<&ConfRef>, context: Option<&X509v3Context<'_>>, name: Nid, value: &str, ) -> Result<X509Extension, ErrorStack>846     pub fn new_nid(
847         conf: Option<&ConfRef>,
848         context: Option<&X509v3Context<'_>>,
849         name: Nid,
850         value: &str,
851     ) -> Result<X509Extension, ErrorStack> {
852         let value = CString::new(value).unwrap();
853         unsafe {
854             ffi::init();
855             let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr);
856             let context = context.map_or(ptr::null_mut(), X509v3Context::as_ptr);
857             let name = name.as_raw();
858             let value = value.as_ptr() as *mut _;
859 
860             cvt_p(ffi::X509V3_EXT_nconf_nid(conf, context, name, value)).map(X509Extension)
861         }
862     }
863 
864     /// Adds an alias for an extension
865     ///
866     /// # Safety
867     ///
868     /// This method modifies global state without locking and therefore is not thread safe
869     #[corresponds(X509V3_EXT_add_alias)]
add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack>870     pub unsafe fn add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack> {
871         ffi::init();
872         cvt(ffi::X509V3_EXT_add_alias(to.as_raw(), from.as_raw())).map(|_| ())
873     }
874 }
875 
876 /// A builder used to construct an `X509Name`.
877 pub struct X509NameBuilder(X509Name);
878 
879 impl X509NameBuilder {
880     /// Creates a new builder.
new() -> Result<X509NameBuilder, ErrorStack>881     pub fn new() -> Result<X509NameBuilder, ErrorStack> {
882         unsafe {
883             ffi::init();
884             cvt_p(ffi::X509_NAME_new()).map(|p| X509NameBuilder(X509Name(p)))
885         }
886     }
887 
888     /// Add a field entry by str.
889     ///
890     /// This corresponds to [`X509_NAME_add_entry_by_txt`].
891     ///
892     /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html
append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack>893     pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
894         unsafe {
895             let field = CString::new(field).unwrap();
896             assert!(value.len() <= isize::max_value() as usize);
897             cvt(ffi::X509_NAME_add_entry_by_txt(
898                 self.0.as_ptr(),
899                 field.as_ptr() as *mut _,
900                 ffi::MBSTRING_UTF8,
901                 value.as_ptr(),
902                 value.len() as isize,
903                 -1,
904                 0,
905             ))
906             .map(|_| ())
907         }
908     }
909 
910     /// Add a field entry by str with a specific type.
911     ///
912     /// This corresponds to [`X509_NAME_add_entry_by_txt`].
913     ///
914     /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html
append_entry_by_text_with_type( &mut self, field: &str, value: &str, ty: Asn1Type, ) -> Result<(), ErrorStack>915     pub fn append_entry_by_text_with_type(
916         &mut self,
917         field: &str,
918         value: &str,
919         ty: Asn1Type,
920     ) -> Result<(), ErrorStack> {
921         unsafe {
922             let field = CString::new(field).unwrap();
923             assert!(value.len() <= isize::max_value() as usize);
924             cvt(ffi::X509_NAME_add_entry_by_txt(
925                 self.0.as_ptr(),
926                 field.as_ptr() as *mut _,
927                 ty.as_raw(),
928                 value.as_ptr(),
929                 value.len() as isize,
930                 -1,
931                 0,
932             ))
933             .map(|_| ())
934         }
935     }
936 
937     /// Add a field entry by NID.
938     ///
939     /// This corresponds to [`X509_NAME_add_entry_by_NID`].
940     ///
941     /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html
append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack>942     pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
943         unsafe {
944             assert!(value.len() <= isize::max_value() as usize);
945             cvt(ffi::X509_NAME_add_entry_by_NID(
946                 self.0.as_ptr(),
947                 field.as_raw(),
948                 ffi::MBSTRING_UTF8,
949                 value.as_ptr() as *mut _,
950                 value.len() as isize,
951                 -1,
952                 0,
953             ))
954             .map(|_| ())
955         }
956     }
957 
958     /// Add a field entry by NID with a specific type.
959     ///
960     /// This corresponds to [`X509_NAME_add_entry_by_NID`].
961     ///
962     /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html
append_entry_by_nid_with_type( &mut self, field: Nid, value: &str, ty: Asn1Type, ) -> Result<(), ErrorStack>963     pub fn append_entry_by_nid_with_type(
964         &mut self,
965         field: Nid,
966         value: &str,
967         ty: Asn1Type,
968     ) -> Result<(), ErrorStack> {
969         unsafe {
970             assert!(value.len() <= isize::max_value() as usize);
971             cvt(ffi::X509_NAME_add_entry_by_NID(
972                 self.0.as_ptr(),
973                 field.as_raw(),
974                 ty.as_raw(),
975                 value.as_ptr() as *mut _,
976                 value.len() as isize,
977                 -1,
978                 0,
979             ))
980             .map(|_| ())
981         }
982     }
983 
984     /// Return an `X509Name`.
build(self) -> X509Name985     pub fn build(self) -> X509Name {
986         self.0
987     }
988 }
989 
990 foreign_type_and_impl_send_sync! {
991     type CType = ffi::X509_NAME;
992     fn drop = ffi::X509_NAME_free;
993 
994     /// The names of an `X509` certificate.
995     pub struct X509Name;
996     /// Reference to `X509Name`.
997     pub struct X509NameRef;
998 }
999 
1000 impl X509Name {
1001     /// Returns a new builder.
builder() -> Result<X509NameBuilder, ErrorStack>1002     pub fn builder() -> Result<X509NameBuilder, ErrorStack> {
1003         X509NameBuilder::new()
1004     }
1005 
1006     /// Loads subject names from a file containing PEM-formatted certificates.
1007     ///
1008     /// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack>1009     pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> {
1010         let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1011         unsafe { cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p)) }
1012     }
1013 
1014     from_der! {
1015         /// Deserializes a DER-encoded X509 name structure.
1016         ///
1017         /// This corresponds to [`d2i_X509_NAME`].
1018         ///
1019         /// [`d2i_X509_NAME`]: https://www.openssl.org/docs/manmaster/man3/d2i_X509_NAME.html
1020         from_der,
1021         X509Name,
1022         ffi::d2i_X509_NAME
1023     }
1024 }
1025 
1026 impl Stackable for X509Name {
1027     type StackType = ffi::stack_st_X509_NAME;
1028 }
1029 
1030 impl X509NameRef {
1031     /// Returns the name entries by the nid.
entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_>1032     pub fn entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_> {
1033         X509NameEntries {
1034             name: self,
1035             nid: Some(nid),
1036             loc: -1,
1037         }
1038     }
1039 
1040     /// Returns an iterator over all `X509NameEntry` values
entries(&self) -> X509NameEntries<'_>1041     pub fn entries(&self) -> X509NameEntries<'_> {
1042         X509NameEntries {
1043             name: self,
1044             nid: None,
1045             loc: -1,
1046         }
1047     }
1048 
1049     /// Compare two names, like [`Ord`] but it may fail.
1050     ///
1051     /// With OpenSSL versions from 3.0.0 this may return an error if the underlying `X509_NAME_cmp`
1052     /// call fails.
1053     /// For OpenSSL versions before 3.0.0 it will never return an error, but due to a bug it may
1054     /// spuriously return `Ordering::Less` if the `X509_NAME_cmp` call fails.
1055     #[corresponds(X509_NAME_cmp)]
try_cmp(&self, other: &X509NameRef) -> Result<Ordering, ErrorStack>1056     pub fn try_cmp(&self, other: &X509NameRef) -> Result<Ordering, ErrorStack> {
1057         let cmp = unsafe { ffi::X509_NAME_cmp(self.as_ptr(), other.as_ptr()) };
1058         if cfg!(ossl300) && cmp == -2 {
1059             return Err(ErrorStack::get());
1060         }
1061         Ok(cmp.cmp(&0))
1062     }
1063 
1064     to_der! {
1065         /// Serializes the certificate into a DER-encoded X509 name structure.
1066         ///
1067         /// This corresponds to [`i2d_X509_NAME`].
1068         ///
1069         /// [`i2d_X509_NAME`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_X509_NAME.html
1070         to_der,
1071         ffi::i2d_X509_NAME
1072     }
1073 }
1074 
1075 impl fmt::Debug for X509NameRef {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result1076     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1077         formatter.debug_list().entries(self.entries()).finish()
1078     }
1079 }
1080 
1081 /// A type to destructure and examine an `X509Name`.
1082 pub struct X509NameEntries<'a> {
1083     name: &'a X509NameRef,
1084     nid: Option<Nid>,
1085     loc: c_int,
1086 }
1087 
1088 impl<'a> Iterator for X509NameEntries<'a> {
1089     type Item = &'a X509NameEntryRef;
1090 
next(&mut self) -> Option<&'a X509NameEntryRef>1091     fn next(&mut self) -> Option<&'a X509NameEntryRef> {
1092         unsafe {
1093             match self.nid {
1094                 Some(nid) => {
1095                     // There is a `Nid` specified to search for
1096                     self.loc =
1097                         ffi::X509_NAME_get_index_by_NID(self.name.as_ptr(), nid.as_raw(), self.loc);
1098                     if self.loc == -1 {
1099                         return None;
1100                     }
1101                 }
1102                 None => {
1103                     // Iterate over all `Nid`s
1104                     self.loc += 1;
1105                     if self.loc >= ffi::X509_NAME_entry_count(self.name.as_ptr()) {
1106                         return None;
1107                     }
1108                 }
1109             }
1110 
1111             let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc);
1112 
1113             Some(X509NameEntryRef::from_const_ptr_opt(entry).expect("entry must not be null"))
1114         }
1115     }
1116 }
1117 
1118 foreign_type_and_impl_send_sync! {
1119     type CType = ffi::X509_NAME_ENTRY;
1120     fn drop = ffi::X509_NAME_ENTRY_free;
1121 
1122     /// A name entry associated with a `X509Name`.
1123     pub struct X509NameEntry;
1124     /// Reference to `X509NameEntry`.
1125     pub struct X509NameEntryRef;
1126 }
1127 
1128 impl X509NameEntryRef {
1129     /// Returns the field value of an `X509NameEntry`.
1130     ///
1131     /// This corresponds to [`X509_NAME_ENTRY_get_data`].
1132     ///
1133     /// [`X509_NAME_ENTRY_get_data`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_data.html
data(&self) -> &Asn1StringRef1134     pub fn data(&self) -> &Asn1StringRef {
1135         unsafe {
1136             let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr());
1137             Asn1StringRef::from_ptr(data)
1138         }
1139     }
1140 
1141     /// Returns the `Asn1Object` value of an `X509NameEntry`.
1142     /// This is useful for finding out about the actual `Nid` when iterating over all `X509NameEntries`.
1143     ///
1144     /// This corresponds to [`X509_NAME_ENTRY_get_object`].
1145     ///
1146     /// [`X509_NAME_ENTRY_get_object`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_object.html
object(&self) -> &Asn1ObjectRef1147     pub fn object(&self) -> &Asn1ObjectRef {
1148         unsafe {
1149             let object = ffi::X509_NAME_ENTRY_get_object(self.as_ptr());
1150             Asn1ObjectRef::from_ptr(object)
1151         }
1152     }
1153 }
1154 
1155 impl fmt::Debug for X509NameEntryRef {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result1156     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1157         formatter.write_fmt(format_args!("{:?} = {:?}", self.object(), self.data()))
1158     }
1159 }
1160 
1161 /// A builder used to construct an `X509Req`.
1162 pub struct X509ReqBuilder(X509Req);
1163 
1164 impl X509ReqBuilder {
1165     /// Returns a builder for a certificate request.
1166     ///
1167     /// This corresponds to [`X509_REQ_new`].
1168     ///
1169     ///[`X509_REQ_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_new.html
new() -> Result<X509ReqBuilder, ErrorStack>1170     pub fn new() -> Result<X509ReqBuilder, ErrorStack> {
1171         unsafe {
1172             ffi::init();
1173             cvt_p(ffi::X509_REQ_new()).map(|p| X509ReqBuilder(X509Req(p)))
1174         }
1175     }
1176 
1177     /// Set the numerical value of the version field.
1178     ///
1179     /// This corresponds to [`X509_REQ_set_version`].
1180     ///
1181     ///[`X509_REQ_set_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_version.html
set_version(&mut self, version: i32) -> Result<(), ErrorStack>1182     pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
1183         unsafe {
1184             cvt(ffi::X509_REQ_set_version(
1185                 self.0.as_ptr(),
1186                 version as c_long,
1187             ))
1188             .map(|_| ())
1189         }
1190     }
1191 
1192     /// Set the issuer name.
1193     ///
1194     /// This corresponds to [`X509_REQ_set_subject_name`].
1195     ///
1196     /// [`X509_REQ_set_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_subject_name.html
set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack>1197     pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
1198         unsafe {
1199             cvt(ffi::X509_REQ_set_subject_name(
1200                 self.0.as_ptr(),
1201                 subject_name.as_ptr(),
1202             ))
1203             .map(|_| ())
1204         }
1205     }
1206 
1207     /// Set the public key.
1208     ///
1209     /// This corresponds to [`X509_REQ_set_pubkey`].
1210     ///
1211     /// [`X509_REQ_set_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_pubkey.html
set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPublic,1212     pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1213     where
1214         T: HasPublic,
1215     {
1216         unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
1217     }
1218 
1219     /// Return an `X509v3Context`. This context object can be used to construct
1220     /// certain `X509` extensions.
x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a>1221     pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> {
1222         unsafe {
1223             let mut ctx = mem::zeroed();
1224 
1225             ffi::X509V3_set_ctx(
1226                 &mut ctx,
1227                 ptr::null_mut(),
1228                 ptr::null_mut(),
1229                 self.0.as_ptr(),
1230                 ptr::null_mut(),
1231                 0,
1232             );
1233 
1234             // nodb case taken care of since we zeroed ctx above
1235             if let Some(conf) = conf {
1236                 ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr());
1237             }
1238 
1239             X509v3Context(ctx, PhantomData)
1240         }
1241     }
1242 
1243     /// Permits any number of extension fields to be added to the certificate.
add_extensions( &mut self, extensions: &StackRef<X509Extension>, ) -> Result<(), ErrorStack>1244     pub fn add_extensions(
1245         &mut self,
1246         extensions: &StackRef<X509Extension>,
1247     ) -> Result<(), ErrorStack> {
1248         unsafe {
1249             cvt(ffi::X509_REQ_add_extensions(
1250                 self.0.as_ptr(),
1251                 extensions.as_ptr(),
1252             ))
1253             .map(|_| ())
1254         }
1255     }
1256 
1257     /// Sign the request using a private key.
1258     ///
1259     /// This corresponds to [`X509_REQ_sign`].
1260     ///
1261     /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html
sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> where T: HasPrivate,1262     pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
1263     where
1264         T: HasPrivate,
1265     {
1266         unsafe {
1267             cvt(ffi::X509_REQ_sign(
1268                 self.0.as_ptr(),
1269                 key.as_ptr(),
1270                 hash.as_ptr(),
1271             ))
1272             .map(|_| ())
1273         }
1274     }
1275 
1276     /// Sign the request using a private key without a digest.
1277     ///
1278     /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null
1279     /// message digest.
1280     ///
1281     /// This corresponds to [`X509_REQ_sign`].
1282     ///
1283     /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html
1284     #[cfg(boringssl)]
sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPrivate,1285     pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1286     where
1287         T: HasPrivate,
1288     {
1289         unsafe {
1290             cvt(ffi::X509_REQ_sign(
1291                 self.0.as_ptr(),
1292                 key.as_ptr(),
1293                 ptr::null(),
1294             ))
1295             .map(|_| ())
1296         }
1297     }
1298 
1299     /// Returns the `X509Req`.
build(self) -> X509Req1300     pub fn build(self) -> X509Req {
1301         self.0
1302     }
1303 }
1304 
1305 foreign_type_and_impl_send_sync! {
1306     type CType = ffi::X509_REQ;
1307     fn drop = ffi::X509_REQ_free;
1308 
1309     /// An `X509` certificate request.
1310     pub struct X509Req;
1311     /// Reference to `X509Req`.
1312     pub struct X509ReqRef;
1313 }
1314 
1315 impl X509Req {
1316     /// A builder for `X509Req`.
builder() -> Result<X509ReqBuilder, ErrorStack>1317     pub fn builder() -> Result<X509ReqBuilder, ErrorStack> {
1318         X509ReqBuilder::new()
1319     }
1320 
1321     from_pem! {
1322         /// Deserializes a PEM-encoded PKCS#10 certificate request structure.
1323         ///
1324         /// The input should have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
1325         ///
1326         /// This corresponds to [`PEM_read_bio_X509_REQ`].
1327         ///
1328         /// [`PEM_read_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509_REQ.html
1329         from_pem,
1330         X509Req,
1331         ffi::PEM_read_bio_X509_REQ
1332     }
1333 
1334     from_der! {
1335         /// Deserializes a DER-encoded PKCS#10 certificate request structure.
1336         ///
1337         /// This corresponds to [`d2i_X509_REQ`].
1338         ///
1339         /// [`d2i_X509_REQ`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_X509_REQ.html
1340         from_der,
1341         X509Req,
1342         ffi::d2i_X509_REQ
1343     }
1344 }
1345 
1346 impl X509ReqRef {
1347     to_pem! {
1348         /// Serializes the certificate request to a PEM-encoded PKCS#10 structure.
1349         ///
1350         /// The output will have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
1351         ///
1352         /// This corresponds to [`PEM_write_bio_X509_REQ`].
1353         ///
1354         /// [`PEM_write_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509_REQ.html
1355         to_pem,
1356         ffi::PEM_write_bio_X509_REQ
1357     }
1358 
1359     to_der! {
1360         /// Serializes the certificate request to a DER-encoded PKCS#10 structure.
1361         ///
1362         /// This corresponds to [`i2d_X509_REQ`].
1363         ///
1364         /// [`i2d_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_X509_REQ.html
1365         to_der,
1366         ffi::i2d_X509_REQ
1367     }
1368 
1369     to_pem! {
1370         /// Converts the request to human readable text.
1371         #[corresponds(X509_Req_print)]
1372         to_text,
1373         ffi::X509_REQ_print
1374     }
1375 
1376     /// Returns the numerical value of the version field of the certificate request.
1377     ///
1378     /// This corresponds to [`X509_REQ_get_version`]
1379     ///
1380     /// [`X509_REQ_get_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_version.html
version(&self) -> i321381     pub fn version(&self) -> i32 {
1382         unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
1383     }
1384 
1385     /// Returns the subject name of the certificate request.
1386     ///
1387     /// This corresponds to [`X509_REQ_get_subject_name`]
1388     ///
1389     /// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_subject_name.html
subject_name(&self) -> &X509NameRef1390     pub fn subject_name(&self) -> &X509NameRef {
1391         unsafe {
1392             let name = X509_REQ_get_subject_name(self.as_ptr());
1393             X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null")
1394         }
1395     }
1396 
1397     /// Returns the public key of the certificate request.
1398     ///
1399     /// This corresponds to [`X509_REQ_get_pubkey"]
1400     ///
1401     /// [`X509_REQ_get_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_pubkey.html
public_key(&self) -> Result<PKey<Public>, ErrorStack>1402     pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
1403         unsafe {
1404             let key = cvt_p(ffi::X509_REQ_get_pubkey(self.as_ptr()))?;
1405             Ok(PKey::from_ptr(key))
1406         }
1407     }
1408 
1409     /// Check if the certificate request is signed using the given public key.
1410     ///
1411     /// Returns `true` if verification succeeds.
1412     ///
1413     /// This corresponds to [`X509_REQ_verify"].
1414     ///
1415     /// [`X509_REQ_verify`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_verify.html
verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack> where T: HasPublic,1416     pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
1417     where
1418         T: HasPublic,
1419     {
1420         unsafe { cvt_n(ffi::X509_REQ_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
1421     }
1422 
1423     /// Returns the extensions of the certificate request.
1424     ///
1425     /// This corresponds to [`X509_REQ_get_extensions"]
extensions(&self) -> Result<Stack<X509Extension>, ErrorStack>1426     pub fn extensions(&self) -> Result<Stack<X509Extension>, ErrorStack> {
1427         unsafe {
1428             let extensions = cvt_p(ffi::X509_REQ_get_extensions(self.as_ptr()))?;
1429             Ok(Stack::from_ptr(extensions))
1430         }
1431     }
1432 }
1433 
1434 /// The result of peer certificate verification.
1435 #[derive(Copy, Clone, PartialEq, Eq)]
1436 pub struct X509VerifyResult(c_int);
1437 
1438 impl fmt::Debug for X509VerifyResult {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1439     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1440         fmt.debug_struct("X509VerifyResult")
1441             .field("code", &self.0)
1442             .field("error", &self.error_string())
1443             .finish()
1444     }
1445 }
1446 
1447 impl fmt::Display for X509VerifyResult {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1448     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1449         fmt.write_str(self.error_string())
1450     }
1451 }
1452 
1453 impl Error for X509VerifyResult {}
1454 
1455 impl X509VerifyResult {
1456     /// Creates an `X509VerifyResult` from a raw error number.
1457     ///
1458     /// # Safety
1459     ///
1460     /// Some methods on `X509VerifyResult` are not thread safe if the error
1461     /// number is invalid.
from_raw(err: c_int) -> X509VerifyResult1462     pub unsafe fn from_raw(err: c_int) -> X509VerifyResult {
1463         X509VerifyResult(err)
1464     }
1465 
1466     /// Return the integer representation of an `X509VerifyResult`.
1467     #[allow(clippy::trivially_copy_pass_by_ref)]
as_raw(&self) -> c_int1468     pub fn as_raw(&self) -> c_int {
1469         self.0
1470     }
1471 
1472     /// Return a human readable error string from the verification error.
1473     ///
1474     /// This corresponds to [`X509_verify_cert_error_string`].
1475     ///
1476     /// [`X509_verify_cert_error_string`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_verify_cert_error_string.html
1477     #[allow(clippy::trivially_copy_pass_by_ref)]
error_string(&self) -> &'static str1478     pub fn error_string(&self) -> &'static str {
1479         ffi::init();
1480 
1481         unsafe {
1482             let s = ffi::X509_verify_cert_error_string(self.0 as c_long);
1483             str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
1484         }
1485     }
1486 
1487     /// Successful peer certificate verification.
1488     pub const OK: X509VerifyResult = X509VerifyResult(ffi::X509_V_OK);
1489     /// Application verification failure.
1490     pub const APPLICATION_VERIFICATION: X509VerifyResult =
1491         X509VerifyResult(ffi::X509_V_ERR_APPLICATION_VERIFICATION);
1492 }
1493 
1494 foreign_type_and_impl_send_sync! {
1495     type CType = ffi::GENERAL_NAME;
1496     fn drop = ffi::GENERAL_NAME_free;
1497 
1498     /// An `X509` certificate alternative names.
1499     pub struct GeneralName;
1500     /// Reference to `GeneralName`.
1501     pub struct GeneralNameRef;
1502 }
1503 
1504 impl GeneralNameRef {
ia5_string(&self, ffi_type: c_int) -> Option<&str>1505     fn ia5_string(&self, ffi_type: c_int) -> Option<&str> {
1506         unsafe {
1507             if (*self.as_ptr()).type_ != ffi_type {
1508                 return None;
1509             }
1510 
1511             #[cfg(boringssl)]
1512             let d = (*self.as_ptr()).d.ptr;
1513             #[cfg(not(boringssl))]
1514             let d = (*self.as_ptr()).d;
1515 
1516             let ptr = ASN1_STRING_get0_data(d as *mut _);
1517             let len = ffi::ASN1_STRING_length(d as *mut _);
1518 
1519             let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
1520             // IA5Strings are stated to be ASCII (specifically IA5). Hopefully
1521             // OpenSSL checks that when loading a certificate but if not we'll
1522             // use this instead of from_utf8_unchecked just in case.
1523             str::from_utf8(slice).ok()
1524         }
1525     }
1526 
1527     /// Returns the contents of this `GeneralName` if it is an `rfc822Name`.
email(&self) -> Option<&str>1528     pub fn email(&self) -> Option<&str> {
1529         self.ia5_string(ffi::GEN_EMAIL)
1530     }
1531 
1532     /// Returns the contents of this `GeneralName` if it is a `dNSName`.
dnsname(&self) -> Option<&str>1533     pub fn dnsname(&self) -> Option<&str> {
1534         self.ia5_string(ffi::GEN_DNS)
1535     }
1536 
1537     /// Returns the contents of this `GeneralName` if it is an `uniformResourceIdentifier`.
uri(&self) -> Option<&str>1538     pub fn uri(&self) -> Option<&str> {
1539         self.ia5_string(ffi::GEN_URI)
1540     }
1541 
1542     /// Returns the contents of this `GeneralName` if it is an `iPAddress`.
ipaddress(&self) -> Option<&[u8]>1543     pub fn ipaddress(&self) -> Option<&[u8]> {
1544         unsafe {
1545             if (*self.as_ptr()).type_ != ffi::GEN_IPADD {
1546                 return None;
1547             }
1548             #[cfg(boringssl)]
1549             let d: *const ffi::ASN1_STRING = std::mem::transmute((*self.as_ptr()).d);
1550             #[cfg(not(boringssl))]
1551             let d = (*self.as_ptr()).d;
1552 
1553             let ptr = ASN1_STRING_get0_data(d as *mut _);
1554             let len = ffi::ASN1_STRING_length(d as *mut _);
1555 
1556             Some(slice::from_raw_parts(ptr as *const u8, len as usize))
1557         }
1558     }
1559 }
1560 
1561 impl fmt::Debug for GeneralNameRef {
fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result1562     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1563         if let Some(email) = self.email() {
1564             formatter.write_str(email)
1565         } else if let Some(dnsname) = self.dnsname() {
1566             formatter.write_str(dnsname)
1567         } else if let Some(uri) = self.uri() {
1568             formatter.write_str(uri)
1569         } else if let Some(ipaddress) = self.ipaddress() {
1570             let result = String::from_utf8_lossy(ipaddress);
1571             formatter.write_str(&result)
1572         } else {
1573             formatter.write_str("(empty)")
1574         }
1575     }
1576 }
1577 
1578 impl Stackable for GeneralName {
1579     type StackType = ffi::stack_st_GENERAL_NAME;
1580 }
1581 
1582 foreign_type_and_impl_send_sync! {
1583     type CType = ffi::ACCESS_DESCRIPTION;
1584     fn drop = ffi::ACCESS_DESCRIPTION_free;
1585 
1586     /// `AccessDescription` of certificate authority information.
1587     pub struct AccessDescription;
1588     /// Reference to `AccessDescription`.
1589     pub struct AccessDescriptionRef;
1590 }
1591 
1592 impl AccessDescriptionRef {
1593     /// Returns the access method OID.
method(&self) -> &Asn1ObjectRef1594     pub fn method(&self) -> &Asn1ObjectRef {
1595         unsafe { Asn1ObjectRef::from_ptr((*self.as_ptr()).method) }
1596     }
1597 
1598     // Returns the access location.
location(&self) -> &GeneralNameRef1599     pub fn location(&self) -> &GeneralNameRef {
1600         unsafe { GeneralNameRef::from_ptr((*self.as_ptr()).location) }
1601     }
1602 }
1603 
1604 impl Stackable for AccessDescription {
1605     type StackType = ffi::stack_st_ACCESS_DESCRIPTION;
1606 }
1607 
1608 foreign_type_and_impl_send_sync! {
1609     type CType = ffi::X509_ALGOR;
1610     fn drop = ffi::X509_ALGOR_free;
1611 
1612     /// An `X509` certificate signature algorithm.
1613     pub struct X509Algorithm;
1614     /// Reference to `X509Algorithm`.
1615     pub struct X509AlgorithmRef;
1616 }
1617 
1618 impl X509AlgorithmRef {
1619     /// Returns the ASN.1 OID of this algorithm.
object(&self) -> &Asn1ObjectRef1620     pub fn object(&self) -> &Asn1ObjectRef {
1621         unsafe {
1622             let mut oid = ptr::null();
1623             X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr());
1624             Asn1ObjectRef::from_const_ptr_opt(oid).expect("algorithm oid must not be null")
1625         }
1626     }
1627 }
1628 
1629 foreign_type_and_impl_send_sync! {
1630     type CType = ffi::X509_OBJECT;
1631     fn drop = X509_OBJECT_free;
1632 
1633     /// An `X509` or an X509 certificate revocation list.
1634     pub struct X509Object;
1635     /// Reference to `X509Object`
1636     pub struct X509ObjectRef;
1637 }
1638 
1639 impl X509ObjectRef {
x509(&self) -> Option<&X509Ref>1640     pub fn x509(&self) -> Option<&X509Ref> {
1641         unsafe {
1642             let ptr = X509_OBJECT_get0_X509(self.as_ptr());
1643             X509Ref::from_const_ptr_opt(ptr)
1644         }
1645     }
1646 }
1647 
1648 impl Stackable for X509Object {
1649     type StackType = ffi::stack_st_X509_OBJECT;
1650 }
1651 
1652 cfg_if! {
1653     if #[cfg(any(boringssl, ossl110, libressl273))] {
1654         use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature};
1655     } else {
1656         #[allow(bad_style)]
1657         unsafe fn X509_getm_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
1658             (*(*(*x).cert_info).validity).notAfter
1659         }
1660 
1661         #[allow(bad_style)]
1662         unsafe fn X509_getm_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
1663             (*(*(*x).cert_info).validity).notBefore
1664         }
1665 
1666         #[allow(bad_style)]
1667         unsafe fn X509_up_ref(x: *mut ffi::X509) {
1668             ffi::CRYPTO_add_lock(
1669                 &mut (*x).references,
1670                 1,
1671                 ffi::CRYPTO_LOCK_X509,
1672                 "mod.rs\0".as_ptr() as *const _,
1673                 line!() as c_int,
1674             );
1675         }
1676 
1677         #[allow(bad_style)]
1678         unsafe fn X509_get0_signature(
1679             psig: *mut *const ffi::ASN1_BIT_STRING,
1680             palg: *mut *const ffi::X509_ALGOR,
1681             x: *const ffi::X509,
1682         ) {
1683             if !psig.is_null() {
1684                 *psig = (*x).signature;
1685             }
1686             if !palg.is_null() {
1687                 *palg = (*x).sig_alg;
1688             }
1689         }
1690     }
1691 }
1692 
1693 cfg_if! {
1694     if #[cfg(any(boringssl, ossl110, libressl350))] {
1695         use ffi::{
1696             X509_ALGOR_get0, ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter,
1697             X509_set1_notBefore, X509_REQ_get_version, X509_REQ_get_subject_name,
1698         };
1699     } else {
1700         use ffi::{
1701             ASN1_STRING_data as ASN1_STRING_get0_data,
1702             X509_STORE_CTX_get_chain as X509_STORE_CTX_get0_chain,
1703             X509_set_notAfter as X509_set1_notAfter,
1704             X509_set_notBefore as X509_set1_notBefore,
1705         };
1706 
1707         #[allow(bad_style)]
1708         unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long {
1709             ffi::ASN1_INTEGER_get((*(*x).req_info).version)
1710         }
1711 
1712         #[allow(bad_style)]
1713         unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME {
1714             (*(*x).req_info).subject
1715         }
1716 
1717         #[allow(bad_style)]
1718         unsafe fn X509_ALGOR_get0(
1719             paobj: *mut *const ffi::ASN1_OBJECT,
1720             pptype: *mut c_int,
1721             pval: *mut *mut ::libc::c_void,
1722             alg: *const ffi::X509_ALGOR,
1723         ) {
1724             if !paobj.is_null() {
1725                 *paobj = (*alg).algorithm;
1726             }
1727             assert!(pptype.is_null());
1728             assert!(pval.is_null());
1729         }
1730     }
1731 }
1732 
1733 cfg_if! {
1734     if #[cfg(any(ossl110, boringssl, libressl270))] {
1735         use ffi::X509_OBJECT_get0_X509;
1736     } else {
1737         #[allow(bad_style)]
1738         unsafe fn X509_OBJECT_get0_X509(x: *mut ffi::X509_OBJECT) -> *mut ffi::X509 {
1739             if (*x).type_ == ffi::X509_LU_X509 {
1740                 (*x).data.x509
1741             } else {
1742                 ptr::null_mut()
1743             }
1744         }
1745     }
1746 }
1747 
1748 cfg_if! {
1749     if #[cfg(any(ossl110, libressl350))] {
1750         use ffi::X509_OBJECT_free;
1751     } else if #[cfg(boringssl)] {
1752         use ffi::X509_OBJECT_free_contents as X509_OBJECT_free;
1753     } else {
1754         #[allow(bad_style)]
1755         unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) {
1756             ffi::X509_OBJECT_free_contents(x);
1757             ffi::CRYPTO_free(x as *mut libc::c_void);
1758         }
1759     }
1760 }
1761