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