1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#![allow(
    clippy::missing_safety_doc,
    dead_code,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_imports
)]
#![cfg_attr(feature = "unstable_boringssl", allow(ambiguous_glob_reexports))]
#![doc(html_root_url = "https://docs.rs/openssl-sys/0.9")]
#![recursion_limit = "128"] // configure fixed limit across all rust versions

extern crate libc;
pub use libc::c_int;

#[cfg(feature = "unstable_boringssl")]
extern crate bssl_sys;
#[cfg(feature = "unstable_boringssl")]
pub use bssl_sys::*;

#[cfg(all(boringssl, not(feature = "unstable_boringssl")))]
#[path = "."]
mod boringssl {
    include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));

    pub fn init() {
        unsafe {
            CRYPTO_library_init();
        }
    }
}
#[cfg(all(boringssl, not(feature = "unstable_boringssl")))]
pub use boringssl::*;

#[cfg(openssl)]
#[path = "."]
mod openssl {
    use libc::*;

    #[cfg(feature = "bindgen")]
    include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));

    pub use self::aes::*;
    pub use self::asn1::*;
    pub use self::bio::*;
    pub use self::bn::*;
    pub use self::cms::*;
    pub use self::crypto::*;
    pub use self::dtls1::*;
    pub use self::ec::*;
    pub use self::err::*;
    pub use self::evp::*;
    #[cfg(not(feature = "bindgen"))]
    pub use self::handwritten::*;
    pub use self::obj_mac::*;
    pub use self::ocsp::*;
    pub use self::pem::*;
    pub use self::pkcs7::*;
    pub use self::rsa::*;
    pub use self::sha::*;
    pub use self::srtp::*;
    pub use self::ssl::*;
    pub use self::ssl3::*;
    pub use self::tls1::*;
    pub use self::types::*;
    pub use self::x509::*;
    pub use self::x509_vfy::*;
    pub use self::x509v3::*;

    #[macro_use]
    mod macros;

    mod aes;
    mod asn1;
    mod bio;
    mod bn;
    mod cms;
    mod crypto;
    mod dtls1;
    mod ec;
    mod err;
    mod evp;
    #[cfg(not(feature = "bindgen"))]
    mod handwritten;
    mod obj_mac;
    mod ocsp;
    mod pem;
    mod pkcs7;
    mod rsa;
    mod sha;
    mod srtp;
    mod ssl;
    mod ssl3;
    mod tls1;
    mod types;
    mod x509;
    mod x509_vfy;
    mod x509v3;

    use std::sync::Once;
    // explicitly initialize to work around https://github.com/openssl/openssl/issues/3505
    static INIT: Once = Once::new();

    // FIXME remove
    pub type PasswordCallback = unsafe extern "C" fn(
        buf: *mut c_char,
        size: c_int,
        rwflag: c_int,
        user_data: *mut c_void,
    ) -> c_int;

    #[cfg(ossl110)]
    pub fn init() {
        use std::ptr;

        #[cfg(not(ossl111b))]
        let init_options = OPENSSL_INIT_LOAD_SSL_STRINGS;
        #[cfg(ossl111b)]
        let init_options = OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_NO_ATEXIT;

        INIT.call_once(|| unsafe {
            OPENSSL_init_ssl(init_options, ptr::null_mut());
        })
    }

    #[cfg(not(ossl110))]
    pub fn init() {
        use std::io::{self, Write};
        use std::mem;
        use std::process;
        use std::sync::{Mutex, MutexGuard};

        static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
        static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> =
            0 as *mut Vec<Option<MutexGuard<'static, ()>>>;

        unsafe extern "C" fn locking_function(
            mode: c_int,
            n: c_int,
            _file: *const c_char,
            _line: c_int,
        ) {
            let mutex = &(*MUTEXES)[n as usize];

            if mode & CRYPTO_LOCK != 0 {
                (*GUARDS)[n as usize] = Some(mutex.lock().unwrap());
            } else {
                if let None = (*GUARDS)[n as usize].take() {
                    let _ = writeln!(
                        io::stderr(),
                        "BUG: rust-openssl lock {} already unlocked, aborting",
                        n
                    );
                    process::abort();
                }
            }
        }

        cfg_if! {
            if #[cfg(unix)] {
                fn set_id_callback() {
                    unsafe extern "C" fn thread_id() -> c_ulong {
                        ::libc::pthread_self() as c_ulong
                    }

                    unsafe {
                        CRYPTO_set_id_callback__fixed_rust(Some(thread_id));
                    }
                }
            } else {
                fn set_id_callback() {}
            }
        }

        INIT.call_once(|| unsafe {
            SSL_library_init();
            SSL_load_error_strings();
            OPENSSL_add_all_algorithms_noconf();

            let num_locks = CRYPTO_num_locks();
            let mut mutexes = Box::new(Vec::new());
            for _ in 0..num_locks {
                mutexes.push(Mutex::new(()));
            }
            MUTEXES = mem::transmute(mutexes);
            let guards: Box<Vec<Option<MutexGuard<()>>>> =
                Box::new((0..num_locks).map(|_| None).collect());
            GUARDS = mem::transmute(guards);

            CRYPTO_set_locking_callback__fixed_rust(Some(locking_function));
            set_id_callback();
        })
    }

    /// Disable explicit initialization of the openssl libs.
    ///
    /// This is only appropriate to use if the openssl crate is being consumed by an application
    /// that will be performing the initialization explicitly.
    ///
    /// # Safety
    ///
    /// In some versions of openssl, skipping initialization will fall back to the default procedure
    /// while other will cause difficult to debug errors so care must be taken when calling this.
    pub unsafe fn assume_init() {
        INIT.call_once(|| {});
    }
}
#[cfg(openssl)]
pub use openssl::*;