1//! Bindings to OpenSSL
2//!
3//! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.1 through
4//! 3.x.x and LibreSSL versions 2.5 through 3.7.x are supported.
5//!
6//! # Building
7//!
8//! Both OpenSSL libraries and headers are required to build this crate. There are multiple options available to locate
9//! OpenSSL.
10//!
11//! ## Vendored
12//!
13//! If the `vendored` Cargo feature is enabled, the `openssl-src` crate will be used to compile and statically link to
14//! a copy of OpenSSL. The build process requires a C compiler, perl (and perl-core), and make. The OpenSSL version will generally track
15//! the newest OpenSSL release, and changes to the version are *not* considered breaking changes.
16//!
17//! ```toml
18//! [dependencies]
19//! openssl = { version = "0.10", features = ["vendored"] }
20//! ```
21//!
22//! The vendored copy will not be configured to automatically find the system's root certificates, but the
23//! `openssl-probe` crate can be used to do that instead.
24//!
25//! ## Automatic
26//!
27//! The `openssl-sys` crate will automatically detect OpenSSL installations via Homebrew on macOS and vcpkg on Windows.
28//! Additionally, it will use `pkg-config` on Unix-like systems to find the system installation.
29//!
30//! ```not_rust
31//! # macOS (Homebrew)
32//! $ brew install openssl@3
33//!
34//! # macOS (MacPorts)
35//! $ sudo port install openssl
36//!
37//! # macOS (pkgsrc)
38//! $ sudo pkgin install openssl
39//!
40//! # Arch Linux
41//! $ sudo pacman -S pkg-config openssl
42//!
43//! # Debian and Ubuntu
44//! $ sudo apt-get install pkg-config libssl-dev
45//!
46//! # Fedora
47//! $ sudo dnf install pkg-config perl-FindBin openssl-devel
48//!
49//! # Alpine Linux
50//! $ apk add pkgconfig openssl-dev
51//!
52//! # openSUSE
53//! $ sudo zypper in libopenssl-devel
54//! ```
55//!
56//! ## Manual
57//!
58//! A set of environment variables can be used to point `openssl-sys` towards an OpenSSL installation. They will
59//! override the automatic detection logic.
60//!
61//! * `OPENSSL_DIR` - If specified, the directory of an OpenSSL installation. The directory should contain `lib` and
62//! `include` subdirectories containing the libraries and headers respectively.
63//! * `OPENSSL_LIB_DIR` and `OPENSSL_INCLUDE_DIR` - If specified, the directories containing the OpenSSL libraries and
64//! headers respectively. This can be used if the OpenSSL installation is split in a nonstandard directory layout.
65//! * `OPENSSL_STATIC` - If set, the crate will statically link to OpenSSL rather than dynamically link.
66//! * `OPENSSL_LIBS` - If set, a `:`-separated list of library names to link to (e.g. `ssl:crypto`). This can be used
67//! if nonstandard library names were used for whatever reason.
68//! * `OPENSSL_NO_VENDOR` - If set, always find OpenSSL in the system, even if the `vendored` feature is enabled.
69//!
70//! Additionally, these variables can be prefixed with the upper-cased target architecture (e.g.
71//! `X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR`), which can be useful when cross compiling.
72//!
73//! # Feature Detection
74//!
75//! APIs have been added to and removed from the various supported OpenSSL versions, and this library exposes the
76//! functionality available in the version being linked against. This means that methods, constants, and even modules
77//! will be present when building against one version of OpenSSL but not when building against another! APIs will
78//! document any version-specific availability restrictions.
79//!
80//! A build script can be used to detect the OpenSSL or LibreSSL version at compile time if needed. The `openssl-sys`
81//! crate propagates the version via the `DEP_OPENSSL_VERSION_NUMBER` and `DEP_OPENSSL_LIBRESSL_VERSION_NUMBER`
82//! environment variables to build scripts. The version format is a hex-encoding of the OpenSSL release version:
83//! `0xMNNFFPPS`. For example, version 1.0.2g's encoding is `0x1_00_02_07_0`.
84//!
85//! For example, let's say we want to adjust the TLSv1.3 cipher suites used by a client, but also want to compile
86//! against OpenSSL versions that don't support TLSv1.3:
87//!
88//! Cargo.toml:
89//!
90//! ```toml
91//! [dependencies]
92//! openssl-sys = "0.9"
93//! openssl = "0.10"
94//! ```
95//!
96//! build.rs:
97//!
98//! ```
99//! use std::env;
100//!
101//! fn main() {
102//! if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
103//! let version = u64::from_str_radix(&v, 16).unwrap();
104//!
105//! if version >= 0x1_01_01_00_0 {
106//! println!("cargo:rustc-cfg=openssl111");
107//! }
108//! }
109//! }
110//! ```
111//!
112//! lib.rs:
113//!
114//! ```
115//! use openssl::ssl::{SslConnector, SslMethod};
116//!
117//! let mut ctx = SslConnector::builder(SslMethod::tls()).unwrap();
118//!
119//! // set_ciphersuites was added in OpenSSL 1.1.1, so we can only call it when linking against that version
120//! #[cfg(openssl111)]
121//! ctx.set_ciphersuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256").unwrap();
122//! ```
123#![doc(html_root_url = "https://docs.rs/openssl/0.10")]
124#![warn(rust_2018_idioms)]
125#![allow(clippy::uninlined_format_args, clippy::needless_doctest_main)]
126
127#[doc(inline)]
128pub use ffi::init;
129
130use libc::c_int;
131#[cfg(ossl300)]
132use libc::c_long;
133
134use crate::error::ErrorStack;
135
136#[macro_use]
137mod macros;
138
139mod bio;
140#[macro_use]
141mod util;
142pub mod aes;
143pub mod asn1;
144pub mod base64;
145pub mod bn;
146pub mod cipher;
147pub mod cipher_ctx;
148#[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))]
149pub mod cms;
150pub mod conf;
151pub mod derive;
152pub mod dh;
153pub mod dsa;
154pub mod ec;
155pub mod ecdsa;
156pub mod encrypt;
157#[cfg(not(boringssl))]
158pub mod envelope;
159pub mod error;
160pub mod ex_data;
161#[cfg(not(any(libressl, ossl300)))]
162pub mod fips;
163pub mod hash;
164#[cfg(ossl300)]
165pub mod lib_ctx;
166pub mod md;
167pub mod md_ctx;
168pub mod memcmp;
169pub mod nid;
170#[cfg(not(osslconf = "OPENSSL_NO_OCSP"))]
171pub mod ocsp;
172pub mod pkcs12;
173pub mod pkcs5;
174#[cfg(not(boringssl))]
175pub mod pkcs7;
176pub mod pkey;
177pub mod pkey_ctx;
178#[cfg(ossl300)]
179pub mod provider;
180pub mod rand;
181pub mod rsa;
182pub mod sha;
183pub mod sign;
184pub mod srtp;
185pub mod ssl;
186pub mod stack;
187pub mod string;
188pub mod symm;
189pub mod version;
190pub mod x509;
191
192#[cfg(boringssl)]
193type LenType = libc::size_t;
194#[cfg(not(boringssl))]
195type LenType = libc::c_int;
196
197#[cfg(boringssl)]
198type SLenType = libc::ssize_t;
199#[cfg(not(boringssl))]
200type SLenType = libc::c_int;
201
202#[inline]
203fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
204 if r.is_null() {
205 Err(ErrorStack::get())
206 } else {
207 Ok(r)
208 }
209}
210
211#[inline]
212fn cvt_p_const<T>(r: *const T) -> Result<*const T, ErrorStack> {
213 if r.is_null() {
214 Err(ErrorStack::get())
215 } else {
216 Ok(r)
217 }
218}
219
220#[inline]
221fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
222 if r <= 0 {
223 Err(ErrorStack::get())
224 } else {
225 Ok(r)
226 }
227}
228
229// cvt_long is currently only used in functions that require openssl >= 3.0.0,
230// so this cfg statement is used to avoid "unused function" errors when
231// compiling with openssl < 3.0.0
232#[inline]
233#[cfg(ossl300)]
234fn cvt_long(r: c_long) -> Result<c_long, ErrorStack> {
235 if r <= 0 {
236 Err(ErrorStack::get())
237 } else {
238 Ok(r)
239 }
240}
241
242#[inline]
243fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
244 if r < 0 {
245 Err(ErrorStack::get())
246 } else {
247 Ok(r)
248 }
249}
250