rustls_symcrypt/
lib.rs

1#![doc = include_str!("../README.md")]
2use rustls::crypto::{CryptoProvider, GetRandomFailed, SecureRandom, SupportedKxGroup};
3
4use rustls::SupportedCipherSuite;
5use symcrypt::symcrypt_random;
6
7mod cipher_suites;
8mod ecdh;
9mod hash;
10mod hmac;
11mod signer;
12mod tls12;
13mod tls13;
14mod verify;
15use crate::verify::SUPPORTED_SIG_ALGS;
16
17/// Exporting default cipher suites for TLS 1.3
18pub use cipher_suites::{TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384};
19
20/// Exporting default cipher suites for TLS 1.2
21pub use cipher_suites::{
22    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
23    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
24};
25
26/// Exporting ChaCha suites for TLS 1.2 and TLS 1.3
27#[cfg(feature = "chacha")]
28pub use cipher_suites::{
29    TLS13_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
30    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
31};
32
33/// Exporting default key exchange groups
34pub use ecdh::{SECP256R1, SECP384R1};
35
36/// Exporting X25519 key exchange group
37#[cfg(feature = "x25519")]
38pub use ecdh::X25519;
39
40/// `default_symcrypt_provider` returns a `CryptoProvider` using the default `SymCrypt` configuration and cipher suites.
41/// To see the default cipher suites, please take a look at [`DEFAULT_CIPHER_SUITES`].
42///
43/// Sample usage:
44/// ```rust
45/// use rustls::{ClientConfig, RootCertStore};
46/// use rustls_symcrypt::default_symcrypt_provider;
47/// use std::sync::Arc;
48/// use webpki_roots;
49///
50/// let mut root_store = RootCertStore {
51///     roots: webpki_roots::TLS_SERVER_ROOTS.iter().cloned().collect(),
52/// };
53///
54/// let mut config =
55/// ClientConfig::builder_with_provider(Arc::new(default_symcrypt_provider()))
56///     .with_safe_default_protocol_versions()
57///     .unwrap()
58///     .with_root_certificates(root_store)
59///     .with_no_client_auth();
60/// // Rest of the connection setup
61///
62/// ```
63pub fn default_symcrypt_provider() -> CryptoProvider {
64    CryptoProvider {
65        cipher_suites: DEFAULT_CIPHER_SUITES.to_vec(),
66        kx_groups: ecdh::ALL_KX_GROUPS.to_vec(),
67        signature_verification_algorithms: SUPPORTED_SIG_ALGS,
68        secure_random: &SymCrypt,
69        key_provider: &signer::SymCryptProvider,
70    }
71}
72
73/// `custom_symcrypt_provider` provides a way to set up an custom config using a `symcrypt` crypto backend.
74///
75/// `provided_cipher_suites` takes in an optional `Vec<>` of `SupportedCipherSuites`.
76/// The supplied arguments for `provided_cipher_suite` will be used when when negotiating the TLS cipher suite;
77/// and should be placed in preference order, where the first element has highest priority.
78/// If `None` or an empty `Vec<>` is provided the [`DEFAULT_CIPHER_SUITES`] will be used instead.
79///
80/// `provided_kx_group` takes in an optional `Vec<>` of `SupportedKxGroup`
81/// The supplied arguments for `provided_kx_group` will be used when when negotiating the TLS key exchange;
82/// and should be placed in preference order, where the first element has highest priority.
83/// If `None` or an empty `Vec<>` is provided the default will be used instead.
84///
85/// This call cannot fail.
86///
87/// Sample usage:
88/// ```rust
89/// use rustls::{ClientConfig, RootCertStore};
90/// use rustls_symcrypt::{custom_symcrypt_provider, TLS13_AES_128_GCM_SHA256, SECP256R1};
91/// use std::sync::Arc;
92/// use webpki_roots;
93///
94/// let mut root_store = RootCertStore {
95///     roots: webpki_roots::TLS_SERVER_ROOTS.iter().cloned().collect(),
96/// };
97
98/// // Set custom config of cipher suites that have been imported from rustls_symcrypt.
99/// let cipher_suites = vec![TLS13_AES_128_GCM_SHA256];
100/// let kx_group = vec![SECP256R1];
101
102/// let mut config =
103///     ClientConfig::builder_with_provider(Arc::new(custom_symcrypt_provider(
104///         Some(cipher_suites), Some(kx_group))))
105///             .with_safe_default_protocol_versions()
106///             .unwrap()
107///             .with_root_certificates(root_store)
108///             .with_no_client_auth();
109///     // Rest of the connection setup
110/// ```
111pub fn custom_symcrypt_provider(
112    provided_cipher_suites: Option<Vec<SupportedCipherSuite>>,
113    provided_kx_group: Option<Vec<&'static dyn SupportedKxGroup>>,
114) -> CryptoProvider {
115    let cipher_suites = match provided_cipher_suites {
116        Some(suites) if !suites.is_empty() => suites, // Use provided non-empty suites
117        _ => DEFAULT_CIPHER_SUITES.to_vec(),          // Use default suites if None or empty
118    };
119
120    let kx_group = match provided_kx_group {
121        Some(groups) if !groups.is_empty() => groups, // Use provided non-empty groups
122        _ => ecdh::ALL_KX_GROUPS.to_vec(),            // Use default groups if None or empty
123    };
124
125    CryptoProvider {
126        cipher_suites,
127        kx_groups: kx_group,
128        signature_verification_algorithms: SUPPORTED_SIG_ALGS,
129        secure_random: &SymCrypt,
130        key_provider: &signer::SymCryptProvider,
131    }
132}
133
134/// List of SymCrypt supported cipher suites in a preference order.
135/// The first element has highest priority when negotiating cipher suites.
136/// ```ignore
137/// // TLS 1.3 suites
138/// TLS13_AES_256_GCM_SHA384
139/// TLS13_AES_128_GCM_SHA256
140/// TLS13_CHACHA20_POLY1305_SHA256 // Enabled with the `chacha` feature
141/// // TLS 1.2 suites
142/// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
143/// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
144/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 // Enabled with the `chacha` feature
145/// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
146/// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
147/// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 // Enabled with the `chacha` feature
148/// ```
149pub static DEFAULT_CIPHER_SUITES: &[SupportedCipherSuite] = ALL_CIPHER_SUITES;
150
151static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
152    // TLS 1.3 suites
153    TLS13_AES_256_GCM_SHA384,
154    TLS13_AES_128_GCM_SHA256,
155    #[cfg(feature = "chacha")]
156    TLS13_CHACHA20_POLY1305_SHA256,
157    // TLS 1.2 suites
158    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
159    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
160    #[cfg(feature = "chacha")]
161    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
162    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
163    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
164    #[cfg(feature = "chacha")]
165    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
166];
167
168#[derive(Debug)]
169struct SymCrypt;
170
171impl SecureRandom for SymCrypt {
172    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
173        symcrypt_random(buf);
174        Ok(())
175    }
176}
177
178#[cfg(test)]
179mod test {
180    use super::*;
181
182    #[test]
183    fn test_secure_random() {
184        let random = SymCrypt;
185        let mut buff_1 = [0u8; 10];
186        let mut buff_2 = [0u8; 10];
187
188        let _ = random.fill(&mut buff_1);
189        let _ = random.fill(&mut buff_2);
190
191        assert_ne!(buff_1, buff_2);
192    }
193}