rustls_openssl/
lib.rs

1//! # rustls-openssl
2//!
3//! A [rustls crypto provider](https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html)  that uses OpenSSL for crypto.
4//!
5//! ## Supported Ciphers
6//!
7//! Supported cipher suites are listed below, in descending order of preference.
8//!
9//! If OpenSSL is compiled with the `OPENSSL_NO_CHACHA` option, or the `fips` feature is enabled,
10//! then the suites using ChaCha20-Poly1305 will not be available.
11//! If the `tls12` feature is disabled then the TLS 1.2 cipher suites will not be available.
12//!
13//! ### TLS 1.3
14//!
15//! * TLS13_AES_256_GCM_SHA384
16//! * TLS13_AES_128_GCM_SHA256
17//! * TLS13_CHACHA20_POLY1305_SHA256
18//!
19//! ### TLS 1.2
20//!
21//! * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
22//! * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
23//! * TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
24//! * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
25//! * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
26//! * TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
27//!
28//! ## Supported Key Exchanges
29//!
30//! In descending order of preference:
31//!
32//! * SECP384R1
33//! * SECP256R1
34//! * X25519
35//!
36//! If the `fips` feature is enabled then X25519 will not be available.
37//!
38//! ## Usage
39//!
40//! Add `rustls-openssl` to your `Cargo.toml`:
41//!
42//! ```toml
43//! [dependencies]
44//! rustls = { version = "0.23.0", features = ["tls12", "std"], default-features = false }
45//! rustls_openssl = "0.1.0"
46//! ```
47//!
48//! ### Configuration
49//!
50//! Use [default_provider()] to create a provider using cipher suites and key exchange groups listed above.
51//! Use [custom_provider()] to specify custom cipher suites and key exchange groups.
52//!
53//! # Features
54//! - `tls12`: Enables TLS 1.2 cipher suites. Enabled by default.
55//! - `fips`: Enabling this feature removes non-FIPS-approved cipher suites and key exchanges. Disabled by default. See [fips].
56#![warn(missing_docs)]
57use openssl::rand::rand_priv_bytes;
58use rustls::crypto::{CryptoProvider, GetRandomFailed, SupportedKxGroup};
59use rustls::SupportedCipherSuite;
60
61mod aead;
62mod hash;
63mod hkdf;
64mod hmac;
65mod kx;
66mod openssl_internal;
67#[cfg(feature = "tls12")]
68mod prf;
69mod quic;
70mod signer;
71#[cfg(feature = "tls12")]
72mod tls12;
73mod tls13;
74mod verify;
75
76pub mod cipher_suite {
77    //! Supported cipher suites.
78    #[cfg(feature = "tls12")]
79    pub use super::tls12::{
80        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
81        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
82    };
83    #[cfg(all(feature = "tls12", chacha, not(feature = "fips")))]
84    pub use super::tls12::{
85        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
86    };
87    #[cfg(all(chacha, not(feature = "fips")))]
88    pub use super::tls13::TLS13_CHACHA20_POLY1305_SHA256;
89    pub use super::tls13::{TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384};
90}
91
92pub use kx::ALL_KX_GROUPS;
93
94pub mod kx_group {
95    //! Supported key exchange groups.
96    #[cfg(not(feature = "fips"))]
97    pub use super::kx::X25519;
98    pub use super::kx::{SECP256R1, SECP384R1};
99}
100pub use signer::KeyProvider;
101pub use verify::SUPPORTED_SIG_ALGS;
102
103/// Returns an OpenSSL-based [CryptoProvider] using all available cipher suites ([ALL_CIPHER_SUITES]) and key exchange groups ([ALL_KX_GROUPS]).
104///
105/// Sample usage:
106/// ```rust
107/// use rustls::{ClientConfig, RootCertStore};
108/// use rustls_openssl::default_provider;
109/// use std::sync::Arc;
110/// use webpki_roots;
111///
112/// let mut root_store = RootCertStore {
113///     roots: webpki_roots::TLS_SERVER_ROOTS.iter().cloned().collect(),
114/// };
115///
116/// let mut config =
117///     ClientConfig::builder_with_provider(Arc::new(default_provider()))
118///        .with_safe_default_protocol_versions()
119///         .unwrap()
120///         .with_root_certificates(root_store)
121///         .with_no_client_auth();
122///
123/// ```
124pub fn default_provider() -> CryptoProvider {
125    CryptoProvider {
126        cipher_suites: ALL_CIPHER_SUITES.to_vec(),
127        kx_groups: ALL_KX_GROUPS.to_vec(),
128        signature_verification_algorithms: SUPPORTED_SIG_ALGS,
129        secure_random: &SecureRandom,
130        key_provider: &KeyProvider,
131    }
132}
133
134/// Create a [CryptoProvider] with specific cipher suites and key exchange groups
135///
136/// The specified cipher suites and key exchange groups should be defined in descending order of preference.
137/// i.e the first elements have the highest priority during negotiation.
138///
139/// If the `fips` feature is enabled then fips mode will be enabled for OpenSSL, and this function will panic if this fails.
140///
141/// Sample usage:
142/// ```rust
143/// use rustls::{ClientConfig, RootCertStore};
144/// use rustls_openssl::custom_provider;
145/// use rustls_openssl::cipher_suite::TLS13_AES_128_GCM_SHA256;
146/// use rustls_openssl::kx_group::SECP256R1;
147/// use std::sync::Arc;
148/// use webpki_roots;
149///
150/// let mut root_store = RootCertStore {
151///     roots: webpki_roots::TLS_SERVER_ROOTS.iter().cloned().collect(),
152/// };
153///  
154/// // Set custom config of cipher suites that have been imported from rustls_openssl.
155/// let cipher_suites = vec![TLS13_AES_128_GCM_SHA256];
156/// let kx_group = vec![SECP256R1];
157///
158/// let mut config =
159///     ClientConfig::builder_with_provider(Arc::new(custom_provider(
160///         cipher_suites, kx_group)))
161///             .with_safe_default_protocol_versions()
162///             .unwrap()
163///             .with_root_certificates(root_store)
164///             .with_no_client_auth();
165///
166///
167/// ```
168pub fn custom_provider(
169    cipher_suites: Vec<SupportedCipherSuite>,
170    kx_groups: Vec<&'static dyn SupportedKxGroup>,
171) -> CryptoProvider {
172    CryptoProvider {
173        cipher_suites,
174        kx_groups,
175        signature_verification_algorithms: SUPPORTED_SIG_ALGS,
176        secure_random: &SecureRandom,
177        key_provider: &KeyProvider,
178    }
179}
180
181/// All supported cipher suites in descending order of preference:
182/// * TLS13_AES_256_GCM_SHA384
183/// * TLS13_AES_128_GCM_SHA256
184/// * TLS13_CHACHA20_POLY1305_SHA256
185/// * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
186/// * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
187/// * TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
188/// * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
189/// * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
190/// * TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
191///
192/// If the non-default `fips` feature is enabled, or OpenSSL is compiled with the `OPENSSL_NO_CHACHA` option, then the ChaCha20-Poly1305 cipher suites will not be included.
193/// If the default `tls12` feature is disabled then the TLS 1.2 cipher suites will not be included.
194pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
195    tls13::TLS13_AES_256_GCM_SHA384,
196    tls13::TLS13_AES_128_GCM_SHA256,
197    #[cfg(all(chacha, not(feature = "fips")))]
198    tls13::TLS13_CHACHA20_POLY1305_SHA256,
199    #[cfg(feature = "tls12")]
200    tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
201    #[cfg(feature = "tls12")]
202    tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
203    #[cfg(all(feature = "tls12", chacha, not(feature = "fips")))]
204    tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
205    #[cfg(feature = "tls12")]
206    tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
207    #[cfg(feature = "tls12")]
208    tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
209    #[cfg(all(feature = "tls12", chacha, not(feature = "fips")))]
210    tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
211];
212
213/// A struct that implements [rustls::crypto::SecureRandom].
214#[derive(Debug)]
215pub struct SecureRandom;
216
217impl rustls::crypto::SecureRandom for SecureRandom {
218    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
219        rand_priv_bytes(buf).map_err(|_| GetRandomFailed)
220    }
221
222    fn fips(&self) -> bool {
223        fips::enabled()
224    }
225}
226
227pub mod fips {
228    //! # FIPS support
229    //!
230    //! To use rustls with OpenSSL in FIPS mode, perform the following actions.
231    //!
232    //! ## 1. Enable the `fips` feature
233    //!
234    //! This removes non-FIPS-approved cipher suites and key exchanges.
235    //!
236    //! ## 2. Specify `require_ems` when constructing [rustls::ClientConfig] or [rustls::ServerConfig]
237    //!
238    //! See [rustls documentation](https://docs.rs/rustls/latest/rustls/client/struct.ClientConfig.html#structfield.require_ems) for rationale.
239    //!
240    //! ## 3. Enable FIPS mode for OpenSSL
241    //!
242    //! See [enable()].
243    //!
244    //! ## 4. Validate the FIPS status of your ClientConfig or ServerConfig at runtime
245    //! See [rustls documenation on FIPS](https://docs.rs/rustls/latest/rustls/manual/_06_fips/index.html#3-validate-the-fips-status-of-your-clientconfigserverconfig-at-run-time).
246
247    /// Returns `true` if OpenSSL is running in FIPS mode.
248    #[cfg(fips_module)]
249    pub(crate) fn enabled() -> bool {
250        openssl::fips::enabled()
251    }
252    #[cfg(not(fips_module))]
253    pub(crate) fn enabled() -> bool {
254        unsafe { openssl_sys::EVP_default_properties_is_fips_enabled(std::ptr::null_mut()) == 1 }
255    }
256
257    /// Enable FIPS mode for OpenSSL.
258    ///
259    /// This should be called on application startup before the provider is used.
260    ///
261    /// On OpenSSL 1.1.1 this calls [FIPS_mode_set](https://wiki.openssl.org/index.php/FIPS_mode_set()).
262    /// On OpenSSL 3 this loads a FIPS provider, which must be available.
263    ///
264    /// Panics if FIPS cannot be enabled
265    #[cfg(fips_module)]
266    pub fn enable() {
267        openssl::fips::enable(true).expect("Failed to enable FIPS mode.");
268    }
269
270    /// Enable FIPS mode for OpenSSL.
271    ///
272    /// This should be called on application startup before the provider is used.
273    ///
274    /// On OpenSSL 1.1.1 this calls [FIPS_mode_set](https://wiki.openssl.org/index.php/FIPS_mode_set()).
275    /// On OpenSSL 3 this loads a FIPS provider, which must be available.
276    ///
277    /// Panics if FIPS cannot be enabled
278    #[cfg(not(fips_module))]
279    pub fn enable() {
280        // Use OnceCell to ensure that the provider is only loaded once
281        use once_cell::sync::OnceCell;
282
283        use crate::openssl_internal;
284        static PROVIDER: OnceCell<openssl::provider::Provider> = OnceCell::new();
285        PROVIDER.get_or_init(|| {
286            let provider = openssl::provider::Provider::load(None, "fips")
287                .expect("Failed to load FIPS provider.");
288            unsafe {
289                openssl_internal::cvt(openssl_sys::EVP_default_properties_enable_fips(
290                    std::ptr::null_mut(),
291                    1,
292                ))
293                .expect("Failed to enable FIPS properties.");
294            }
295            provider
296        });
297    }
298}