rustls_cng_crypto/
lib.rs

1//! # rustls-cng-crypto
2//!
3//! A [rustls crypto provider](https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html) for Windows that uses CNG for crypto.
4//!
5//! ## Supported Ciphers
6//!
7//! Supported cipher suites are listed below, in descending order of preference.
8//!
9//! If the `tls12` feature is disabled then the TLS 1.2 cipher suites will not be available.
10//!
11//! ### TLS 1.3
12//!
13//! * `TLS13_AES_256_GCM_SHA384`
14//! * `TLS13_AES_128_GCM_SHA256`
15//! * `TLS13_CHACHA20_POLY1305_SHA256`
16//!
17//! ### TLS 1.2
18//!
19//! * `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`
20//! * `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`
21//! * `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256`
22//! * `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`
23//! * `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`
24//! * `TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256`
25//!
26//! ## Supported Key Exchanges
27//!
28//! In descending order of preference:
29//!
30//! * X25519
31//! * SECP256R1
32//! * SECP384R1
33//!
34//! ## Usage
35//!
36//! Add `rustls-cng-crypto` to your `Cargo.toml`:
37//!
38//! ```toml
39//! [dependencies]
40//! rustls = { version = "0.23.0", features = ["tls12", "std"], default-features = false }
41//! rustls_cng_crypto = "0.1.0"
42//! ```
43//!
44//! ### Configuration
45//!
46//! Use [`default_provider()`] to create a provider using cipher suites and key exchange groups listed above.
47//! Use [`custom_provider()`] to specify custom cipher suites and key exchange groups.
48//!
49//! # Features
50//! - `tls12`: Enables TLS 1.2 cipher suites. Enabled by default.
51//! - `fips`: Changes the default provider to use FIPS-approved cipher suites and key exchange groups. See [fips].
52#![warn(missing_docs)]
53use rustls::crypto::{CryptoProvider, GetRandomFailed, SupportedKxGroup};
54use rustls::SupportedCipherSuite;
55
56use windows::Win32::Security::Cryptography::{
57    BCryptGenRandom, BCRYPT_ALG_HANDLE, BCRYPT_USE_SYSTEM_PREFERRED_RNG,
58};
59
60mod aead;
61mod alg;
62mod fips;
63mod hash;
64mod hkdf;
65mod hmac;
66mod keys;
67mod kx;
68#[cfg(feature = "tls12")]
69mod prf;
70mod quic;
71mod signer;
72#[cfg(feature = "tls12")]
73mod tls12;
74mod tls13;
75mod verify;
76
77pub mod cipher_suite {
78    //! Supported cipher suites.
79    #[cfg(feature = "tls12")]
80    pub use super::tls12::{
81        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
82        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
83    };
84    #[cfg(feature = "tls12")]
85    pub use super::tls12::{
86        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
87    };
88    pub use super::tls13::{TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384};
89}
90
91pub use alg::ShutdownHandle;
92#[cfg(feature = "fips")]
93pub use fips::provider as default_provider;
94pub use fips::provider as fips_provider;
95pub use kx::ALL_KX_GROUPS;
96pub mod kx_group {
97    //! Supported key exchange groups.
98    pub use super::kx::{SECP256R1, SECP384R1, X25519};
99}
100pub use signer::KeyProvider;
101pub use verify::SUPPORTED_SIG_ALGS;
102
103/// Returns a CNG-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_cng_crypto::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/// ```
124///
125/// When the `fips` feature is enabled, this function will return the provider created by [`fips_provider()`].
126#[cfg(not(feature = "fips"))]
127pub fn default_provider() -> CryptoProvider {
128    CryptoProvider {
129        cipher_suites: ALL_CIPHER_SUITES.to_vec(),
130        kx_groups: ALL_KX_GROUPS.to_vec(),
131        signature_verification_algorithms: SUPPORTED_SIG_ALGS,
132        secure_random: &SecureRandom,
133        key_provider: &KeyProvider,
134    }
135}
136
137/// Create a [`CryptoProvider`] with specific cipher suites and key exchange groups
138///
139/// The specified cipher suites and key exchange groups should be defined in descending order of preference.
140/// i.e the first elements have the highest priority during negotiation.
141///
142/// Sample usage:
143/// ```rust
144/// use rustls::{ClientConfig, RootCertStore};
145/// use rustls_cng_crypto::custom_provider;
146/// use rustls_cng_crypto::cipher_suite::TLS13_AES_128_GCM_SHA256;
147/// use rustls_cng_crypto::kx_group::SECP256R1;
148/// use std::sync::Arc;
149/// use webpki_roots;
150///
151/// let mut root_store = RootCertStore {
152///     roots: webpki_roots::TLS_SERVER_ROOTS.iter().cloned().collect(),
153/// };
154///
155/// // Set custom config of cipher suites that have been imported from rustls_cng_crypto.
156/// let cipher_suites = vec![TLS13_AES_128_GCM_SHA256];
157/// let kx_group = vec![SECP256R1];
158///
159/// let mut config =
160///     ClientConfig::builder_with_provider(Arc::new(custom_provider(
161///         cipher_suites, kx_group)))
162///             .with_safe_default_protocol_versions()
163///             .unwrap()
164///             .with_root_certificates(root_store)
165///             .with_no_client_auth();
166///
167///
168/// ```
169#[must_use]
170pub fn custom_provider(
171    cipher_suites: Vec<SupportedCipherSuite>,
172    kx_groups: Vec<&'static dyn SupportedKxGroup>,
173) -> CryptoProvider {
174    CryptoProvider {
175        cipher_suites,
176        kx_groups,
177        signature_verification_algorithms: SUPPORTED_SIG_ALGS,
178        secure_random: &SecureRandom,
179        key_provider: &KeyProvider,
180    }
181}
182
183/// All supported cipher suites in descending order of preference:
184/// * `TLS13_AES_256_GCM_SHA384`
185/// * `TLS13_AES_128_GCM_SHA256`
186/// * `TLS13_CHACHA20_POLY1305_SHA256`
187/// * `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`
188/// * `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`
189/// * `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256`
190/// * `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`
191/// * `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`
192/// * `TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256`
193///
194/// If the default `tls12` feature is disabled then the TLS 1.2 cipher suites will not be included.
195pub static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
196    tls13::TLS13_AES_256_GCM_SHA384,
197    tls13::TLS13_AES_128_GCM_SHA256,
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(feature = "tls12")]
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(feature = "tls12")]
210    tls12::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
211];
212
213/// A struct that implements [`rustls::crypto::SecureRandom`] using CNG.
214#[derive(Debug)]
215pub struct SecureRandom;
216
217impl rustls::crypto::SecureRandom for SecureRandom {
218    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
219        unsafe {
220            BCryptGenRandom(
221                BCRYPT_ALG_HANDLE::default(),
222                buf,
223                BCRYPT_USE_SYSTEM_PREFERRED_RNG,
224            )
225            .ok()
226            .map_err(|_| GetRandomFailed)
227        }
228    }
229
230    fn fips(&self) -> bool {
231        fips::enabled()
232    }
233}