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  #[cfg(all(soong, boringssl))]
128  extern crate bssl_sys as ffi;
129  
130  #[doc(inline)]
131  pub use ffi::init;
132  
133  use libc::c_int;
134  #[cfg(ossl300)]
135  use libc::c_long;
136  
137  use crate::error::ErrorStack;
138  
139  #[macro_use]
140  mod macros;
141  
142  mod bio;
143  #[macro_use]
144  mod util;
145  pub mod aes;
146  pub mod asn1;
147  pub mod base64;
148  pub mod bn;
149  pub mod cipher;
150  pub mod cipher_ctx;
151  #[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS"), not(boringssl)))]
152  pub mod cms;
153  pub mod conf;
154  pub mod derive;
155  pub mod dh;
156  pub mod dsa;
157  pub mod ec;
158  pub mod ecdsa;
159  pub mod encrypt;
160  #[cfg(not(boringssl))]
161  pub mod envelope;
162  pub mod error;
163  pub mod ex_data;
164  #[cfg(not(any(libressl, ossl300)))]
165  pub mod fips;
166  pub mod hash;
167  #[cfg(boringssl)]
168  pub mod hkdf;
169  #[cfg(boringssl)]
170  pub mod hmac;
171  #[cfg(ossl300)]
172  pub mod lib_ctx;
173  pub mod md;
174  pub mod md_ctx;
175  pub mod memcmp;
176  pub mod nid;
177  #[cfg(all(not(osslconf = "OPENSSL_NO_OCSP"), not(boringssl)))]
178  pub mod ocsp;
179  pub mod pkcs12;
180  pub mod pkcs5;
181  #[cfg(not(boringssl))]
182  pub mod pkcs7;
183  pub mod pkey;
184  pub mod pkey_ctx;
185  #[cfg(ossl300)]
186  pub mod provider;
187  pub mod rand;
188  pub mod rsa;
189  pub mod sha;
190  pub mod sign;
191  pub mod srtp;
192  pub mod ssl;
193  pub mod stack;
194  pub mod string;
195  pub mod symm;
196  pub mod version;
197  pub mod x509;
198  
199  #[cfg(boringssl)]
200  type LenType = libc::size_t;
201  #[cfg(not(boringssl))]
202  type LenType = libc::c_int;
203  
204  #[cfg(boringssl)]
205  type SLenType = libc::ssize_t;
206  #[cfg(not(boringssl))]
207  type SLenType = libc::c_int;
208  
209  #[inline]
cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack>210  fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
211      if r.is_null() {
212          Err(ErrorStack::get())
213      } else {
214          Ok(r)
215      }
216  }
217  
218  #[inline]
cvt_p_const<T>(r: *const T) -> Result<*const T, ErrorStack>219  fn cvt_p_const<T>(r: *const T) -> Result<*const T, ErrorStack> {
220      if r.is_null() {
221          Err(ErrorStack::get())
222      } else {
223          Ok(r)
224      }
225  }
226  
227  #[inline]
cvt(r: c_int) -> Result<c_int, ErrorStack>228  fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
229      if r <= 0 {
230          Err(ErrorStack::get())
231      } else {
232          Ok(r)
233      }
234  }
235  
236  // cvt_long is currently only used in functions that require openssl >= 3.0.0,
237  // so this cfg statement is used to avoid "unused function" errors when
238  // compiling with openssl < 3.0.0
239  #[inline]
240  #[cfg(ossl300)]
cvt_long(r: c_long) -> Result<c_long, ErrorStack>241  fn cvt_long(r: c_long) -> Result<c_long, ErrorStack> {
242      if r <= 0 {
243          Err(ErrorStack::get())
244      } else {
245          Ok(r)
246      }
247  }
248  
249  #[inline]
cvt_n(r: c_int) -> Result<c_int, ErrorStack>250  fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
251      if r < 0 {
252          Err(ErrorStack::get())
253      } else {
254          Ok(r)
255      }
256  }
257