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 openssl-devel
48 //!
49 //! # Alpine Linux
50 //! $ apk add pkgconfig openssl-dev
51 //! ```
52 //!
53 //! ## Manual
54 //!
55 //! A set of environment variables can be used to point `openssl-sys` towards an OpenSSL installation. They will
56 //! override the automatic detection logic.
57 //!
58 //! * `OPENSSL_DIR` - If specified, the directory of an OpenSSL installation. The directory should contain `lib` and
59 //! `include` subdirectories containing the libraries and headers respectively.
60 //! * `OPENSSL_LIB_DIR` and `OPENSSL_INCLUDE_DIR` - If specified, the directories containing the OpenSSL libraries and
61 //! headers respectively. This can be used if the OpenSSL installation is split in a nonstandard directory layout.
62 //! * `OPENSSL_STATIC` - If set, the crate will statically link to OpenSSL rather than dynamically link.
63 //! * `OPENSSL_LIBS` - If set, a `:`-separated list of library names to link to (e.g. `ssl:crypto`). This can be used
64 //! if nonstandard library names were used for whatever reason.
65 //! * `OPENSSL_NO_VENDOR` - If set, always find OpenSSL in the system, even if the `vendored` feature is enabled.
66 //!
67 //! Additionally, these variables can be prefixed with the upper-cased target architecture (e.g.
68 //! `X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR`), which can be useful when cross compiling.
69 //!
70 //! # Feature Detection
71 //!
72 //! APIs have been added to and removed from the various supported OpenSSL versions, and this library exposes the
73 //! functionality available in the version being linked against. This means that methods, constants, and even modules
74 //! will be present when building against one version of OpenSSL but not when building against another! APIs will
75 //! document any version-specific availability restrictions.
76 //!
77 //! A build script can be used to detect the OpenSSL or LibreSSL version at compile time if needed. The `openssl-sys`
78 //! crate propagates the version via the `DEP_OPENSSL_VERSION_NUMBER` and `DEP_OPENSSL_LIBRESSL_VERSION_NUMBER`
79 //! environment variables to build scripts. The version format is a hex-encoding of the OpenSSL release version:
80 //! `0xMNNFFPPS`. For example, version 1.0.2g's encoding is `0x1_00_02_07_0`.
81 //!
82 //! For example, let's say we want to adjust the TLSv1.3 cipher suites used by a client, but also want to compile
83 //! against OpenSSL versions that don't support TLSv1.3:
84 //!
85 //! Cargo.toml:
86 //!
87 //! ```toml
88 //! [dependencies]
89 //! openssl-sys = "0.9"
90 //! openssl = "0.10"
91 //! ```
92 //!
93 //! build.rs:
94 //!
95 //! ```
96 //! use std::env;
97 //!
98 //! fn main() {
99 //! if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
100 //! let version = u64::from_str_radix(&v, 16).unwrap();
101 //!
102 //! if version >= 0x1_01_01_00_0 {
103 //! println!("cargo:rustc-cfg=openssl111");
104 //! }
105 //! }
106 //! }
107 //! ```
108 //!
109 //! lib.rs:
110 //!
111 //! ```
112 //! use openssl::ssl::{SslConnector, SslMethod};
113 //!
114 //! let mut ctx = SslConnector::builder(SslMethod::tls()).unwrap();
115 //!
116 //! // set_ciphersuites was added in OpenSSL 1.1.1, so we can only call it when linking against that version
117 //! #[cfg(openssl111)]
118 //! ctx.set_ciphersuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256").unwrap();
119 //! ```
120 #![doc(html_root_url = "https://docs.rs/openssl/0.10")]
121 #![warn(rust_2018_idioms)]
122 #![allow(clippy::uninlined_format_args, clippy::needless_doctest_main)]
123
124 #[doc(inline)]
125 pub use ffi::init;
126
127 use libc::c_int;
128
129 extern crate openssl_sys as ffi;
130 use crate::error::ErrorStack;
131
132 #[macro_use]
133 mod macros;
134
135 mod bio;
136 #[macro_use]
137 mod util;
138 pub mod aes;
139 pub mod asn1;
140 pub mod base64;
141 pub mod bn;
142 pub mod cipher;
143 pub mod cipher_ctx;
144 #[cfg(all(not(boringssl), not(libressl), not(osslconf = "OPENSSL_NO_CMS")))]
145 pub mod cms;
146 pub mod conf;
147 pub mod derive;
148 pub mod dh;
149 pub mod dsa;
150 pub mod ec;
151 pub mod ecdsa;
152 pub mod encrypt;
153 #[cfg(not(boringssl))]
154 pub mod envelope;
155 pub mod error;
156 pub mod ex_data;
157 #[cfg(not(any(libressl, ossl300)))]
158 pub mod fips;
159 pub mod hash;
160 #[cfg(ossl300)]
161 pub mod lib_ctx;
162 pub mod md;
163 pub mod md_ctx;
164 pub mod memcmp;
165 pub mod nid;
166 #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_OCSP")))]
167 pub mod ocsp;
168 pub mod pkcs12;
169 pub mod pkcs5;
170 #[cfg(not(boringssl))]
171 pub mod pkcs7;
172 pub mod pkey;
173 pub mod pkey_ctx;
174 #[cfg(ossl300)]
175 pub mod provider;
176 pub mod rand;
177 pub mod rsa;
178 pub mod sha;
179 pub mod sign;
180 pub mod srtp;
181 pub mod ssl;
182 pub mod stack;
183 pub mod string;
184 pub mod symm;
185 pub mod version;
186 pub mod x509;
187
188 #[cfg(boringssl)]
189 type LenType = libc::size_t;
190 #[cfg(not(boringssl))]
191 type LenType = libc::c_int;
192
193 #[cfg(boringssl)]
194 type SLenType = libc::ssize_t;
195 #[cfg(not(boringssl))]
196 type SLenType = libc::c_int;
197
198 #[inline]
cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack>199 fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
200 if r.is_null() {
201 Err(ErrorStack::get())
202 } else {
203 Ok(r)
204 }
205 }
206
207 #[inline]
cvt(r: c_int) -> Result<c_int, ErrorStack>208 fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
209 if r <= 0 {
210 Err(ErrorStack::get())
211 } else {
212 Ok(r)
213 }
214 }
215
216 #[inline]
cvt_n(r: c_int) -> Result<c_int, ErrorStack>217 fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
218 if r < 0 {
219 Err(ErrorStack::get())
220 } else {
221 Ok(r)
222 }
223 }
224