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