ferron/setup/
tls_single.rs1use ferron_common::{get_value, get_values};
2use rustls::crypto::aws_lc_rs::cipher_suite::*;
3use rustls::crypto::aws_lc_rs::default_provider;
4use rustls::crypto::aws_lc_rs::kx_group::*;
5use rustls::crypto::CryptoProvider;
6use rustls::version::{TLS12, TLS13};
7use rustls::{ConfigBuilder, ServerConfig, WantsVerifier, WantsVersions};
8
9pub fn init_crypto_provider(
11 global_configuration: Option<&ferron_common::config::ServerConfiguration>,
12) -> Result<CryptoProvider, anyhow::Error> {
13 let mut crypto_provider = default_provider();
14 set_cipher_suites(&mut crypto_provider, global_configuration)?;
15 set_ecdh_curves(&mut crypto_provider, global_configuration)?;
16 Ok(crypto_provider)
17}
18
19fn set_cipher_suites(
21 crypto_provider: &mut CryptoProvider,
22 global_configuration: Option<&ferron_common::config::ServerConfiguration>,
23) -> Result<(), anyhow::Error> {
24 let cipher_suite: Vec<&ferron_common::config::ServerConfigurationValue> =
25 global_configuration.map_or(vec![], |c| get_values!("tls_cipher_suite", c));
26 if !cipher_suite.is_empty() {
27 let mut cipher_suites = Vec::new();
28 let cipher_suite_iter = cipher_suite.iter();
29 for cipher_suite_config in cipher_suite_iter {
30 if let Some(cipher_suite) = cipher_suite_config.as_str() {
31 let cipher_suite_to_add = match cipher_suite {
32 "TLS_AES_128_GCM_SHA256" => TLS13_AES_128_GCM_SHA256,
33 "TLS_AES_256_GCM_SHA384" => TLS13_AES_256_GCM_SHA384,
34 "TLS_CHACHA20_POLY1305_SHA256" => TLS13_CHACHA20_POLY1305_SHA256,
35 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
36 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
37 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
38 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
39 "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" => TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
40 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
41 _ => Err(anyhow::anyhow!(
42 "The \"{}\" cipher suite is not supported",
43 cipher_suite
44 ))?,
45 };
46 cipher_suites.push(cipher_suite_to_add);
47 }
48 }
49 crypto_provider.cipher_suites = cipher_suites;
50 }
51 Ok(())
52}
53
54fn set_ecdh_curves(
56 crypto_provider: &mut CryptoProvider,
57 global_configuration: Option<&ferron_common::config::ServerConfiguration>,
58) -> Result<(), anyhow::Error> {
59 let ecdh_curves = global_configuration.map_or(vec![], |c| get_values!("tls_ecdh_curve", c));
60 if !ecdh_curves.is_empty() {
61 let mut kx_groups = Vec::new();
62 let ecdh_curves_iter = ecdh_curves.iter();
63 for ecdh_curve_config in ecdh_curves_iter {
64 if let Some(ecdh_curve) = ecdh_curve_config.as_str() {
65 let kx_group_to_add = match ecdh_curve {
66 "secp256r1" => SECP256R1,
67 "secp384r1" => SECP384R1,
68 "x25519" => X25519,
69 "x25519mklem768" => X25519MLKEM768,
70 "mklem768" => MLKEM768,
71 _ => Err(anyhow::anyhow!("The \"{}\" ECDH curve is not supported", ecdh_curve))?,
72 };
73 kx_groups.push(kx_group_to_add);
74 }
75 }
76 crypto_provider.kx_groups = kx_groups;
77 }
78 Ok(())
79}
80
81pub fn set_tls_version(
83 tls_config_builder_wants_versions: ConfigBuilder<ServerConfig, WantsVersions>,
84 global_configuration: Option<&ferron_common::config::ServerConfiguration>,
85) -> Result<ConfigBuilder<ServerConfig, WantsVerifier>, anyhow::Error> {
86 let min_tls_version_option = global_configuration
87 .and_then(|c| get_value!("tls_min_version", c))
88 .and_then(|v| v.as_str());
89 let max_tls_version_option = global_configuration
90 .and_then(|c| get_value!("tls_max_version", c))
91 .and_then(|v| v.as_str());
92
93 let tls_config_builder_wants_verifier = if min_tls_version_option.is_none() && max_tls_version_option.is_none() {
94 tls_config_builder_wants_versions.with_safe_default_protocol_versions()?
95 } else {
96 let tls_versions = [("TLSv1.2", &TLS12), ("TLSv1.3", &TLS13)];
97 let min_tls_version_index = min_tls_version_option
98 .map_or(Some(0), |v| tls_versions.iter().position(|p| p.0 == v))
99 .ok_or(anyhow::anyhow!("Invalid minimum TLS version"))?;
100 let max_tls_version_index = max_tls_version_option
101 .map_or(Some(tls_versions.len() - 1), |v| {
102 tls_versions.iter().position(|p| p.0 == v)
103 })
104 .ok_or(anyhow::anyhow!("Invalid maximum TLS version"))?;
105 if max_tls_version_index < min_tls_version_index {
106 Err(anyhow::anyhow!("Maximum TLS version is older than minimum TLS version"))?
107 }
108 tls_config_builder_wants_versions.with_protocol_versions(
109 &tls_versions[min_tls_version_index..=max_tls_version_index]
110 .iter()
111 .map(|p| p.1)
112 .collect::<Vec<_>>(),
113 )?
114 };
115
116 Ok(tls_config_builder_wants_verifier)
117}