|
52 | 52 | //!
|
53 | 53 | //! # Features
|
54 | 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. |
56 |
| -//! |
57 |
| -//! # FIPS |
58 |
| -//! |
59 |
| -//! To use rustls with OpenSSL in FIPS mode, perform the following actions. |
60 |
| -//! |
61 |
| -//! ## 1. Enable the FIPS feature |
62 |
| -//! |
63 |
| -//! This removes non-FIPS-approved cipher suites and key exchanges. |
64 |
| -//! |
65 |
| -//! ## 2. Specify `require_ems` when constructing [rustls::ClientConfig] or [rustls::ServerConfig] |
66 |
| -//! |
67 |
| -//! See [rustls documentation](https://docs.rs/rustls/latest/rustls/client/struct.ClientConfig.html#structfield.require_ems) for rationale. |
68 |
| -//! |
69 |
| -//! ## 3. Enable FIPS mode for OpenSSL |
70 |
| -//! |
71 |
| -//! [enable_fips()] can be used to enable FIPS mode for OpenSSL without users needing to depend on the [openssl] crate directly. |
72 |
| -//! This calls [openssl::fips::enable](https://github.com/sfackler/rust-openssl/blob/538a5cb737e8d83085553cac01643820dc7ff205/openssl/src/fips.rs#L12), panicking if that fails. |
73 |
| -
|
74 |
| -//! ## 4. Validate the FIPS status of your ClientConfig or ServerConfig at runtime |
75 |
| -//! 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). |
| 55 | +//! - `fips`: Enabling this feature removes non-FIPS-approved cipher suites and key exchanges. Disabled by default. See [fips]. |
76 | 56 | #![warn(missing_docs)]
|
77 |
| - |
78 |
| -use openssl::rand::rand_bytes; |
| 57 | +use openssl::error::ErrorStack; |
| 58 | +use openssl::rand::rand_priv_bytes; |
| 59 | +use openssl_sys::c_int; |
79 | 60 | use rustls::crypto::{CryptoProvider, GetRandomFailed, SupportedKxGroup};
|
80 | 61 | use rustls::SupportedCipherSuite;
|
81 | 62 |
|
@@ -238,28 +219,89 @@ pub struct SecureRandom;
|
238 | 219 |
|
239 | 220 | impl rustls::crypto::SecureRandom for SecureRandom {
|
240 | 221 | fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
|
241 |
| - rand_bytes(buf).map_err(|_| GetRandomFailed) |
| 222 | + rand_priv_bytes(buf).map_err(|_| GetRandomFailed) |
242 | 223 | }
|
243 | 224 |
|
244 | 225 | fn fips(&self) -> bool {
|
245 |
| - fips() |
| 226 | + fips::enabled() |
246 | 227 | }
|
247 | 228 | }
|
248 | 229 |
|
249 |
| -/// Returns `true` if OpenSSL is running in FIPS mode. |
250 |
| -#[cfg(fips_module)] |
251 |
| -pub(crate) fn fips() -> bool { |
252 |
| - openssl::fips::enabled() |
253 |
| -} |
254 |
| -#[cfg(not(fips_module))] |
255 |
| -pub(crate) fn fips() -> bool { |
256 |
| - false |
| 230 | +pub(crate) fn cvt(r: c_int) -> Result<i32, ErrorStack> { |
| 231 | + if r <= 0 { |
| 232 | + Err(ErrorStack::get()) |
| 233 | + } else { |
| 234 | + Ok(r) |
| 235 | + } |
257 | 236 | }
|
258 | 237 |
|
259 |
| -/// Enable FIPS mode for OpenSSL. |
260 |
| -/// |
261 |
| -/// Panics if FIPS mode cannot be enabled. |
262 |
| -#[cfg(all(fips_module, feature = "fips"))] |
263 |
| -pub fn enable_fips() { |
264 |
| - openssl::fips::enable(true).expect("Failed to enable FIPS mode."); |
| 238 | +pub mod fips { |
| 239 | + //! # FIPS support |
| 240 | + //! |
| 241 | + //! To use rustls with OpenSSL in FIPS mode, perform the following actions. |
| 242 | + //! |
| 243 | + //! ## 1. Enable the `fips` feature |
| 244 | + //! |
| 245 | + //! This removes non-FIPS-approved cipher suites and key exchanges. |
| 246 | + //! |
| 247 | + //! ## 2. Specify `require_ems` when constructing [rustls::ClientConfig] or [rustls::ServerConfig] |
| 248 | + //! |
| 249 | + //! See [rustls documentation](https://docs.rs/rustls/latest/rustls/client/struct.ClientConfig.html#structfield.require_ems) for rationale. |
| 250 | + //! |
| 251 | + //! ## 3. Enable FIPS mode for OpenSSL |
| 252 | + //! |
| 253 | + //! See [enable()]. |
| 254 | + //! |
| 255 | + //! ## 4. Validate the FIPS status of your ClientConfig or ServerConfig at runtime |
| 256 | + //! 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). |
| 257 | +
|
| 258 | + /// Returns `true` if OpenSSL is running in FIPS mode. |
| 259 | + #[cfg(fips_module)] |
| 260 | + pub(crate) fn enabled() -> bool { |
| 261 | + openssl::fips::enabled() |
| 262 | + } |
| 263 | + #[cfg(not(fips_module))] |
| 264 | + pub(crate) fn enabled() -> bool { |
| 265 | + unsafe { openssl_sys::EVP_default_properties_is_fips_enabled(std::ptr::null_mut()) == 1 } |
| 266 | + } |
| 267 | + |
| 268 | + /// Enable FIPS mode for OpenSSL. |
| 269 | + /// |
| 270 | + /// This should be called on application startup before the provider is used. |
| 271 | + /// |
| 272 | + /// On OpenSSL 1.1.1 this calls [FIPS_mode_set](https://wiki.openssl.org/index.php/FIPS_mode_set()). |
| 273 | + /// On OpenSSL 3 this loads a FIPS provider, which must be available. |
| 274 | + /// |
| 275 | + /// Panics if FIPS cannot be enabled |
| 276 | + #[cfg(fips_module)] |
| 277 | + pub fn enable() { |
| 278 | + openssl::fips::enable(true).expect("Failed to enable FIPS mode."); |
| 279 | + } |
| 280 | + |
| 281 | + /// Enable FIPS mode for OpenSSL. |
| 282 | + /// |
| 283 | + /// This should be called on application startup before the provider is used. |
| 284 | + /// |
| 285 | + /// On OpenSSL 1.1.1 this calls [FIPS_mode_set](https://wiki.openssl.org/index.php/FIPS_mode_set()). |
| 286 | + /// On OpenSSL 3 this loads a FIPS provider, which must be available. |
| 287 | + /// |
| 288 | + /// Panics if FIPS cannot be enabled |
| 289 | + #[cfg(not(fips_module))] |
| 290 | + pub fn enable() { |
| 291 | + // Use OnceCell to ensure that the provider is only loaded once |
| 292 | + use once_cell::sync::OnceCell; |
| 293 | + static PROVIDER: OnceCell<openssl::provider::Provider> = OnceCell::new(); |
| 294 | + PROVIDER.get_or_init(|| { |
| 295 | + let provider = openssl::provider::Provider::load(None, "fips") |
| 296 | + .expect("Failed to load FIPS provider."); |
| 297 | + unsafe { |
| 298 | + crate::cvt(openssl_sys::EVP_default_properties_enable_fips( |
| 299 | + std::ptr::null_mut(), |
| 300 | + 1, |
| 301 | + )) |
| 302 | + .expect("Failed to enable FIPS properties."); |
| 303 | + } |
| 304 | + provider |
| 305 | + }); |
| 306 | + } |
265 | 307 | }
|
0 commit comments