variant_ssl_sys/
lib.rs

1#![allow(
2    clippy::missing_safety_doc,
3    dead_code,
4    non_camel_case_types,
5    non_snake_case,
6    non_upper_case_globals,
7    unused_imports
8)]
9#![doc(html_root_url = "https://docs.rs/variant-ssl-sys/0.15")]
10#![recursion_limit = "128"] // configure fixed limit across all rust versions
11
12extern crate libc;
13pub use libc::c_int;
14
15#[cfg(feature = "boringssl")]
16extern crate bssl_sys;
17#[cfg(feature = "boringssl")]
18pub use bssl_sys::*;
19
20#[cfg(feature = "aws-lc")]
21extern crate aws_lc_sys;
22
23#[cfg(awslc)]
24#[path = "."]
25mod aws_lc {
26    #[cfg(feature = "aws-lc")]
27    pub use aws_lc_sys::*;
28
29    #[cfg(not(feature = "aws-lc"))]
30    include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
31
32    use libc::{c_char, c_long, c_void};
33
34    pub fn init() {
35        unsafe { CRYPTO_library_init() }
36    }
37
38    // BIO_get_mem_data is a C preprocessor macro by definition
39    #[allow(non_snake_case, clippy::not_unsafe_ptr_arg_deref)]
40    pub fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long {
41        unsafe { BIO_ctrl(b, BIO_CTRL_INFO, 0, pp.cast::<c_void>()) }
42    }
43}
44#[cfg(awslc)]
45pub use aws_lc::*;
46
47#[cfg(openssl)]
48#[path = "."]
49mod openssl {
50    use libc::*;
51
52    #[cfg(feature = "bindgen")]
53    include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
54
55    pub use self::aes::*;
56    pub use self::asn1::*;
57    pub use self::bio::*;
58    pub use self::bn::*;
59    pub use self::cms::*;
60    pub use self::crypto::*;
61    pub use self::dtls1::*;
62    pub use self::ec::*;
63    pub use self::err::*;
64    pub use self::evp::*;
65    #[cfg(not(feature = "bindgen"))]
66    pub use self::handwritten::*;
67    #[cfg(tongsuo)]
68    pub use self::ntls::*;
69    pub use self::obj_mac::*;
70    pub use self::ocsp::*;
71    pub use self::pem::*;
72    pub use self::pkcs7::*;
73    pub use self::rsa::*;
74    pub use self::sha::*;
75    pub use self::srtp::*;
76    pub use self::ssl::*;
77    pub use self::ssl3::*;
78    pub use self::tls1::*;
79    pub use self::types::*;
80    pub use self::x509::*;
81    pub use self::x509_vfy::*;
82    pub use self::x509v3::*;
83
84    #[macro_use]
85    mod macros;
86
87    mod aes;
88    mod asn1;
89    mod bio;
90    mod bn;
91    mod cms;
92    mod crypto;
93    mod dtls1;
94    mod ec;
95    mod err;
96    mod evp;
97    #[cfg(not(feature = "bindgen"))]
98    mod handwritten;
99    #[cfg(tongsuo)]
100    mod ntls;
101    mod obj_mac;
102    mod ocsp;
103    mod pem;
104    mod pkcs7;
105    mod rsa;
106    mod sha;
107    mod srtp;
108    mod ssl;
109    mod ssl3;
110    mod tls1;
111    mod types;
112    mod x509;
113    mod x509_vfy;
114    mod x509v3;
115
116    use std::sync::Once;
117    // explicitly initialize to work around https://github.com/openssl/openssl/issues/3505
118    static INIT: Once = Once::new();
119
120    // FIXME remove
121    pub type PasswordCallback = unsafe extern "C" fn(
122        buf: *mut c_char,
123        size: c_int,
124        rwflag: c_int,
125        user_data: *mut c_void,
126    ) -> c_int;
127
128    #[cfg(ossl110)]
129    pub fn init() {
130        use std::ptr;
131
132        #[cfg(not(ossl111b))]
133        let init_options = OPENSSL_INIT_LOAD_SSL_STRINGS;
134        #[cfg(ossl111b)]
135        let init_options = OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_NO_ATEXIT;
136
137        INIT.call_once(|| unsafe {
138            OPENSSL_init_ssl(init_options, ptr::null_mut());
139        })
140    }
141
142    #[cfg(not(ossl110))]
143    pub fn init() {
144        use std::io::{self, Write};
145        use std::mem;
146        use std::process;
147        use std::sync::{Mutex, MutexGuard};
148
149        static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
150        static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> =
151            0 as *mut Vec<Option<MutexGuard<'static, ()>>>;
152
153        unsafe extern "C" fn locking_function(
154            mode: c_int,
155            n: c_int,
156            _file: *const c_char,
157            _line: c_int,
158        ) {
159            let mutex = &(*MUTEXES)[n as usize];
160
161            if mode & CRYPTO_LOCK != 0 {
162                (*GUARDS)[n as usize] = Some(mutex.lock().unwrap());
163            } else {
164                if let None = (*GUARDS)[n as usize].take() {
165                    let _ = writeln!(
166                        io::stderr(),
167                        "BUG: rust-openssl lock {} already unlocked, aborting",
168                        n
169                    );
170                    process::abort();
171                }
172            }
173        }
174
175        cfg_if! {
176            if #[cfg(unix)] {
177                fn set_id_callback() {
178                    unsafe extern "C" fn thread_id() -> c_ulong {
179                        ::libc::pthread_self() as c_ulong
180                    }
181
182                    unsafe {
183                        CRYPTO_set_id_callback(Some(thread_id));
184                    }
185                }
186            } else {
187                fn set_id_callback() {}
188            }
189        }
190
191        INIT.call_once(|| unsafe {
192            SSL_library_init();
193            SSL_load_error_strings();
194            OPENSSL_add_all_algorithms_noconf();
195
196            let num_locks = CRYPTO_num_locks();
197            let mut mutexes = Box::new(Vec::new());
198            for _ in 0..num_locks {
199                mutexes.push(Mutex::new(()));
200            }
201            MUTEXES = mem::transmute(mutexes);
202            let guards: Box<Vec<Option<MutexGuard<()>>>> =
203                Box::new((0..num_locks).map(|_| None).collect());
204            GUARDS = mem::transmute(guards);
205
206            CRYPTO_set_locking_callback(Some(locking_function));
207            set_id_callback();
208        })
209    }
210
211    /// Disable explicit initialization of the openssl libs.
212    ///
213    /// This is only appropriate to use if the openssl crate is being consumed by an application
214    /// that will be performing the initialization explicitly.
215    ///
216    /// # Safety
217    ///
218    /// In some versions of openssl, skipping initialization will fall back to the default procedure
219    /// while other will cause difficult to debug errors so care must be taken when calling this.
220    pub unsafe fn assume_init() {
221        INIT.call_once(|| {});
222    }
223}
224#[cfg(openssl)]
225pub use openssl::*;