      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

    //! Bindings to OpenSSL
    //!
    //! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.1 through
    //! 1.1.1 and LibreSSL versions 2.5 through 2.8 are supported.
    //!
    //! # Building
    //!
    //! Both OpenSSL libraries and headers are required to build this crate. There are multiple options available to locate
    //! OpenSSL.
    //!
    //! ## Vendored
    //!
    //! If the `vendored` Cargo feature is enabled, the `openssl-src` crate will be used to compile and statically link to
    //! a copy of OpenSSL. The build process requires a C compiler, perl, and make. The OpenSSL version will generally track
    //! the newest OpenSSL release, and changes to the version are *not* considered breaking changes.
    //!
    //! ```toml
    //! [dependencies]
    //! openssl = { version = "0.10", features = ["vendored"] }
    //! ```
    //!
    //! The vendored copy will not be configured to automatically find the system's root certificates, but the
    //! `openssl-probe` crate can be used to do that instead.
    //!
    //! ## Automatic
    //!
    //! The `openssl-sys` crate will automatically detect OpenSSL installations via Homebrew on macOS and vcpkg on Windows.
    //! Additionally, it will use `pkg-config` on Unix-like systems to find the system installation.
    //!
    //! ```not_rust
    //! # macOS
    //! $ brew install openssl@1.1
    //!
    //! # Arch Linux
    //! $ sudo pacman -S pkg-config openssl
    //!
    //! # Debian and Ubuntu
    //! $ sudo apt-get install pkg-config libssl-dev
    //!
    //! # Fedora
    //! $ sudo dnf install pkg-config openssl-devel
    //! ```
    //!
    //! ## Manual
    //!
    //! A set of environment variables can be used to point `openssl-sys` towards an OpenSSL installation. They will
    //! override the automatic detection logic.
    //!
    //! * `OPENSSL_DIR` - If specified, the directory of an OpenSSL installation. The directory should contain `lib` and
    //!     `include` subdirectories containing the libraries and headers respectively.
    //! * `OPENSSL_LIB_DIR` and `OPENSSL_INCLUDE_DIR` - If specified, the directories containing the OpenSSL libraries and
    //!     headers respectively. This can be used if the OpenSSL installation is split in a nonstandard directory layout.
    //! * `OPENSSL_STATIC` - If set, the crate will statically link to OpenSSL rather than dynamically link.
    //! * `OPENSSL_LIBS` - If set, a `:`-separated list of library names to link to (e.g. `ssl:crypto`). This can be used
    //!     if nonstandard library names were used for whatever reason.
    //! * `OPENSSL_NO_VENDOR` - If set, always find OpenSSL in the system, even if the `vendored` feature is enabled.
    //!
    //! Additionally, these variables can be prefixed with the upper-cased target architecture (e.g.
    //!     `X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR`), which can be useful when cross compiling.
    //!
    //! # Feature Detection
    //!
    //! APIs have been added to and removed from the various supported OpenSSL versions, and this library exposes the
    //! functionality available in the version being linked against. This means that methods, constants, and even modules
    //! will be present when building against one version of OpenSSL but not when building against another! APIs will
    //! document any version-specific availability restrictions.
    //!
    //! A build script can be used to detect the OpenSSL or LibreSSL version at compile time if needed. The `openssl-sys`
    //! crate propagates the version via the `DEP_OPENSSL_VERSION_NUMBER` and `DEP_OPENSSL_LIBRESSL_VERSION_NUMBER`
    //! environment variables to build scripts. The version format is a hex-encoding of the OpenSSL release version:
    //! `0xMNNFFPPS`. For example, version 1.0.2g's encoding is `0x1_00_02_07_0`.
    //!
    //! For example, let's say we want to adjust the TLSv1.3 cipher suites used by a client, but also want to compile
    //! against OpenSSL versions that don't support TLSv1.3:
    //!
    //! Cargo.toml:
    //!
    //! ```toml
    //! [dependencies]
    //! openssl-sys = "0.9"
    //! openssl = "0.10"
    //! ```
    //!
    //! build.rs:
    //!
    //! ```
    //! use std::env;
    //!
    //! fn main() {
    //!     if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
    //!         let version = u64::from_str_radix(&v, 16).unwrap();
    //!
    //!         if version >= 0x1_01_01_00_0 {
    //!             println!("cargo:rustc-cfg=openssl111");
    //!         }
    //!     }
    //! }
    //! ```
    //!
    //! lib.rs:
    //!
    //! ```
    //! use openssl::ssl::{SslConnector, SslMethod};
    //!
    //! let mut ctx = SslConnector::builder(SslMethod::tls()).unwrap();
    //!
    //! // set_ciphersuites was added in OpenSSL 1.1.1, so we can only call it when linking against that version
    //! #[cfg(openssl111)]
    //! ctx.set_ciphersuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256").unwrap();
    //! ```
    #![doc(html_root_url = "https://docs.rs/openssl/0.10")]

    #[macro_use]
    extern crate bitflags;
    #[macro_use]
    extern crate cfg_if;
    #[macro_use]
    extern crate foreign_types;
    #[macro_use]
    extern crate lazy_static;
    extern crate libc;
    extern crate openssl_sys as ffi;

    #[cfg(test)]
    extern crate hex;
    #[cfg(test)]
    extern crate tempdir;

    #[doc(inline)]
    pub use ffi::init;

    use libc::c_int;

    use error::ErrorStack;

    #[macro_use]
    mod macros;

    mod bio;
    #[macro_use]
    mod util;
    pub mod aes;
    pub mod asn1;
    pub mod base64;
    pub mod bn;
    #[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))]
    pub mod cms;
    pub mod conf;
    pub mod derive;
    pub mod dh;
    pub mod dsa;
    pub mod ec;
    pub mod ecdsa;
    pub mod encrypt;
    pub mod envelope;
    pub mod error;
    pub mod ex_data;
    #[cfg(not(libressl))]
    pub mod fips;
    pub mod hash;
    pub mod memcmp;
    pub mod nid;
    pub mod ocsp;
    pub mod pkcs12;
    pub mod pkcs5;
    pub mod pkcs7;
    pub mod pkey;
    pub mod rand;
    pub mod rsa;
    pub mod sha;
    pub mod sign;
    pub mod srtp;
    pub mod ssl;
    pub mod stack;
    pub mod string;
    pub mod symm;
    pub mod version;
    pub mod x509;

    fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
        if r.is_null() {
            Err(ErrorStack::get())
        } else {
            Ok(r)
        }
    }

    fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
        if r <= 0 {
            Err(ErrorStack::get())
        } else {
            Ok(r)
        }
    }

    fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
        if r < 0 {
            Err(ErrorStack::get())
        } else {
            Ok(r)
        }
    }