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 ffi;
11 use foreign_types::{ForeignType, ForeignTypeRef};
12 use libc::{c_int, c_long};
13 use std::error::Error;
14 use std::ffi::{CStr, CString};
15 use std::fmt;
16 use std::marker::PhantomData;
17 use std::mem;
18 use std::path::Path;
19 use std::ptr;
20 use std::slice;
21 use std::str;
22 
23 use asn1::{Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef};
24 use bio::MemBioSlice;
25 use conf::ConfRef;
26 use error::ErrorStack;
27 use ex_data::Index;
28 use hash::{DigestBytes, MessageDigest};
29 use nid::Nid;
30 use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
31 use ssl::SslRef;
32 use stack::{Stack, StackRef, Stackable};
33 use string::OpensslString;
34 use {cvt, cvt_n, cvt_p};
35 
36 #[cfg(any(ossl102, libressl261))]
37 pub mod verify;
38 
39 pub mod extension;
40 pub mod store;
41 
42 #[cfg(test)]
43 mod tests;
44 
45 foreign_type_and_impl_send_sync! {
46     type CType = ffi::X509_STORE_CTX;
47     fn drop = ffi::X509_STORE_CTX_free;
48 
49     /// An `X509` certificate store context.
50     pub struct X509StoreContext;
51 
52     /// Reference to `X509StoreContext`.
53     pub struct X509StoreContextRef;
54 }
55 
56 impl X509StoreContext {
57     /// Returns the index which can be used to obtain a reference to the `Ssl` associated with a
58     /// context.
59     pub fn ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack> {
60         unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) }
61     }
62 
63     /// Creates a new `X509StoreContext` instance.
64     ///
65     /// This corresponds to [`X509_STORE_CTX_new`].
66     ///
67     /// [`X509_STORE_CTX_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_new.html
68     pub fn new() -> Result<X509StoreContext, ErrorStack> {
69         unsafe {
70             ffi::init();
71             cvt_p(ffi::X509_STORE_CTX_new()).map(|p| X509StoreContext(p))
72         }
73     }
74 }
75 
76 impl X509StoreContextRef {
77     /// Returns application data pertaining to an `X509` store context.
78     ///
79     /// This corresponds to [`X509_STORE_CTX_get_ex_data`].
80     ///
81     /// [`X509_STORE_CTX_get_ex_data`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_get_ex_data.html
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     ///
95     /// This corresponds to [`X509_STORE_CTX_get_error`].
96     ///
97     /// [`X509_STORE_CTX_get_error`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get_error.html
98     pub fn error(&self) -> X509VerifyResult {
99         unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) }
100     }
101 
102     /// Initializes this context with the given certificate, certificates chain and certificate
103     /// store. After initializing the context, the `with_context` closure is called with the prepared
104     /// context. As long as the closure is running, the context stays initialized and can be used
105     /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished.
106     ///
107     /// * `trust` - The certificate store with the trusted certificates.
108     /// * `cert` - The certificate that should be verified.
109     /// * `cert_chain` - The certificates chain.
110     /// * `with_context` - The closure that is called with the initialized context.
111     ///
112     /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to
113     /// [`X509_STORE_CTX_cleanup`] after calling `with_context`.
114     ///
115     /// [`X509_STORE_CTX_init`]:  https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_init.html
116     /// [`X509_STORE_CTX_cleanup`]:  https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html
117     pub fn init<F, T>(
118         &mut self,
119         trust: &store::X509StoreRef,
120         cert: &X509Ref,
121         cert_chain: &StackRef<X509>,
122         with_context: F,
123     ) -> Result<T, ErrorStack>
124     where
125         F: FnOnce(&mut X509StoreContextRef) -> Result<T, ErrorStack>,
126     {
127         struct Cleanup<'a>(&'a mut X509StoreContextRef);
128 
129         impl<'a> Drop for Cleanup<'a> {
130             fn drop(&mut self) {
131                 unsafe {
132                     ffi::X509_STORE_CTX_cleanup(self.0.as_ptr());
133                 }
134             }
135         }
136 
137         unsafe {
138             cvt(ffi::X509_STORE_CTX_init(
139                 self.as_ptr(),
140                 trust.as_ptr(),
141                 cert.as_ptr(),
142                 cert_chain.as_ptr(),
143             ))?;
144 
145             let cleanup = Cleanup(self);
146             with_context(cleanup.0)
147         }
148     }
149 
150     /// Verifies the stored certificate.
151     ///
152     /// Returns `true` if verification succeeds. The `error` method will return the specific
153     /// validation error if the certificate was not valid.
154     ///
155     /// This will only work inside of a call to `init`.
156     ///
157     /// This corresponds to [`X509_verify_cert`].
158     ///
159     /// [`X509_verify_cert`]:  https://www.openssl.org/docs/man1.0.2/crypto/X509_verify_cert.html
160     pub fn verify_cert(&mut self) -> Result<bool, ErrorStack> {
161         unsafe { cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0) }
162     }
163 
164     /// Set the error code of the context.
165     ///
166     /// This corresponds to [`X509_STORE_CTX_set_error`].
167     ///
168     /// [`X509_STORE_CTX_set_error`]:  https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_set_error.html
169     pub fn set_error(&mut self, result: X509VerifyResult) {
170         unsafe {
171             ffi::X509_STORE_CTX_set_error(self.as_ptr(), result.as_raw());
172         }
173     }
174 
175     /// Returns a reference to the certificate which caused the error or None if
176     /// no certificate is relevant to the error.
177     ///
178     /// This corresponds to [`X509_STORE_CTX_get_current_cert`].
179     ///
180     /// [`X509_STORE_CTX_get_current_cert`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get_current_cert.html
181     pub fn current_cert(&self) -> Option<&X509Ref> {
182         unsafe {
183             let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr());
184             if ptr.is_null() {
185                 None
186             } else {
187                 Some(X509Ref::from_ptr(ptr))
188             }
189         }
190     }
191 
192     /// Returns a non-negative integer representing the depth in the certificate
193     /// chain where the error occurred. If it is zero it occurred in the end
194     /// entity certificate, one if it is the certificate which signed the end
195     /// entity certificate and so on.
196     ///
197     /// This corresponds to [`X509_STORE_CTX_get_error_depth`].
198     ///
199     /// [`X509_STORE_CTX_get_error_depth`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get_error_depth.html
200     pub fn error_depth(&self) -> u32 {
201         unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 }
202     }
203 
204     /// Returns a reference to a complete valid `X509` certificate chain.
205     ///
206     /// This corresponds to [`X509_STORE_CTX_get0_chain`].
207     ///
208     /// [`X509_STORE_CTX_get0_chain`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get0_chain.html
209     pub fn chain(&self) -> Option<&StackRef<X509>> {
210         unsafe {
211             let chain = X509_STORE_CTX_get0_chain(self.as_ptr());
212 
213             if chain.is_null() {
214                 None
215             } else {
216                 Some(StackRef::from_ptr(chain))
217             }
218         }
219     }
220 }
221 
222 /// A builder used to construct an `X509`.
223 pub struct X509Builder(X509);
224 
225 impl X509Builder {
226     /// Creates a new builder.
227     pub fn new() -> Result<X509Builder, ErrorStack> {
228         unsafe {
229             ffi::init();
230             cvt_p(ffi::X509_new()).map(|p| X509Builder(X509(p)))
231         }
232     }
233 
234     /// Sets the notAfter constraint on the certificate.
235     pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
236         unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
237     }
238 
239     /// Sets the notBefore constraint on the certificate.
240     pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
241         unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
242     }
243 
244     /// Sets the version of the certificate.
245     ///
246     /// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of
247     /// the X.509 standard should pass `2` to this method.
248     pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
249         unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version.into())).map(|_| ()) }
250     }
251 
252     /// Sets the serial number of the certificate.
253     pub fn set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack> {
254         unsafe {
255             cvt(ffi::X509_set_serialNumber(
256                 self.0.as_ptr(),
257                 serial_number.as_ptr(),
258             ))
259             .map(|_| ())
260         }
261     }
262 
263     /// Sets the issuer name of the certificate.
264     pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> {
265         unsafe {
266             cvt(ffi::X509_set_issuer_name(
267                 self.0.as_ptr(),
268                 issuer_name.as_ptr(),
269             ))
270             .map(|_| ())
271         }
272     }
273 
274     /// Sets the subject name of the certificate.
275     ///
276     /// When building certificates, the `C`, `ST`, and `O` options are common when using the openssl command line tools.
277     /// The `CN` field is used for the common name, such as a DNS name.
278     ///
279     /// ```
280     /// use openssl::x509::{X509, X509NameBuilder};
281     ///
282     /// let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap();
283     /// x509_name.append_entry_by_text("C", "US").unwrap();
284     /// x509_name.append_entry_by_text("ST", "CA").unwrap();
285     /// x509_name.append_entry_by_text("O", "Some organization").unwrap();
286     /// x509_name.append_entry_by_text("CN", "www.example.com").unwrap();
287     /// let x509_name = x509_name.build();
288     ///
289     /// let mut x509 = openssl::x509::X509::builder().unwrap();
290     /// x509.set_subject_name(&x509_name).unwrap();
291     /// ```
292     pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
293         unsafe {
294             cvt(ffi::X509_set_subject_name(
295                 self.0.as_ptr(),
296                 subject_name.as_ptr(),
297             ))
298             .map(|_| ())
299         }
300     }
301 
302     /// Sets the public key associated with the certificate.
303     pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
304     where
305         T: HasPublic,
306     {
307         unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
308     }
309 
310     /// Returns a context object which is needed to create certain X509 extension values.
311     ///
312     /// Set `issuer` to `None` if the certificate will be self-signed.
313     pub fn x509v3_context<'a>(
314         &'a self,
315         issuer: Option<&'a X509Ref>,
316         conf: Option<&'a ConfRef>,
317     ) -> X509v3Context<'a> {
318         unsafe {
319             let mut ctx = mem::zeroed();
320 
321             let issuer = match issuer {
322                 Some(issuer) => issuer.as_ptr(),
323                 None => self.0.as_ptr(),
324             };
325             let subject = self.0.as_ptr();
326             ffi::X509V3_set_ctx(
327                 &mut ctx,
328                 issuer,
329                 subject,
330                 ptr::null_mut(),
331                 ptr::null_mut(),
332                 0,
333             );
334 
335             // nodb case taken care of since we zeroed ctx above
336             if let Some(conf) = conf {
337                 ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr());
338             }
339 
340             X509v3Context(ctx, PhantomData)
341         }
342     }
343 
344     /// Adds an X509 extension value to the certificate.
345     pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> {
346         unsafe {
347             cvt(ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1))?;
348             mem::forget(extension);
349             Ok(())
350         }
351     }
352 
353     /// Signs the certificate with a private key.
354     pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
355     where
356         T: HasPrivate,
357     {
358         unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) }
359     }
360 
361     /// Consumes the builder, returning the certificate.
362     pub fn build(self) -> X509 {
363         self.0
364     }
365 }
366 
367 foreign_type_and_impl_send_sync! {
368     type CType = ffi::X509;
369     fn drop = ffi::X509_free;
370 
371     /// An `X509` public key certificate.
372     pub struct X509;
373     /// Reference to `X509`.
374     pub struct X509Ref;
375 }
376 
377 impl X509Ref {
378     /// Returns this certificate's subject name.
379     ///
380     /// This corresponds to [`X509_get_subject_name`].
381     ///
382     /// [`X509_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_subject_name.html
383     pub fn subject_name(&self) -> &X509NameRef {
384         unsafe {
385             let name = ffi::X509_get_subject_name(self.as_ptr());
386             assert!(!name.is_null());
387             X509NameRef::from_ptr(name)
388         }
389     }
390 
391     /// Returns this certificate's issuer name.
392     ///
393     /// This corresponds to [`X509_get_issuer_name`].
394     ///
395     /// [`X509_get_issuer_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_subject_name.html
396     pub fn issuer_name(&self) -> &X509NameRef {
397         unsafe {
398             let name = ffi::X509_get_issuer_name(self.as_ptr());
399             assert!(!name.is_null());
400             X509NameRef::from_ptr(name)
401         }
402     }
403 
404     /// Returns this certificate's subject alternative name entries, if they exist.
405     ///
406     /// This corresponds to [`X509_get_ext_d2i`] called with `NID_subject_alt_name`.
407     ///
408     /// [`X509_get_ext_d2i`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_ext_d2i.html
409     pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> {
410         unsafe {
411             let stack = ffi::X509_get_ext_d2i(
412                 self.as_ptr(),
413                 ffi::NID_subject_alt_name,
414                 ptr::null_mut(),
415                 ptr::null_mut(),
416             );
417             if stack.is_null() {
418                 None
419             } else {
420                 Some(Stack::from_ptr(stack as *mut _))
421             }
422         }
423     }
424 
425     /// Returns this certificate's issuer alternative name entries, if they exist.
426     ///
427     /// This corresponds to [`X509_get_ext_d2i`] called with `NID_issuer_alt_name`.
428     ///
429     /// [`X509_get_ext_d2i`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_ext_d2i.html
430     pub fn issuer_alt_names(&self) -> Option<Stack<GeneralName>> {
431         unsafe {
432             let stack = ffi::X509_get_ext_d2i(
433                 self.as_ptr(),
434                 ffi::NID_issuer_alt_name,
435                 ptr::null_mut(),
436                 ptr::null_mut(),
437             );
438             if stack.is_null() {
439                 None
440             } else {
441                 Some(Stack::from_ptr(stack as *mut _))
442             }
443         }
444     }
445 
446     pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
447         unsafe {
448             let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?;
449             Ok(PKey::from_ptr(pkey))
450         }
451     }
452 
453     /// Returns a digest of the DER representation of the certificate.
454     ///
455     /// This corresponds to [`X509_digest`].
456     ///
457     /// [`X509_digest`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_digest.html
458     pub fn digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack> {
459         unsafe {
460             let mut digest = DigestBytes {
461                 buf: [0; ffi::EVP_MAX_MD_SIZE as usize],
462                 len: ffi::EVP_MAX_MD_SIZE as usize,
463             };
464             let mut len = ffi::EVP_MAX_MD_SIZE;
465             cvt(ffi::X509_digest(
466                 self.as_ptr(),
467                 hash_type.as_ptr(),
468                 digest.buf.as_mut_ptr() as *mut _,
469                 &mut len,
470             ))?;
471             digest.len = len as usize;
472 
473             Ok(digest)
474         }
475     }
476 
477     #[deprecated(since = "0.10.9", note = "renamed to digest")]
478     pub fn fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack> {
479         self.digest(hash_type).map(|b| b.to_vec())
480     }
481 
482     /// Returns the certificate's Not After validity period.
483     pub fn not_after(&self) -> &Asn1TimeRef {
484         unsafe {
485             let date = X509_getm_notAfter(self.as_ptr());
486             assert!(!date.is_null());
487             Asn1TimeRef::from_ptr(date)
488         }
489     }
490 
491     /// Returns the certificate's Not Before validity period.
492     pub fn not_before(&self) -> &Asn1TimeRef {
493         unsafe {
494             let date = X509_getm_notBefore(self.as_ptr());
495             assert!(!date.is_null());
496             Asn1TimeRef::from_ptr(date)
497         }
498     }
499 
500     /// Returns the certificate's signature
501     pub fn signature(&self) -> &Asn1BitStringRef {
502         unsafe {
503             let mut signature = ptr::null();
504             X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr());
505             assert!(!signature.is_null());
506             Asn1BitStringRef::from_ptr(signature as *mut _)
507         }
508     }
509 
510     /// Returns the certificate's signature algorithm.
511     pub fn signature_algorithm(&self) -> &X509AlgorithmRef {
512         unsafe {
513             let mut algor = ptr::null();
514             X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr());
515             assert!(!algor.is_null());
516             X509AlgorithmRef::from_ptr(algor as *mut _)
517         }
518     }
519 
520     /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information
521     /// Access field.
522     pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> {
523         unsafe { cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p)) }
524     }
525 
526     /// Checks that this certificate issued `subject`.
527     pub fn issued(&self, subject: &X509Ref) -> X509VerifyResult {
528         unsafe {
529             let r = ffi::X509_check_issued(self.as_ptr(), subject.as_ptr());
530             X509VerifyResult::from_raw(r)
531         }
532     }
533 
534     /// Check if the certificate is signed using the given public key.
535     ///
536     /// Only the signature is checked: no other checks (such as certificate chain validity)
537     /// are performed.
538     ///
539     /// Returns `true` if verification succeeds.
540     ///
541     /// This corresponds to [`X509_verify"].
542     ///
543     /// [`X509_verify`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_verify.html
544     pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
545     where
546         T: HasPublic,
547     {
548         unsafe { cvt_n(ffi::X509_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
549     }
550 
551     /// Returns this certificate's serial number.
552     ///
553     /// This corresponds to [`X509_get_serialNumber`].
554     ///
555     /// [`X509_get_serialNumber`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_serialNumber.html
556     pub fn serial_number(&self) -> &Asn1IntegerRef {
557         unsafe {
558             let r = ffi::X509_get_serialNumber(self.as_ptr());
559             assert!(!r.is_null());
560             Asn1IntegerRef::from_ptr(r)
561         }
562     }
563 
564     to_pem! {
565         /// Serializes the certificate into a PEM-encoded X509 structure.
566         ///
567         /// The output will have a header of `-----BEGIN CERTIFICATE-----`.
568         ///
569         /// This corresponds to [`PEM_write_bio_X509`].
570         ///
571         /// [`PEM_write_bio_X509`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509.html
572         to_pem,
573         ffi::PEM_write_bio_X509
574     }
575 
576     to_der! {
577         /// Serializes the certificate into a DER-encoded X509 structure.
578         ///
579         /// This corresponds to [`i2d_X509`].
580         ///
581         /// [`i2d_X509`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_X509.html
582         to_der,
583         ffi::i2d_X509
584     }
585 }
586 
587 impl ToOwned for X509Ref {
588     type Owned = X509;
589 
590     fn to_owned(&self) -> X509 {
591         unsafe {
592             X509_up_ref(self.as_ptr());
593             X509::from_ptr(self.as_ptr())
594         }
595     }
596 }
597 
598 impl X509 {
599     /// Returns a new builder.
600     pub fn builder() -> Result<X509Builder, ErrorStack> {
601         X509Builder::new()
602     }
603 
604     from_pem! {
605         /// Deserializes a PEM-encoded X509 structure.
606         ///
607         /// The input should have a header of `-----BEGIN CERTIFICATE-----`.
608         ///
609         /// This corresponds to [`PEM_read_bio_X509`].
610         ///
611         /// [`PEM_read_bio_X509`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509.html
612         from_pem,
613         X509,
614         ffi::PEM_read_bio_X509
615     }
616 
617     from_der! {
618         /// Deserializes a DER-encoded X509 structure.
619         ///
620         /// This corresponds to [`d2i_X509`].
621         ///
622         /// [`d2i_X509`]: https://www.openssl.org/docs/manmaster/man3/d2i_X509.html
623         from_der,
624         X509,
625         ffi::d2i_X509
626     }
627 
628     /// Deserializes a list of PEM-formatted certificates.
629     pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> {
630         unsafe {
631             ffi::init();
632             let bio = MemBioSlice::new(pem)?;
633 
634             let mut certs = vec![];
635             loop {
636                 let r =
637                     ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut());
638                 if r.is_null() {
639                     let err = ffi::ERR_peek_last_error();
640                     if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM
641                         && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE
642                     {
643                         ffi::ERR_clear_error();
644                         break;
645                     }
646 
647                     return Err(ErrorStack::get());
648                 } else {
649                     certs.push(X509(r));
650                 }
651             }
652 
653             Ok(certs)
654         }
655     }
656 }
657 
658 impl Clone for X509 {
659     fn clone(&self) -> X509 {
660         X509Ref::to_owned(self)
661     }
662 }
663 
664 impl AsRef<X509Ref> for X509Ref {
665     fn as_ref(&self) -> &X509Ref {
666         self
667     }
668 }
669 
670 impl Stackable for X509 {
671     type StackType = ffi::stack_st_X509;
672 }
673 
674 /// A context object required to construct certain `X509` extension values.
675 pub struct X509v3Context<'a>(ffi::X509V3_CTX, PhantomData<(&'a X509Ref, &'a ConfRef)>);
676 
677 impl<'a> X509v3Context<'a> {
678     pub fn as_ptr(&self) -> *mut ffi::X509V3_CTX {
679         &self.0 as *const _ as *mut _
680     }
681 }
682 
683 foreign_type_and_impl_send_sync! {
684     type CType = ffi::X509_EXTENSION;
685     fn drop = ffi::X509_EXTENSION_free;
686 
687     /// Permit additional fields to be added to an `X509` v3 certificate.
688     pub struct X509Extension;
689     /// Reference to `X509Extension`.
690     pub struct X509ExtensionRef;
691 }
692 
693 impl Stackable for X509Extension {
694     type StackType = ffi::stack_st_X509_EXTENSION;
695 }
696 
697 impl X509Extension {
698     /// Constructs an X509 extension value. See `man x509v3_config` for information on supported
699     /// names and their value formats.
700     ///
701     /// Some extension types, such as `subjectAlternativeName`, require an `X509v3Context` to be
702     /// provided.
703     ///
704     /// See the extension module for builder types which will construct certain common extensions.
705     pub fn new(
706         conf: Option<&ConfRef>,
707         context: Option<&X509v3Context>,
708         name: &str,
709         value: &str,
710     ) -> Result<X509Extension, ErrorStack> {
711         let name = CString::new(name).unwrap();
712         let value = CString::new(value).unwrap();
713         unsafe {
714             ffi::init();
715             let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr);
716             let context = context.map_or(ptr::null_mut(), X509v3Context::as_ptr);
717             let name = name.as_ptr() as *mut _;
718             let value = value.as_ptr() as *mut _;
719 
720             cvt_p(ffi::X509V3_EXT_nconf(conf, context, name, value)).map(X509Extension)
721         }
722     }
723 
724     /// Constructs an X509 extension value. See `man x509v3_config` for information on supported
725     /// extensions and their value formats.
726     ///
727     /// Some extension types, such as `nid::SUBJECT_ALTERNATIVE_NAME`, require an `X509v3Context` to
728     /// be provided.
729     ///
730     /// See the extension module for builder types which will construct certain common extensions.
731     pub fn new_nid(
732         conf: Option<&ConfRef>,
733         context: Option<&X509v3Context>,
734         name: Nid,
735         value: &str,
736     ) -> Result<X509Extension, ErrorStack> {
737         let value = CString::new(value).unwrap();
738         unsafe {
739             ffi::init();
740             let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr);
741             let context = context.map_or(ptr::null_mut(), X509v3Context::as_ptr);
742             let name = name.as_raw();
743             let value = value.as_ptr() as *mut _;
744 
745             cvt_p(ffi::X509V3_EXT_nconf_nid(conf, context, name, value)).map(X509Extension)
746         }
747     }
748 }
749 
750 /// A builder used to construct an `X509Name`.
751 pub struct X509NameBuilder(X509Name);
752 
753 impl X509NameBuilder {
754     /// Creates a new builder.
755     pub fn new() -> Result<X509NameBuilder, ErrorStack> {
756         unsafe {
757             ffi::init();
758             cvt_p(ffi::X509_NAME_new()).map(|p| X509NameBuilder(X509Name(p)))
759         }
760     }
761 
762     /// Add a field entry by str.
763     ///
764     /// This corresponds to [`X509_NAME_add_entry_by_txt`].
765     ///
766     /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html
767     pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
768         unsafe {
769             let field = CString::new(field).unwrap();
770             assert!(value.len() <= c_int::max_value() as usize);
771             cvt(ffi::X509_NAME_add_entry_by_txt(
772                 self.0.as_ptr(),
773                 field.as_ptr() as *mut _,
774                 ffi::MBSTRING_UTF8,
775                 value.as_ptr(),
776                 value.len() as c_int,
777                 -1,
778                 0,
779             ))
780             .map(|_| ())
781         }
782     }
783 
784     /// Add a field entry by NID.
785     ///
786     /// This corresponds to [`X509_NAME_add_entry_by_NID`].
787     ///
788     /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html
789     pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
790         unsafe {
791             assert!(value.len() <= c_int::max_value() as usize);
792             cvt(ffi::X509_NAME_add_entry_by_NID(
793                 self.0.as_ptr(),
794                 field.as_raw(),
795                 ffi::MBSTRING_UTF8,
796                 value.as_ptr() as *mut _,
797                 value.len() as c_int,
798                 -1,
799                 0,
800             ))
801             .map(|_| ())
802         }
803     }
804 
805     /// Return an `X509Name`.
806     pub fn build(self) -> X509Name {
807         self.0
808     }
809 }
810 
811 foreign_type_and_impl_send_sync! {
812     type CType = ffi::X509_NAME;
813     fn drop = ffi::X509_NAME_free;
814 
815     /// The names of an `X509` certificate.
816     pub struct X509Name;
817     /// Reference to `X509Name`.
818     pub struct X509NameRef;
819 }
820 
821 impl X509Name {
822     /// Returns a new builder.
823     pub fn builder() -> Result<X509NameBuilder, ErrorStack> {
824         X509NameBuilder::new()
825     }
826 
827     /// Loads subject names from a file containing PEM-formatted certificates.
828     ///
829     /// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
830     pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> {
831         let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
832         unsafe { cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p)) }
833     }
834 }
835 
836 impl Stackable for X509Name {
837     type StackType = ffi::stack_st_X509_NAME;
838 }
839 
840 impl X509NameRef {
841     /// Returns the name entries by the nid.
842     pub fn entries_by_nid<'a>(&'a self, nid: Nid) -> X509NameEntries<'a> {
843         X509NameEntries {
844             name: self,
845             nid: Some(nid),
846             loc: -1,
847         }
848     }
849 
850     /// Returns an iterator over all `X509NameEntry` values
851     pub fn entries<'a>(&'a self) -> X509NameEntries<'a> {
852         X509NameEntries {
853             name: self,
854             nid: None,
855             loc: -1,
856         }
857     }
858 }
859 
860 /// A type to destructure and examine an `X509Name`.
861 pub struct X509NameEntries<'a> {
862     name: &'a X509NameRef,
863     nid: Option<Nid>,
864     loc: c_int,
865 }
866 
867 impl<'a> Iterator for X509NameEntries<'a> {
868     type Item = &'a X509NameEntryRef;
869 
870     fn next(&mut self) -> Option<&'a X509NameEntryRef> {
871         unsafe {
872             match self.nid {
873                 Some(nid) => {
874                     // There is a `Nid` specified to search for
875                     self.loc =
876                         ffi::X509_NAME_get_index_by_NID(self.name.as_ptr(), nid.as_raw(), self.loc);
877                     if self.loc == -1 {
878                         return None;
879                     }
880                 }
881                 None => {
882                     // Iterate over all `Nid`s
883                     self.loc += 1;
884                     if self.loc >= ffi::X509_NAME_entry_count(self.name.as_ptr()) {
885                         return None;
886                     }
887                 }
888             }
889 
890             let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc);
891             assert!(!entry.is_null());
892 
893             Some(X509NameEntryRef::from_ptr(entry))
894         }
895     }
896 }
897 
898 foreign_type_and_impl_send_sync! {
899     type CType = ffi::X509_NAME_ENTRY;
900     fn drop = ffi::X509_NAME_ENTRY_free;
901 
902     /// A name entry associated with a `X509Name`.
903     pub struct X509NameEntry;
904     /// Reference to `X509NameEntry`.
905     pub struct X509NameEntryRef;
906 }
907 
908 impl X509NameEntryRef {
909     /// Returns the field value of an `X509NameEntry`.
910     ///
911     /// This corresponds to [`X509_NAME_ENTRY_get_data`].
912     ///
913     /// [`X509_NAME_ENTRY_get_data`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_data.html
914     pub fn data(&self) -> &Asn1StringRef {
915         unsafe {
916             let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr());
917             Asn1StringRef::from_ptr(data)
918         }
919     }
920 
921     /// Returns the `Asn1Object` value of an `X509NameEntry`.
922     /// This is useful for finding out about the actual `Nid` when iterating over all `X509NameEntries`.
923     ///
924     /// This corresponds to [`X509_NAME_ENTRY_get_object`].
925     ///
926     /// [`X509_NAME_ENTRY_get_object`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_object.html
927     pub fn object(&self) -> &Asn1ObjectRef {
928         unsafe {
929             let object = ffi::X509_NAME_ENTRY_get_object(self.as_ptr());
930             Asn1ObjectRef::from_ptr(object)
931         }
932     }
933 }
934 
935 /// A builder used to construct an `X509Req`.
936 pub struct X509ReqBuilder(X509Req);
937 
938 impl X509ReqBuilder {
939     /// Returns a builder for a certificate request.
940     ///
941     /// This corresponds to [`X509_REQ_new`].
942     ///
943     ///[`X509_REQ_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_new.html
944     pub fn new() -> Result<X509ReqBuilder, ErrorStack> {
945         unsafe {
946             ffi::init();
947             cvt_p(ffi::X509_REQ_new()).map(|p| X509ReqBuilder(X509Req(p)))
948         }
949     }
950 
951     /// Set the numerical value of the version field.
952     ///
953     /// This corresponds to [`X509_REQ_set_version`].
954     ///
955     ///[`X509_REQ_set_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_version.html
956     pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
957         unsafe { cvt(ffi::X509_REQ_set_version(self.0.as_ptr(), version.into())).map(|_| ()) }
958     }
959 
960     /// Set the issuer name.
961     ///
962     /// This corresponds to [`X509_REQ_set_subject_name`].
963     ///
964     /// [`X509_REQ_set_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_subject_name.html
965     pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
966         unsafe {
967             cvt(ffi::X509_REQ_set_subject_name(
968                 self.0.as_ptr(),
969                 subject_name.as_ptr(),
970             ))
971             .map(|_| ())
972         }
973     }
974 
975     /// Set the public key.
976     ///
977     /// This corresponds to [`X509_REQ_set_pubkey`].
978     ///
979     /// [`X509_REQ_set_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_pubkey.html
980     pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
981     where
982         T: HasPublic,
983     {
984         unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
985     }
986 
987     /// Return an `X509v3Context`. This context object can be used to construct
988     /// certain `X509` extensions.
989     pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> {
990         unsafe {
991             let mut ctx = mem::zeroed();
992 
993             ffi::X509V3_set_ctx(
994                 &mut ctx,
995                 ptr::null_mut(),
996                 ptr::null_mut(),
997                 self.0.as_ptr(),
998                 ptr::null_mut(),
999                 0,
1000             );
1001 
1002             // nodb case taken care of since we zeroed ctx above
1003             if let Some(conf) = conf {
1004                 ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr());
1005             }
1006 
1007             X509v3Context(ctx, PhantomData)
1008         }
1009     }
1010 
1011     /// Permits any number of extension fields to be added to the certificate.
1012     pub fn add_extensions(
1013         &mut self,
1014         extensions: &StackRef<X509Extension>,
1015     ) -> Result<(), ErrorStack> {
1016         unsafe {
1017             cvt(ffi::X509_REQ_add_extensions(
1018                 self.0.as_ptr(),
1019                 extensions.as_ptr(),
1020             ))
1021             .map(|_| ())
1022         }
1023     }
1024 
1025     /// Sign the request using a private key.
1026     ///
1027     /// This corresponds to [`X509_REQ_sign`].
1028     ///
1029     /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html
1030     pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
1031     where
1032         T: HasPrivate,
1033     {
1034         unsafe {
1035             cvt(ffi::X509_REQ_sign(
1036                 self.0.as_ptr(),
1037                 key.as_ptr(),
1038                 hash.as_ptr(),
1039             ))
1040             .map(|_| ())
1041         }
1042     }
1043 
1044     /// Returns the `X509Req`.
1045     pub fn build(self) -> X509Req {
1046         self.0
1047     }
1048 }
1049 
1050 foreign_type_and_impl_send_sync! {
1051     type CType = ffi::X509_REQ;
1052     fn drop = ffi::X509_REQ_free;
1053 
1054     /// An `X509` certificate request.
1055     pub struct X509Req;
1056     /// Reference to `X509Req`.
1057     pub struct X509ReqRef;
1058 }
1059 
1060 impl X509Req {
1061     /// A builder for `X509Req`.
1062     pub fn builder() -> Result<X509ReqBuilder, ErrorStack> {
1063         X509ReqBuilder::new()
1064     }
1065 
1066     from_pem! {
1067         /// Deserializes a PEM-encoded PKCS#10 certificate request structure.
1068         ///
1069         /// The input should have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
1070         ///
1071         /// This corresponds to [`PEM_read_bio_X509_REQ`].
1072         ///
1073         /// [`PEM_read_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509_REQ.html
1074         from_pem,
1075         X509Req,
1076         ffi::PEM_read_bio_X509_REQ
1077     }
1078 
1079     from_der! {
1080         /// Deserializes a DER-encoded PKCS#10 certificate request structure.
1081         ///
1082         /// This corresponds to [`d2i_X509_REQ`].
1083         ///
1084         /// [`d2i_X509_REQ`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_X509_REQ.html
1085         from_der,
1086         X509Req,
1087         ffi::d2i_X509_REQ
1088     }
1089 }
1090 
1091 impl X509ReqRef {
1092     to_pem! {
1093         /// Serializes the certificate request to a PEM-encoded PKCS#10 structure.
1094         ///
1095         /// The output will have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
1096         ///
1097         /// This corresponds to [`PEM_write_bio_X509_REQ`].
1098         ///
1099         /// [`PEM_write_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509_REQ.html
1100         to_pem,
1101         ffi::PEM_write_bio_X509_REQ
1102     }
1103 
1104     to_der! {
1105         /// Serializes the certificate request to a DER-encoded PKCS#10 structure.
1106         ///
1107         /// This corresponds to [`i2d_X509_REQ`].
1108         ///
1109         /// [`i2d_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_X509_REQ.html
1110         to_der,
1111         ffi::i2d_X509_REQ
1112     }
1113 
1114     /// Returns the numerical value of the version field of the certificate request.
1115     ///
1116     /// This corresponds to [`X509_REQ_get_version`]
1117     ///
1118     /// [`X509_REQ_get_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_version.html
1119     pub fn version(&self) -> i32 {
1120         unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
1121     }
1122 
1123     /// Returns the subject name of the certificate request.
1124     ///
1125     /// This corresponds to [`X509_REQ_get_subject_name`]
1126     ///
1127     /// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_subject_name.html
1128     pub fn subject_name(&self) -> &X509NameRef {
1129         unsafe {
1130             let name = X509_REQ_get_subject_name(self.as_ptr());
1131             assert!(!name.is_null());
1132             X509NameRef::from_ptr(name)
1133         }
1134     }
1135 
1136     /// Returns the public key of the certificate request.
1137     ///
1138     /// This corresponds to [`X509_REQ_get_pubkey"]
1139     ///
1140     /// [`X509_REQ_get_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_pubkey.html
1141     pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
1142         unsafe {
1143             let key = cvt_p(ffi::X509_REQ_get_pubkey(self.as_ptr()))?;
1144             Ok(PKey::from_ptr(key))
1145         }
1146     }
1147 
1148     /// Check if the certificate request is signed using the given public key.
1149     ///
1150     /// Returns `true` if verification succeeds.
1151     ///
1152     /// This corresponds to [`X509_REQ_verify"].
1153     ///
1154     /// [`X509_REQ_verify`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_verify.html
1155     pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
1156     where
1157         T: HasPublic,
1158     {
1159         unsafe { cvt_n(ffi::X509_REQ_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
1160     }
1161 
1162     /// Returns the extensions of the certificate request.
1163     ///
1164     /// This corresponds to [`X509_REQ_get_extensions"]
1165     pub fn extensions(&self) -> Result<Stack<X509Extension>, ErrorStack> {
1166         unsafe {
1167             let extensions = cvt_p(ffi::X509_REQ_get_extensions(self.as_ptr()))?;
1168             Ok(Stack::from_ptr(extensions))
1169         }
1170     }
1171 }
1172 
1173 /// The result of peer certificate verification.
1174 #[derive(Copy, Clone, PartialEq, Eq)]
1175 pub struct X509VerifyResult(c_int);
1176 
1177 impl fmt::Debug for X509VerifyResult {
1178     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1179         fmt.debug_struct("X509VerifyResult")
1180             .field("code", &self.0)
1181             .field("error", &self.error_string())
1182             .finish()
1183     }
1184 }
1185 
1186 impl fmt::Display for X509VerifyResult {
1187     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1188         fmt.write_str(self.error_string())
1189     }
1190 }
1191 
1192 impl Error for X509VerifyResult {
1193     fn description(&self) -> &str {
1194         "an X509 validation error"
1195     }
1196 }
1197 
1198 impl X509VerifyResult {
1199     /// Creates an `X509VerifyResult` from a raw error number.
1200     ///
1201     /// # Safety
1202     ///
1203     /// Some methods on `X509VerifyResult` are not thread safe if the error
1204     /// number is invalid.
1205     pub unsafe fn from_raw(err: c_int) -> X509VerifyResult {
1206         X509VerifyResult(err)
1207     }
1208 
1209     /// Return the integer representation of an `X509VerifyResult`.
1210     pub fn as_raw(&self) -> c_int {
1211         self.0
1212     }
1213 
1214     /// Return a human readable error string from the verification error.
1215     ///
1216     /// This corresponds to [`X509_verify_cert_error_string`].
1217     ///
1218     /// [`X509_verify_cert_error_string`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_verify_cert_error_string.html
1219     pub fn error_string(&self) -> &'static str {
1220         ffi::init();
1221 
1222         unsafe {
1223             let s = ffi::X509_verify_cert_error_string(self.0 as c_long);
1224             str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
1225         }
1226     }
1227 
1228     /// Successful peer certifiate verification.
1229     pub const OK: X509VerifyResult = X509VerifyResult(ffi::X509_V_OK);
1230     /// Application verification failure.
1231     pub const APPLICATION_VERIFICATION: X509VerifyResult =
1232         X509VerifyResult(ffi::X509_V_ERR_APPLICATION_VERIFICATION);
1233 }
1234 
1235 foreign_type_and_impl_send_sync! {
1236     type CType = ffi::GENERAL_NAME;
1237     fn drop = ffi::GENERAL_NAME_free;
1238 
1239     /// An `X509` certificate alternative names.
1240     pub struct GeneralName;
1241     /// Reference to `GeneralName`.
1242     pub struct GeneralNameRef;
1243 }
1244 
1245 impl GeneralNameRef {
1246     fn ia5_string(&self, ffi_type: c_int) -> Option<&str> {
1247         unsafe {
1248             if (*self.as_ptr()).type_ != ffi_type {
1249                 return None;
1250             }
1251 
1252             let ptr = ASN1_STRING_get0_data((*self.as_ptr()).d as *mut _);
1253             let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _);
1254 
1255             let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
1256             // IA5Strings are stated to be ASCII (specifically IA5). Hopefully
1257             // OpenSSL checks that when loading a certificate but if not we'll
1258             // use this instead of from_utf8_unchecked just in case.
1259             str::from_utf8(slice).ok()
1260         }
1261     }
1262 
1263     /// Returns the contents of this `GeneralName` if it is an `rfc822Name`.
1264     pub fn email(&self) -> Option<&str> {
1265         self.ia5_string(ffi::GEN_EMAIL)
1266     }
1267 
1268     /// Returns the contents of this `GeneralName` if it is a `dNSName`.
1269     pub fn dnsname(&self) -> Option<&str> {
1270         self.ia5_string(ffi::GEN_DNS)
1271     }
1272 
1273     /// Returns the contents of this `GeneralName` if it is an `uniformResourceIdentifier`.
1274     pub fn uri(&self) -> Option<&str> {
1275         self.ia5_string(ffi::GEN_URI)
1276     }
1277 
1278     /// Returns the contents of this `GeneralName` if it is an `iPAddress`.
1279     pub fn ipaddress(&self) -> Option<&[u8]> {
1280         unsafe {
1281             if (*self.as_ptr()).type_ != ffi::GEN_IPADD {
1282                 return None;
1283             }
1284 
1285             let ptr = ASN1_STRING_get0_data((*self.as_ptr()).d as *mut _);
1286             let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _);
1287 
1288             Some(slice::from_raw_parts(ptr as *const u8, len as usize))
1289         }
1290     }
1291 }
1292 
1293 impl Stackable for GeneralName {
1294     type StackType = ffi::stack_st_GENERAL_NAME;
1295 }
1296 
1297 foreign_type_and_impl_send_sync! {
1298     type CType = ffi::X509_ALGOR;
1299     fn drop = ffi::X509_ALGOR_free;
1300 
1301     /// An `X509` certificate signature algorithm.
1302     pub struct X509Algorithm;
1303     /// Reference to `X509Algorithm`.
1304     pub struct X509AlgorithmRef;
1305 }
1306 
1307 impl X509AlgorithmRef {
1308     /// Returns the ASN.1 OID of this algorithm.
1309     pub fn object(&self) -> &Asn1ObjectRef {
1310         unsafe {
1311             let mut oid = ptr::null();
1312             X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr());
1313             assert!(!oid.is_null());
1314             Asn1ObjectRef::from_ptr(oid as *mut _)
1315         }
1316     }
1317 }
1318 
1319 cfg_if! {
1320     if #[cfg(any(ossl110, libressl273))] {
1321         use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature};
1322     } else {
1323         #[allow(bad_style)]
1324         unsafe fn X509_getm_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
1325             (*(*(*x).cert_info).validity).notAfter
1326         }
1327 
1328         #[allow(bad_style)]
1329         unsafe fn X509_getm_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
1330             (*(*(*x).cert_info).validity).notBefore
1331         }
1332 
1333         #[allow(bad_style)]
1334         unsafe fn X509_up_ref(x: *mut ffi::X509) {
1335             ffi::CRYPTO_add_lock(
1336                 &mut (*x).references,
1337                 1,
1338                 ffi::CRYPTO_LOCK_X509,
1339                 "mod.rs\0".as_ptr() as *const _,
1340                 line!() as c_int,
1341             );
1342         }
1343 
1344         #[allow(bad_style)]
1345         unsafe fn X509_get0_signature(
1346             psig: *mut *const ffi::ASN1_BIT_STRING,
1347             palg: *mut *const ffi::X509_ALGOR,
1348             x: *const ffi::X509,
1349         ) {
1350             if !psig.is_null() {
1351                 *psig = (*x).signature;
1352             }
1353             if !palg.is_null() {
1354                 *palg = (*x).sig_alg;
1355             }
1356         }
1357     }
1358 }
1359 
1360 cfg_if! {
1361     if #[cfg(ossl110)] {
1362         use ffi::{
1363             X509_ALGOR_get0, ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter,
1364             X509_set1_notBefore, X509_REQ_get_version, X509_REQ_get_subject_name,
1365         };
1366     } else {
1367         use ffi::{
1368             ASN1_STRING_data as ASN1_STRING_get0_data,
1369             X509_STORE_CTX_get_chain as X509_STORE_CTX_get0_chain,
1370             X509_set_notAfter as X509_set1_notAfter,
1371             X509_set_notBefore as X509_set1_notBefore,
1372         };
1373 
1374         #[allow(bad_style)]
1375         unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long {
1376             ffi::ASN1_INTEGER_get((*(*x).req_info).version)
1377         }
1378 
1379         #[allow(bad_style)]
1380         unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME {
1381             (*(*x).req_info).subject
1382         }
1383 
1384         #[allow(bad_style)]
1385         unsafe fn X509_ALGOR_get0(
1386             paobj: *mut *const ffi::ASN1_OBJECT,
1387             pptype: *mut c_int,
1388             pval: *mut *mut ::libc::c_void,
1389             alg: *const ffi::X509_ALGOR,
1390         ) {
1391             if !paobj.is_null() {
1392                 *paobj = (*alg).algorithm;
1393             }
1394             assert!(pptype.is_null());
1395             assert!(pval.is_null());
1396         }
1397     }
1398 }
1399