boring_rustls_provider/
lib.rs1use std::sync::Arc;
29
30use helper::log_and_map;
31#[cfg(all(feature = "fips", feature = "log"))]
32use log::warn;
33use rustls::{
34 SupportedCipherSuite,
35 crypto::{CryptoProvider, GetRandomFailed, SupportedKxGroup},
36};
37use rustls_pki_types::PrivateKeyDer;
38
39mod aead;
40mod hash;
41mod helper;
42mod hkdf;
43mod hmac;
44mod kx;
45#[cfg(feature = "tls12")]
46mod prf;
47pub mod sign;
49#[cfg(feature = "tls12")]
51pub mod tls12;
52pub mod tls13;
54pub mod verify;
56
57pub fn provider() -> CryptoProvider {
64 #[cfg(feature = "fips")]
65 {
66 if !boring::fips::enabled() {
67 panic!(
68 "boring-rustls-provider is built with the 'fips' feature, but the underlying \
69 BoringSSL library is not in FIPS mode."
70 );
71 }
72 provider_with_ciphers(ALL_FIPS_CIPHER_SUITES.to_vec())
73 }
74 #[cfg(not(feature = "fips"))]
75 {
76 provider_with_ciphers(ALL_CIPHER_SUITES.to_vec())
77 }
78}
79
80pub fn provider_with_ciphers(ciphers: Vec<rustls::SupportedCipherSuite>) -> CryptoProvider {
85 #[cfg(feature = "fips")]
86 let ciphers = {
87 let original_len = ciphers.len();
88 let filtered = ciphers
89 .into_iter()
90 .filter(|suite| ALL_FIPS_CIPHER_SUITES.contains(suite))
91 .collect::<Vec<_>>();
92
93 if filtered.len() != original_len {
94 #[cfg(feature = "log")]
95 warn!(
96 "filtered {} non-FIPS cipher suite(s) from provider_with_ciphers",
97 original_len - filtered.len()
98 );
99 }
100
101 filtered
102 };
103
104 CryptoProvider {
105 cipher_suites: ciphers,
106 #[cfg(feature = "fips")]
107 kx_groups: ALL_FIPS_KX_GROUPS.to_vec(),
108 #[cfg(not(feature = "fips"))]
109 kx_groups: ALL_KX_GROUPS.to_vec(),
110 #[cfg(feature = "fips")]
111 signature_verification_algorithms: verify::ALL_FIPS_ALGORITHMS,
112 #[cfg(not(feature = "fips"))]
113 signature_verification_algorithms: verify::ALL_ALGORITHMS,
114 secure_random: &Provider,
115 key_provider: &Provider,
116 }
117}
118
119#[derive(Debug)]
120struct Provider;
121
122impl rustls::crypto::SecureRandom for Provider {
123 fn fill(&self, bytes: &mut [u8]) -> Result<(), rustls::crypto::GetRandomFailed> {
124 boring::rand::rand_bytes(bytes).map_err(|e| log_and_map("rand_bytes", e, GetRandomFailed))
125 }
126
127 fn fips(&self) -> bool {
128 cfg!(feature = "fips")
129 }
130}
131
132impl rustls::crypto::KeyProvider for Provider {
133 fn load_private_key(
134 &self,
135 key_der: PrivateKeyDer<'static>,
136 ) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
137 sign::BoringPrivateKey::try_from(key_der).map(|x| Arc::new(x) as _)
138 }
139
140 fn fips(&self) -> bool {
141 cfg!(feature = "fips")
142 }
143}
144
145#[cfg(feature = "fips")]
146static ALL_FIPS_CIPHER_SUITES: &[SupportedCipherSuite] = &[
147 SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
148 SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
149 #[cfg(feature = "tls12")]
150 SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
151 #[cfg(feature = "tls12")]
152 SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
153 #[cfg(feature = "tls12")]
154 SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
155 #[cfg(feature = "tls12")]
156 SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
157];
158
159#[cfg(not(feature = "fips"))]
160static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
161 SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
162 SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
163 SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
164 #[cfg(feature = "tls12")]
165 SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
166 #[cfg(feature = "tls12")]
167 SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
168 #[cfg(feature = "tls12")]
169 SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
170 #[cfg(feature = "tls12")]
171 SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
172 #[cfg(feature = "tls12")]
173 SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
174 #[cfg(feature = "tls12")]
175 SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
176];
177
178#[cfg(feature = "fips")]
184static ALL_FIPS_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
185 &kx::X25519MlKem768 as _, &kx::Secp256r1 as _, &kx::Secp384r1 as _, ];
189
190#[cfg(all(not(feature = "fips"), feature = "mlkem"))]
195static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
196 &kx::X25519MlKem768 as _, &kx::X25519 as _,
198 &kx::Secp256r1 as _,
199 &kx::Secp384r1 as _,
200];
201
202#[cfg(not(any(feature = "fips", feature = "mlkem")))]
204static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] =
205 &[&kx::X25519 as _, &kx::Secp256r1 as _, &kx::Secp384r1 as _];