From 1dfb1955a0ac06e1a205dd9cd61ad29ab8c6bf0b Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Tue, 8 Feb 2022 22:16:13 +0000 Subject: [PATCH] Allow overriding the TLS cipher in use to get some performance benefit Benchmarked on a Pi 4 server accessed over the LAN: Tls13Aes256GcmSha384 11.7 MB/s (likely the default) Tls13Aes128GcmSha256 18.3 MB/s Tls13Chacha20Poly1305Sha256 24.7 MB/s (rustls doesn't support any other TLSv1.3 suites. We *can* enable TLSv1.2 suites but I'm a little unsure about that...) --- olivefs/src/configuration.rs | 26 ++++++++++++++++++++++++++ olivefs/src/main.rs | 1 + olivefs/src/requester.rs | 17 ++++++++++++++--- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/olivefs/src/configuration.rs b/olivefs/src/configuration.rs index 3c08220..005b861 100644 --- a/olivefs/src/configuration.rs +++ b/olivefs/src/configuration.rs @@ -1,3 +1,7 @@ +use rustls::cipher_suite::{ + TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256, +}; +use rustls::SupportedCipherSuite; use serde::Deserialize; use serde::Serialize; use std::path::PathBuf; @@ -11,6 +15,24 @@ pub struct OlivefsClientConfiguration { pub performance: PerformanceConfiguration, } +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +/// Choice of specific cipher suites +pub enum CipherConfiguration { + Tls13Aes256GcmSha384, + Tls13Aes128GcmSha256, + Tls13Chacha20Poly1305Sha256, +} + +impl Into for CipherConfiguration { + fn into(self) -> SupportedCipherSuite { + match self { + CipherConfiguration::Tls13Aes256GcmSha384 => TLS13_AES_256_GCM_SHA384, + CipherConfiguration::Tls13Aes128GcmSha256 => TLS13_AES_128_GCM_SHA256, + CipherConfiguration::Tls13Chacha20Poly1305Sha256 => TLS13_CHACHA20_POLY1305_SHA256, + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ConnectionConfiguration { /// Host and port combination to connect to. The server name is inferred from this. @@ -34,6 +56,10 @@ pub struct ConnectionConfiguration { /// Keep-alive in seconds pub keep_alive: u32, + + /// Allows overriding the TLS cipher in use. Might be useful for performance reasons. + #[serde(default)] + pub override_cipher: Option, } #[derive(Serialize, Deserialize, Debug, Clone, Default)] diff --git a/olivefs/src/main.rs b/olivefs/src/main.rs index b038a4c..7c60f39 100644 --- a/olivefs/src/main.rs +++ b/olivefs/src/main.rs @@ -60,6 +60,7 @@ async fn main() -> anyhow::Result<()> { &config.connection.client_certificate, &config.connection.client_key, socket_addr, + config.connection.override_cipher, server_name, config.connection.timeout, config.connection.keep_alive, diff --git a/olivefs/src/requester.rs b/olivefs/src/requester.rs index abc364b..e6df948 100644 --- a/olivefs/src/requester.rs +++ b/olivefs/src/requester.rs @@ -14,7 +14,7 @@ use std::str::FromStr; use std::sync::Arc; use std::time::{Duration, SystemTime}; -use crate::configuration::StreamingReaderConfig; +use crate::configuration::{CipherConfiguration, StreamingReaderConfig}; use crate::requester::streaming_reader::StreamingReader; use olivefs_common::io::read_file; use olivefs_common::messages::{ @@ -49,6 +49,7 @@ impl RequesterInternal { cert_path: &Path, cert_key_path: &Path, server_endpoint: SocketAddr, + cipher_configuration: Option, server_name: &str, timeout: u32, keep_alive: u32, @@ -63,8 +64,18 @@ impl RequesterInternal { let mut root_cert_store = RootCertStore::empty(); root_cert_store.add(&ca_cert)?; - let mut client_crypto = rustls::ClientConfig::builder() - .with_safe_defaults() + let client_crypto = rustls::ClientConfig::builder(); + let client_crypto = if let Some(cipher_override) = cipher_configuration { + client_crypto + .with_cipher_suites(&[cipher_override.into()]) + .with_safe_default_kx_groups() + .with_safe_default_protocol_versions() + .unwrap() + } else { + client_crypto.with_safe_defaults() + }; + + let mut client_crypto = client_crypto .with_root_certificates(root_cert_store) .with_single_cert(vec![client_cert], client_key)?;