Add 'fips' Cargo feature

Add `rustls::crypto::default_fips_provider()` behind this
feature.
This commit is contained in:
Sean McGrail 2024-01-04 17:45:14 +00:00 committed by Joseph Birr-Pixton
parent e1149286ff
commit d805e1fdfd
12 changed files with 228 additions and 61 deletions

View File

@ -46,8 +46,10 @@ jobs:
- name: cargo build (debug; default features) - name: cargo build (debug; default features)
run: cargo build --locked run: cargo build --locked
- name: cargo test (debug; all features) # nb. feature sets that include "fips" should be --release --
run: cargo test --locked --all-features # this is required for fips on windows.
- name: cargo test (release; all features)
run: cargo test --release --locked --all-features
env: env:
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
@ -56,6 +58,11 @@ jobs:
env: env:
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
- name: cargo test (release; fips)
run: cargo test --release --no-default-features --features fips,tls12,read_buf,logging
env:
RUST_BACKTRACE: 1
- name: cargo build (debug; rustls-provider-example) - name: cargo build (debug; rustls-provider-example)
run: cargo build --locked -p rustls-provider-example run: cargo build --locked -p rustls-provider-example
@ -111,6 +118,10 @@ jobs:
run: cargo test --no-default-features --features aws_lc_rs,tls12 run: cargo test --no-default-features --features aws_lc_rs,tls12
working-directory: rustls working-directory: rustls
- name: cargo test (debug; no default features; fips,tls12)
run: cargo test --no-default-features --features fips,tls12
working-directory: rustls
- name: cargo test (release; no run) - name: cargo test (release; no run)
run: cargo test --locked --release --no-run run: cargo test --locked --release --no-run
working-directory: rustls working-directory: rustls
@ -186,6 +197,9 @@ jobs:
- name: Smoke-test benchmark program (aws-lc-rs) - name: Smoke-test benchmark program (aws-lc-rs)
run: cargo run -p rustls --release --locked --example bench --no-default-features --features aws_lc_rs,tls12 run: cargo run -p rustls --release --locked --example bench --no-default-features --features aws_lc_rs,tls12
- name: Smoke-test benchmark program (fips)
run: cargo run -p rustls --release --locked --example bench --no-default-features --features fips,tls12
- name: Run micro-benchmarks - name: Run micro-benchmarks
run: cargo bench --locked --all-features run: cargo bench --locked --all-features
env: env:

40
Cargo.lock generated
View File

@ -293,12 +293,27 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "aws-lc-fips-sys"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f56794bd674ee9f3d8de0e1d378ee44c72beb3506e5b747f89a632eb39adba1"
dependencies = [
"bindgen 0.69.1",
"cmake",
"dunce",
"fs_extra",
"libc",
"paste",
]
[[package]] [[package]]
name = "aws-lc-rs" name = "aws-lc-rs"
version = "1.5.2" version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bc2aa0a35a53d7cfda07a69f74d67a918ced3ec1a607f5bce5da7c3aff6bab7" checksum = "7bc2aa0a35a53d7cfda07a69f74d67a918ced3ec1a607f5bce5da7c3aff6bab7"
dependencies = [ dependencies = [
"aws-lc-fips-sys",
"aws-lc-sys", "aws-lc-sys",
"mirai-annotations", "mirai-annotations",
"untrusted 0.7.1", "untrusted 0.7.1",
@ -311,7 +326,7 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2c6f9497a1bd3bed0a28a01b8836dbe9c7a2c521e47a14b165c64c4df592331" checksum = "c2c6f9497a1bd3bed0a28a01b8836dbe9c7a2c521e47a14b165c64c4df592331"
dependencies = [ dependencies = [
"bindgen", "bindgen 0.68.1",
"cmake", "cmake",
"dunce", "dunce",
"fs_extra", "fs_extra",
@ -381,6 +396,29 @@ dependencies = [
"which", "which",
] ]
[[package]]
name = "bindgen"
version = "0.69.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2"
dependencies = [
"bitflags 2.4.1",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.46",
"which",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"

View File

@ -31,6 +31,7 @@ aws_lc_rs = ["dep:aws-lc-rs", "webpki/aws_lc_rs"]
ring = ["dep:ring", "webpki/ring"] ring = ["dep:ring", "webpki/ring"]
tls12 = [] tls12 = []
read_buf = ["rustversion"] read_buf = ["rustversion"]
fips = ["aws_lc_rs", "aws-lc-rs?/fips"]
[dev-dependencies] [dev-dependencies]
base64 = "0.21" base64 = "0.21"

View File

@ -173,13 +173,13 @@ impl BenchmarkParam {
} }
static ALL_BENCHMARKS: &[BenchmarkParam] = &[ static ALL_BENCHMARKS: &[BenchmarkParam] = &[
#[cfg(feature = "tls12")] #[cfg(all(feature = "tls12", not(feature = "fips")))]
BenchmarkParam::new( BenchmarkParam::new(
KeyType::Rsa, KeyType::Rsa,
cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
&rustls::version::TLS12, &rustls::version::TLS12,
), ),
#[cfg(feature = "tls12")] #[cfg(all(feature = "tls12", not(feature = "fips")))]
BenchmarkParam::new( BenchmarkParam::new(
KeyType::EcdsaP256, KeyType::EcdsaP256,
cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
@ -209,6 +209,7 @@ static ALL_BENCHMARKS: &[BenchmarkParam] = &[
cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
&rustls::version::TLS12, &rustls::version::TLS12,
), ),
#[cfg(not(feature = "fips"))]
BenchmarkParam::new( BenchmarkParam::new(
KeyType::Rsa, KeyType::Rsa,
cipher_suite::TLS13_CHACHA20_POLY1305_SHA256, cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,

View File

@ -1,6 +1,8 @@
use crate::builder::ConfigBuilder; use crate::builder::ConfigBuilder;
use crate::common_state::{CommonState, Protocol, Side}; use crate::common_state::{CommonState, Protocol, Side};
use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon}; use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon};
#[cfg(any(feature = "ring", feature = "fips"))]
use crate::crypto::default_provider;
use crate::crypto::{CryptoProvider, SupportedKxGroup}; use crate::crypto::{CryptoProvider, SupportedKxGroup};
use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme}; use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
use crate::error::Error; use crate::error::Error;
@ -14,7 +16,7 @@ use crate::suites::{ExtractedSecrets, SupportedCipherSuite};
use crate::unbuffered::{EncryptError, TransmitTlsData}; use crate::unbuffered::{EncryptError, TransmitTlsData};
use crate::versions; use crate::versions;
use crate::KeyLog; use crate::KeyLog;
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
use crate::WantsVerifier; use crate::WantsVerifier;
use crate::{verify, WantsVersions}; use crate::{verify, WantsVersions};
@ -206,31 +208,40 @@ pub struct ClientConfig {
impl ClientConfig { impl ClientConfig {
/// Create a builder for a client configuration with the default /// Create a builder for a client configuration with the default
/// [`CryptoProvider`]: [`crypto::ring::default_provider`] and safe ciphersuite and /// [`CryptoProvider`].
/// protocol defaults. ///
/// This is:
///
/// - [`crypto::aws_lc_rs::default_provider`] if the `fips` crate feature is
/// enabled.
/// - [`crypto::ring::default_provider`] if the `ring` crate feature is
/// enabled and the `fips` crate feature is not enabled.
///
/// If neither of these are true, this function is not available and you
/// must use [`ClientConfig::builder_with_provider()`] instead.
/// ///
/// For more information, see the [`ConfigBuilder`] documentation. /// For more information, see the [`ConfigBuilder`] documentation.
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
pub fn builder() -> ConfigBuilder<Self, WantsVerifier> { pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
// Safety: we know the *ring* provider's ciphersuites are compatible with the safe default protocol versions. // Safety: we know the *ring* and aws-lc-rs providers' ciphersuites are compatible with the safe default protocol versions.
Self::builder_with_provider(crate::crypto::ring::default_provider().into()) Self::builder_with_provider(default_provider().into())
.with_safe_default_protocol_versions() .with_safe_default_protocol_versions()
.unwrap() .unwrap()
} }
/// Create a builder for a client configuration with the default /// Create a builder for a client configuration with the default
/// [`CryptoProvider`]: [`crypto::ring::default_provider`], safe ciphersuite defaults and /// [`CryptoProvider`] (see [`ClientConfig::builder()`] for details), safe
/// the provided protocol versions. /// ciphersuite defaults and the provided protocol versions.
/// ///
/// Panics if provided an empty slice of supported versions. /// Panics if provided an empty slice of supported versions.
/// ///
/// For more information, see the [`ConfigBuilder`] documentation. /// For more information, see the [`ConfigBuilder`] documentation.
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
pub fn builder_with_protocol_versions( pub fn builder_with_protocol_versions(
versions: &[&'static versions::SupportedProtocolVersion], versions: &[&'static versions::SupportedProtocolVersion],
) -> ConfigBuilder<Self, WantsVerifier> { ) -> ConfigBuilder<Self, WantsVerifier> {
// Safety: we know the *ring* provider's ciphersuites are compatible with all protocol version choices. // Safety: we know the *ring* and aws-lc-rs providers' ciphersuites are compatible with all protocol version choices.
Self::builder_with_provider(crate::crypto::ring::default_provider().into()) Self::builder_with_provider(default_provider().into())
.with_protocol_versions(versions) .with_protocol_versions(versions)
.unwrap() .unwrap()
} }

View File

@ -10,6 +10,7 @@ use pki_types::PrivateKeyDer;
use webpki::aws_lc_rs as webpki_algs; use webpki::aws_lc_rs as webpki_algs;
use alloc::sync::Arc; use alloc::sync::Arc;
use alloc::vec::Vec;
// aws-lc-rs has a -- roughly -- ring-compatible API, so we just reuse all that // aws-lc-rs has a -- roughly -- ring-compatible API, so we just reuse all that
// glue here. The shared files should always use `super::ring_like` to access a // glue here. The shared files should always use `super::ring_like` to access a
@ -35,23 +36,29 @@ pub(crate) mod tls13;
/// A `CryptoProvider` backed by aws-lc-rs. /// A `CryptoProvider` backed by aws-lc-rs.
pub fn default_provider() -> CryptoProvider { pub fn default_provider() -> CryptoProvider {
CryptoProvider { CryptoProvider {
// TODO: make this filtering conditional on fips feature cipher_suites: DEFAULT_CIPHER_SUITES.to_vec(),
cipher_suites: DEFAULT_CIPHER_SUITES kx_groups: default_kx_groups(),
.iter()
.filter(|cs| cs.fips())
.copied()
.collect(),
kx_groups: ALL_KX_GROUPS
.iter()
.filter(|kx| kx.fips())
.copied()
.collect(),
signature_verification_algorithms: SUPPORTED_SIG_ALGS, signature_verification_algorithms: SUPPORTED_SIG_ALGS,
secure_random: &AwsLcRs, secure_random: &AwsLcRs,
key_provider: &AwsLcRs, key_provider: &AwsLcRs,
} }
} }
fn default_kx_groups() -> Vec<&'static dyn SupportedKxGroup> {
#[cfg(feature = "fips")]
{
ALL_KX_GROUPS
.iter()
.filter(|cs| cs.fips())
.copied()
.collect()
}
#[cfg(not(feature = "fips"))]
{
ALL_KX_GROUPS.to_vec()
}
}
#[derive(Debug)] #[derive(Debug)]
struct AwsLcRs; struct AwsLcRs;
@ -86,7 +93,26 @@ impl KeyProvider for AwsLcRs {
/// ///
/// This will be [`ALL_CIPHER_SUITES`] sans any supported cipher suites that /// This will be [`ALL_CIPHER_SUITES`] sans any supported cipher suites that
/// shouldn't be enabled by most applications. /// shouldn't be enabled by most applications.
pub static DEFAULT_CIPHER_SUITES: &[SupportedCipherSuite] = ALL_CIPHER_SUITES; pub static DEFAULT_CIPHER_SUITES: &[SupportedCipherSuite] = &[
// TLS1.3 suites
tls13::TLS13_AES_256_GCM_SHA384,
tls13::TLS13_AES_128_GCM_SHA256,
#[cfg(not(feature = "fips"))]
tls13::TLS13_CHACHA20_POLY1305_SHA256,
// TLS1.2 suites
#[cfg(feature = "tls12")]
tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
#[cfg(feature = "tls12")]
tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
#[cfg(all(feature = "tls12", not(feature = "fips")))]
tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
#[cfg(feature = "tls12")]
tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
#[cfg(feature = "tls12")]
tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
#[cfg(all(feature = "tls12", not(feature = "fips")))]
tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
];
/// A list of all the cipher suites supported by the rustls *ring* provider. /// A list of all the cipher suites supported by the rustls *ring* provider.
pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[ pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
@ -200,6 +226,8 @@ pub mod kx_group {
pub use kx::ALL_KX_GROUPS; pub use kx::ALL_KX_GROUPS;
pub use ticketer::Ticketer; pub use ticketer::Ticketer;
use super::SupportedKxGroup;
/// Compatibility shims between ring 0.16.x and 0.17.x API /// Compatibility shims between ring 0.16.x and 0.17.x API
mod ring_shim { mod ring_shim {
use super::ring_like; use super::ring_like;

View File

@ -69,7 +69,7 @@ pub use crate::msgs::handshake::KeyExchangeAlgorithm;
/// crate. /// crate.
/// - [`crypto::aws_lc_rs::default_provider`]: (behind the `aws_lc_rs` feature, /// - [`crypto::aws_lc_rs::default_provider`]: (behind the `aws_lc_rs` feature,
/// which is optional). This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs) /// which is optional). This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs)
/// crate. /// crate. The `fips` crate feature makes this option use FIPS140-3-approved cryptography.
/// ///
/// This structure provides defaults. Everything in it can be overridden at /// This structure provides defaults. Everything in it can be overridden at
/// runtime by replacing field values as needed. /// runtime by replacing field values as needed.
@ -153,6 +153,12 @@ pub use crate::msgs::handshake::KeyExchangeAlgorithm;
/// [provider-example/]: https://github.com/rustls/rustls/tree/main/provider-example/ /// [provider-example/]: https://github.com/rustls/rustls/tree/main/provider-example/
/// [rust-crypto]: https://github.com/rustcrypto /// [rust-crypto]: https://github.com/rustcrypto
/// [dalek-cryptography]: https://github.com/dalek-cryptography /// [dalek-cryptography]: https://github.com/dalek-cryptography
///
/// # FIPS-approved cryptography
/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
///
/// You can verify the configuration at runtime by checking
/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CryptoProvider { pub struct CryptoProvider {
/// List of supported ciphersuites, in preference order -- the first element /// List of supported ciphersuites, in preference order -- the first element
@ -329,3 +335,41 @@ impl From<&[u8]> for SharedSecret {
Self(source.to_vec()) Self(source.to_vec())
} }
} }
#[cfg(any(feature = "ring", feature = "fips"))]
pub(crate) fn default_provider() -> CryptoProvider {
#[cfg(all(feature = "ring", not(feature = "fips")))]
{
crate::crypto::ring::default_provider()
}
#[cfg(feature = "fips")]
{
crate::crypto::aws_lc_rs::default_provider()
}
}
/// This function returns a [`CryptoProvider`] that uses
/// FIPS140-3-approved cryptography.
///
/// You can use this like:
///
/// ```rust
/// # #[cfg(feature = "fips")] {
/// # let root_store = rustls::RootCertStore::empty();
/// let config = rustls::ClientConfig::builder_with_provider(
/// rustls::crypto::default_fips_provider().into()
/// )
/// .with_safe_default_protocol_versions()
/// .unwrap()
/// .with_root_certificates(root_store)
/// .with_no_client_auth();
/// # }
/// ```
///
/// This expresses in your code that you require FIPS-approved
/// cryptography, and will not compile if you make a mistake
/// with cargo features.
#[cfg(feature = "fips")]
pub fn default_fips_provider() -> CryptoProvider {
crate::crypto::aws_lc_rs::default_provider()
}

View File

@ -78,13 +78,11 @@ pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls12::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
#[cfg(feature = "tls12")] #[cfg(feature = "tls12")]
tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls12::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
#[cfg(feature = "tls12")]
tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, tls12::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
#[cfg(feature = "tls12")] #[cfg(feature = "tls12")]
tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls12::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
#[cfg(feature = "tls12")] #[cfg(feature = "tls12")]
tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls12::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
#[cfg(feature = "tls12")]
tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
]; ];

View File

@ -266,6 +266,10 @@
//! Note that aws-lc-rs has additional build-time dependencies like cmake. //! Note that aws-lc-rs has additional build-time dependencies like cmake.
//! See [the documentation](https://aws.github.io/aws-lc-rs/requirements/index.html) for details. //! See [the documentation](https://aws.github.io/aws-lc-rs/requirements/index.html) for details.
//! //!
//! - `fips`: enable support for FIPS140-3-approved cryptography, via the aws-lc-rs crate.
//! This feature enables the `aws_lc_rs` feature, which makes the rustls crate depend
//! on [aws-lc-rs](https://github.com/aws/aws-lc-rs).
//!
//! - `tls12` (enabled by default): enable support for TLS version 1.2. Note that, due to the //! - `tls12` (enabled by default): enable support for TLS version 1.2. Note that, due to the
//! additive nature of Cargo features and because it is enabled by default, other crates //! additive nature of Cargo features and because it is enabled by default, other crates
//! in your dependency graph could re-enable it for your application. If you want to disable //! in your dependency graph could re-enable it for your application. If you want to disable

View File

@ -1,6 +1,8 @@
use crate::builder::ConfigBuilder; use crate::builder::ConfigBuilder;
use crate::common_state::{CommonState, Context, Protocol, Side, State}; use crate::common_state::{CommonState, Context, Protocol, Side, State};
use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon}; use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon};
#[cfg(any(feature = "ring", feature = "fips"))]
use crate::crypto::default_provider;
use crate::crypto::CryptoProvider; use crate::crypto::CryptoProvider;
use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme}; use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
use crate::error::Error; use crate::error::Error;
@ -12,10 +14,10 @@ use crate::msgs::message::Message;
use crate::suites::ExtractedSecrets; use crate::suites::ExtractedSecrets;
use crate::vecbuf::ChunkVecBuffer; use crate::vecbuf::ChunkVecBuffer;
use crate::verify; use crate::verify;
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
use crate::versions; use crate::versions;
use crate::KeyLog; use crate::KeyLog;
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
use crate::WantsVerifier; use crate::WantsVerifier;
use crate::{sign, WantsVersions}; use crate::{sign, WantsVersions};
@ -341,31 +343,40 @@ impl Clone for ServerConfig {
impl ServerConfig { impl ServerConfig {
/// Create a builder for a server configuration with the default /// Create a builder for a server configuration with the default
/// [`CryptoProvider`]: [`crypto::ring::default_provider`] and safe ciphersuite and protocol /// [`CryptoProvider`].
/// defaults. ///
/// This is:
///
/// - [`crypto::aws_lc_rs::default_provider`] if the `fips` crate feature is
/// enabled.
/// - [`crypto::ring::default_provider`] if the `ring` crate feature is
/// enabled and the `fips` crate feature is not enabled.
///
/// If neither of these are true, this function is not available and you
/// must use [`ServerConfig::builder_with_provider()`] instead.
/// ///
/// For more information, see the [`ConfigBuilder`] documentation. /// For more information, see the [`ConfigBuilder`] documentation.
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
pub fn builder() -> ConfigBuilder<Self, WantsVerifier> { pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
// Safety: we know the *ring* provider's ciphersuites are compatible with the safe default protocol versions. // Safety: we know the *ring* and aws-lc-rs providers' ciphersuites are compatible with the safe default protocol versions.
Self::builder_with_provider(crate::crypto::ring::default_provider().into()) Self::builder_with_provider(default_provider().into())
.with_safe_default_protocol_versions() .with_safe_default_protocol_versions()
.unwrap() .unwrap()
} }
/// Create a builder for a server configuration with the default /// Create a builder for a server configuration with the default
/// [`CryptoProvider`]: [`crypto::ring::default_provider`], safe ciphersuite defaults and /// [`CryptoProvider`] (see [`ServerConfig::builder()`] for details), safe
/// the provided protocol versions. /// ciphersuite defaults and the provided protocol versions.
/// ///
/// Panics if provided an empty slice of supported versions. /// Panics if provided an empty slice of supported versions.
/// ///
/// For more information, see the [`ConfigBuilder`] documentation. /// For more information, see the [`ConfigBuilder`] documentation.
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
pub fn builder_with_protocol_versions( pub fn builder_with_protocol_versions(
versions: &[&'static versions::SupportedProtocolVersion], versions: &[&'static versions::SupportedProtocolVersion],
) -> ConfigBuilder<Self, WantsVerifier> { ) -> ConfigBuilder<Self, WantsVerifier> {
// Safety: we know the *ring* provider's ciphersuites are compatible with all protocol version choices. // Safety: we know the *ring* and aws-lc-rs providers' ciphersuites are compatible with all protocol version choices.
Self::builder_with_provider(crate::crypto::ring::default_provider().into()) Self::builder_with_provider(default_provider().into())
.with_protocol_versions(versions) .with_protocol_versions(versions)
.unwrap() .unwrap()
} }

View File

@ -473,7 +473,7 @@ fn server_can_get_client_cert_after_resumption() {
} }
#[test] #[test]
#[cfg(feature = "ring")] #[cfg(all(feature = "ring", not(feature = "fips")))]
fn test_config_builders_debug() { fn test_config_builders_debug() {
let b = ServerConfig::builder_with_provider( let b = ServerConfig::builder_with_provider(
CryptoProvider { CryptoProvider {
@ -961,7 +961,7 @@ fn check_sigalgs_reduced_by_ciphersuite(
fn server_cert_resolve_reduces_sigalgs_for_rsa_ciphersuite() { fn server_cert_resolve_reduces_sigalgs_for_rsa_ciphersuite() {
check_sigalgs_reduced_by_ciphersuite( check_sigalgs_reduced_by_ciphersuite(
KeyType::Rsa, KeyType::Rsa,
CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
vec![ vec![
SignatureScheme::RSA_PSS_SHA512, SignatureScheme::RSA_PSS_SHA512,
SignatureScheme::RSA_PSS_SHA384, SignatureScheme::RSA_PSS_SHA384,
@ -978,9 +978,9 @@ fn server_cert_resolve_reduces_sigalgs_for_rsa_ciphersuite() {
fn server_cert_resolve_reduces_sigalgs_for_ecdsa_ciphersuite() { fn server_cert_resolve_reduces_sigalgs_for_ecdsa_ciphersuite() {
check_sigalgs_reduced_by_ciphersuite( check_sigalgs_reduced_by_ciphersuite(
KeyType::EcdsaP256, KeyType::EcdsaP256,
CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
vec![ vec![
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] #[cfg(any(feature = "fips", all(not(feature = "ring"), feature = "aws_lc_rs")))]
SignatureScheme::ECDSA_NISTP521_SHA512, SignatureScheme::ECDSA_NISTP521_SHA512,
SignatureScheme::ECDSA_NISTP384_SHA384, SignatureScheme::ECDSA_NISTP384_SHA384,
SignatureScheme::ECDSA_NISTP256_SHA256, SignatureScheme::ECDSA_NISTP256_SHA256,
@ -2891,6 +2891,7 @@ fn find_suite(suite: CipherSuite) -> SupportedCipherSuite {
} }
static TEST_CIPHERSUITES: &[(&rustls::SupportedProtocolVersion, KeyType, CipherSuite)] = &[ static TEST_CIPHERSUITES: &[(&rustls::SupportedProtocolVersion, KeyType, CipherSuite)] = &[
#[cfg(not(feature = "fips"))]
( (
&rustls::version::TLS13, &rustls::version::TLS13,
KeyType::Rsa, KeyType::Rsa,
@ -2906,13 +2907,13 @@ static TEST_CIPHERSUITES: &[(&rustls::SupportedProtocolVersion, KeyType, CipherS
KeyType::Rsa, KeyType::Rsa,
CipherSuite::TLS13_AES_128_GCM_SHA256, CipherSuite::TLS13_AES_128_GCM_SHA256,
), ),
#[cfg(feature = "tls12")] #[cfg(all(feature = "tls12", not(feature = "fips")))]
( (
&rustls::version::TLS12, &rustls::version::TLS12,
KeyType::EcdsaP256, KeyType::EcdsaP256,
CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
), ),
#[cfg(feature = "tls12")] #[cfg(all(feature = "tls12", not(feature = "fips")))]
( (
&rustls::version::TLS12, &rustls::version::TLS12,
KeyType::Rsa, KeyType::Rsa,
@ -2958,7 +2959,10 @@ fn negotiated_ciphersuite_default() {
#[test] #[test]
fn all_suites_covered() { fn all_suites_covered() {
assert_eq!(provider::ALL_CIPHER_SUITES.len(), TEST_CIPHERSUITES.len()); assert_eq!(
provider::DEFAULT_CIPHER_SUITES.len(),
TEST_CIPHERSUITES.len()
);
} }
#[test] #[test]
@ -5299,9 +5303,11 @@ fn test_secret_extraction_enabled() {
for suite in [ for suite in [
cipher_suite::TLS13_AES_128_GCM_SHA256, cipher_suite::TLS13_AES_128_GCM_SHA256,
cipher_suite::TLS13_AES_256_GCM_SHA384, cipher_suite::TLS13_AES_256_GCM_SHA384,
#[cfg(not(feature = "fips"))]
cipher_suite::TLS13_CHACHA20_POLY1305_SHA256, cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
#[cfg(not(feature = "fips"))]
cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
] { ] {
let version = suite.version(); let version = suite.version();
@ -5706,26 +5712,38 @@ fn test_client_removes_tls12_session_if_server_sends_undecryptable_first_message
)); ));
} }
#[cfg(feature = "ring")] #[cfg(all(feature = "ring", not(feature = "fips")))]
#[test] #[test]
fn test_client_fips_service_indicator() { fn test_client_fips_service_indicator() {
assert!(!make_client_config(KeyType::Rsa).fips()); assert!(!make_client_config(KeyType::Rsa).fips());
} }
#[cfg(feature = "ring")] #[cfg(all(feature = "ring", not(feature = "fips")))]
#[test] #[test]
fn test_server_fips_service_indicator() { fn test_server_fips_service_indicator() {
assert!(!make_server_config(KeyType::Rsa).fips()); assert!(!make_server_config(KeyType::Rsa).fips());
} }
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] #[cfg(feature = "fips")]
#[test] #[test]
fn test_client_fips_service_indicator() { fn test_client_fips_service_indicator() {
assert!(make_client_config(KeyType::Rsa).fips()); assert!(make_client_config(KeyType::Rsa).fips());
} }
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] #[cfg(feature = "fips")]
#[test] #[test]
fn test_server_fips_service_indicator() { fn test_server_fips_service_indicator() {
assert!(make_server_config(KeyType::Rsa).fips()); assert!(make_server_config(KeyType::Rsa).fips());
} }
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs", not(feature = "fips")))]
#[test]
fn test_client_fips_service_indicator() {
assert!(!make_client_config(KeyType::Rsa).fips());
}
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs", not(feature = "fips")))]
#[test]
fn test_server_fips_service_indicator() {
assert!(!make_server_config(KeyType::Rsa).fips());
}

View File

@ -18,9 +18,9 @@ use rustls::RootCertStore;
use rustls::{ClientConfig, ClientConnection}; use rustls::{ClientConfig, ClientConnection};
use rustls::{ConnectionCommon, ServerConfig, ServerConnection, SideData}; use rustls::{ConnectionCommon, ServerConfig, ServerConnection, SideData};
#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] #[cfg(all(any(not(feature = "ring"), feature = "fips"), feature = "aws_lc_rs"))]
pub use rustls::crypto::aws_lc_rs as provider; pub use rustls::crypto::aws_lc_rs as provider;
#[cfg(feature = "ring")] #[cfg(all(feature = "ring", not(feature = "fips")))]
pub use rustls::crypto::ring as provider; pub use rustls::crypto::ring as provider;
use rustls::crypto::CryptoProvider; use rustls::crypto::CryptoProvider;
@ -344,11 +344,11 @@ impl KeyType {
pub fn server_config_builder() -> rustls::ConfigBuilder<ServerConfig, rustls::WantsVerifier> { pub fn server_config_builder() -> rustls::ConfigBuilder<ServerConfig, rustls::WantsVerifier> {
// ensure `ServerConfig::builder()` is covered, even though it is // ensure `ServerConfig::builder()` is covered, even though it is
// equivalent to `builder_with_provider(provider::provider().into())`. // equivalent to `builder_with_provider(provider::provider().into())`.
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
{ {
rustls::ServerConfig::builder() rustls::ServerConfig::builder()
} }
#[cfg(not(feature = "ring"))] #[cfg(all(not(feature = "ring"), not(feature = "fips")))]
{ {
rustls::ServerConfig::builder_with_provider(provider::default_provider().into()) rustls::ServerConfig::builder_with_provider(provider::default_provider().into())
.with_safe_default_protocol_versions() .with_safe_default_protocol_versions()
@ -374,12 +374,11 @@ pub fn server_config_builder_with_versions(
pub fn client_config_builder() -> rustls::ConfigBuilder<ClientConfig, rustls::WantsVerifier> { pub fn client_config_builder() -> rustls::ConfigBuilder<ClientConfig, rustls::WantsVerifier> {
// ensure `ClientConfig::builder()` is covered, even though it is // ensure `ClientConfig::builder()` is covered, even though it is
// equivalent to `builder_with_provider(provider::provider().into())`. // equivalent to `builder_with_provider(provider::provider().into())`.
#[cfg(feature = "ring")] #[cfg(any(feature = "ring", feature = "fips"))]
{ {
rustls::ClientConfig::builder() rustls::ClientConfig::builder()
} }
#[cfg(all(not(feature = "ring"), not(feature = "fips")))]
#[cfg(not(feature = "ring"))]
{ {
rustls::ClientConfig::builder_with_provider(provider::default_provider().into()) rustls::ClientConfig::builder_with_provider(provider::default_provider().into())
.with_safe_default_protocol_versions() .with_safe_default_protocol_versions()