From 9e38babb5c4ae6b6395bf61d4203b680447d443d Mon Sep 17 00:00:00 2001 From: 0x676e67 Date: Sat, 2 Aug 2025 21:33:32 +0800 Subject: [PATCH 1/6] fix(tls): fix encoding error when multiple ALPS extensions are present --- src/tls/conn/ext.rs | 28 ++++++++++++++++++++-------- src/tls/conn/mod.rs | 11 +++-------- src/tls/types.rs | 11 ++--------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/tls/conn/ext.rs b/src/tls/conn/ext.rs index 3edf86f20..6375122c0 100644 --- a/src/tls/conn/ext.rs +++ b/src/tls/conn/ext.rs @@ -2,12 +2,11 @@ use boring2::{ error::ErrorStack, ssl::{ConnectConfiguration, SslConnectorBuilder, SslSessionRef, SslVerifyMode}, }; -use bytes::Bytes; use crate::{ Error, tls::{ - CertStore, CertificateCompressionAlgorithm, + AlpnProtocol, AlpsProtocol, CertStore, CertificateCompressionAlgorithm, conn::cert_compression::{ BrotliCertificateCompressor, ZlibCertificateCompressor, ZstdCertificateCompressor, }, @@ -34,10 +33,13 @@ pub trait ConnectConfigurationExt { /// Configure the session for the given `ConnectConfiguration`. fn set_seesion2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack>; + /// Configure the ALPN protocols for the given `ConnectConfiguration`. + fn set_alpn_protocols(&mut self, alpn: Option) -> Result<(), ErrorStack>; + /// Configure the ALPS for the given `ConnectConfiguration`. - fn set_alps_protos( + fn set_alps_protocols( &mut self, - alps: Option, + alps_values: Option<&[AlpsProtocol]>, use_new_codepoint: bool, ) -> Result<(), ErrorStack>; @@ -101,13 +103,23 @@ impl SslConnectorBuilderExt for SslConnectorBuilder { impl ConnectConfigurationExt for ConnectConfiguration { #[inline] - fn set_alps_protos( + fn set_alpn_protocols(&mut self, alpn: Option) -> Result<(), ErrorStack> { + if let Some(alpn) = alpn { + self.set_alpn_protos(&alpn.encode())?; + } + Ok(()) + } + + #[inline] + fn set_alps_protocols( &mut self, - alps: Option, + alps_values: Option<&[AlpsProtocol]>, use_new_codepoint: bool, ) -> Result<(), ErrorStack> { - if let Some(alps) = alps { - self.add_application_settings(&alps)?; + if let Some(values) = alps_values { + for alps in values { + self.add_application_settings(alps.value())?; + } // By default, the old endpoint is used. Avoid unnecessary FFI calls. if use_new_codepoint { diff --git a/src/tls/conn/mod.rs b/src/tls/conn/mod.rs index dfe47eac4..0aaaf587a 100644 --- a/src/tls/conn/mod.rs +++ b/src/tls/conn/mod.rs @@ -222,18 +222,13 @@ impl Inner { cfg.set_random_aes_hw_override(self.config.random_aes_hw_override); // Set ALPS protos - cfg.set_alps_protos( - self.config - .alps_protocols - .as_deref() - .map(AlpsProtocol::encode_sequence), + cfg.set_alps_protocols( + self.config.alps_protocols.as_deref(), self.config.alps_use_new_codepoint, )?; // Set ALPN protocols - if let Some(alpn) = req.metadata().alpn_protocol() { - cfg.set_alpn_protos(&alpn.encode())?; - } + cfg.set_alpn_protocols(req.metadata().alpn_protocol())?; let uri = req.uri().clone(); let host = uri.host().ok_or("URI missing host")?; diff --git a/src/tls/types.rs b/src/tls/types.rs index 2749b5999..da6281f05 100644 --- a/src/tls/types.rs +++ b/src/tls/types.rs @@ -67,15 +67,8 @@ impl AlpsProtocol { pub const HTTP3: AlpsProtocol = AlpsProtocol(b"h3"); #[inline] - pub(crate) fn encode_sequence<'a, I>(items: I) -> Bytes - where - I: IntoIterator, - { - let mut buf = BytesMut::new(); - for item in items { - buf.extend_from_slice(item.0); - } - buf.freeze() + pub(crate) const fn value(self) -> &'static [u8] { + self.0 } } From c25d43b13c154d75d513228f415cf04cd30621bb Mon Sep 17 00:00:00 2001 From: 0x676e67 Date: Sat, 2 Aug 2025 21:35:18 +0800 Subject: [PATCH 2/6] Update src/tls/conn/ext.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/tls/conn/ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls/conn/ext.rs b/src/tls/conn/ext.rs index 6375122c0..2cc940d74 100644 --- a/src/tls/conn/ext.rs +++ b/src/tls/conn/ext.rs @@ -31,7 +31,7 @@ pub trait SslConnectorBuilderExt { /// ConnectConfigurationExt trait for `ConnectConfiguration`. pub trait ConnectConfigurationExt { /// Configure the session for the given `ConnectConfiguration`. - fn set_seesion2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack>; + fn set_session2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack>; /// Configure the ALPN protocols for the given `ConnectConfiguration`. fn set_alpn_protocols(&mut self, alpn: Option) -> Result<(), ErrorStack>; From 7a4fcbf8a97a6c6a8bbfcdccfe62df3444a8a677 Mon Sep 17 00:00:00 2001 From: 0x676e67 Date: Sat, 2 Aug 2025 21:38:12 +0800 Subject: [PATCH 3/6] fix build --- src/tls/conn/ext.rs | 2 +- src/tls/conn/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tls/conn/ext.rs b/src/tls/conn/ext.rs index 2cc940d74..4f9940ca2 100644 --- a/src/tls/conn/ext.rs +++ b/src/tls/conn/ext.rs @@ -139,7 +139,7 @@ impl ConnectConfigurationExt for ConnectConfiguration { } #[inline] - fn set_seesion2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { + fn set_session2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { unsafe { self.set_session(session)?; } diff --git a/src/tls/conn/mod.rs b/src/tls/conn/mod.rs index 0aaaf587a..b067fdf72 100644 --- a/src/tls/conn/mod.rs +++ b/src/tls/conn/mod.rs @@ -240,7 +240,7 @@ impl Inner { // If the session cache is enabled, we try to retrieve the session // associated with the key. If it exists, we set it in the SSL configuration. if let Some(session) = cache.lock().get(&key) { - cfg.set_seesion2(&session)?; + cfg.set_session2(&session)?; if self.config.no_ticket { cfg.set_options(SslOptions::NO_TICKET)?; From 6730ef92433b3cdd2406869871aac20673ee5959 Mon Sep 17 00:00:00 2001 From: 0x676e67 Date: Sat, 2 Aug 2025 21:39:23 +0800 Subject: [PATCH 4/6] fmt --- src/tls/conn/ext.rs | 14 +------------- src/tls/conn/mod.rs | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/tls/conn/ext.rs b/src/tls/conn/ext.rs index 4f9940ca2..797c23e10 100644 --- a/src/tls/conn/ext.rs +++ b/src/tls/conn/ext.rs @@ -1,6 +1,6 @@ use boring2::{ error::ErrorStack, - ssl::{ConnectConfiguration, SslConnectorBuilder, SslSessionRef, SslVerifyMode}, + ssl::{ConnectConfiguration, SslConnectorBuilder, SslVerifyMode}, }; use crate::{ @@ -30,9 +30,6 @@ pub trait SslConnectorBuilderExt { /// ConnectConfigurationExt trait for `ConnectConfiguration`. pub trait ConnectConfigurationExt { - /// Configure the session for the given `ConnectConfiguration`. - fn set_session2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack>; - /// Configure the ALPN protocols for the given `ConnectConfiguration`. fn set_alpn_protocols(&mut self, alpn: Option) -> Result<(), ErrorStack>; @@ -137,13 +134,4 @@ impl ConnectConfigurationExt for ConnectConfiguration { self.set_aes_hw_override(random_bool); } } - - #[inline] - fn set_session2(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { - unsafe { - self.set_session(session)?; - } - - Ok(()) - } } diff --git a/src/tls/conn/mod.rs b/src/tls/conn/mod.rs index b067fdf72..6bdb22598 100644 --- a/src/tls/conn/mod.rs +++ b/src/tls/conn/mod.rs @@ -240,7 +240,7 @@ impl Inner { // If the session cache is enabled, we try to retrieve the session // associated with the key. If it exists, we set it in the SSL configuration. if let Some(session) = cache.lock().get(&key) { - cfg.set_session2(&session)?; + unsafe { cfg.set_session(&session) }?; if self.config.no_ticket { cfg.set_options(SslOptions::NO_TICKET)?; From 61c2c96a32bdc447bc073cca2526f524e5e903cc Mon Sep 17 00:00:00 2001 From: 0x676e67 Date: Sat, 2 Aug 2025 22:13:38 +0800 Subject: [PATCH 5/6] fmt --- src/tls/conn/ext.rs | 61 ++------------------------------------------- src/tls/conn/mod.rs | 27 ++++++++++++++------ 2 files changed, 21 insertions(+), 67 deletions(-) diff --git a/src/tls/conn/ext.rs b/src/tls/conn/ext.rs index 797c23e10..50fb0b9dc 100644 --- a/src/tls/conn/ext.rs +++ b/src/tls/conn/ext.rs @@ -1,12 +1,9 @@ -use boring2::{ - error::ErrorStack, - ssl::{ConnectConfiguration, SslConnectorBuilder, SslVerifyMode}, -}; +use boring2::ssl::{SslConnectorBuilder, SslVerifyMode}; use crate::{ Error, tls::{ - AlpnProtocol, AlpsProtocol, CertStore, CertificateCompressionAlgorithm, + CertStore, CertificateCompressionAlgorithm, conn::cert_compression::{ BrotliCertificateCompressor, ZlibCertificateCompressor, ZstdCertificateCompressor, }, @@ -28,22 +25,6 @@ pub trait SslConnectorBuilderExt { ) -> crate::Result; } -/// ConnectConfigurationExt trait for `ConnectConfiguration`. -pub trait ConnectConfigurationExt { - /// Configure the ALPN protocols for the given `ConnectConfiguration`. - fn set_alpn_protocols(&mut self, alpn: Option) -> Result<(), ErrorStack>; - - /// Configure the ALPS for the given `ConnectConfiguration`. - fn set_alps_protocols( - &mut self, - alps_values: Option<&[AlpsProtocol]>, - use_new_codepoint: bool, - ) -> Result<(), ErrorStack>; - - /// Configure the random aes hardware override for the given `ConnectConfiguration`. - fn set_random_aes_hw_override(&mut self, enable: bool); -} - impl SslConnectorBuilderExt for SslConnectorBuilder { #[inline] fn set_cert_store(mut self, store: Option<&CertStore>) -> crate::Result { @@ -97,41 +78,3 @@ impl SslConnectorBuilderExt for SslConnectorBuilder { Ok(self) } } - -impl ConnectConfigurationExt for ConnectConfiguration { - #[inline] - fn set_alpn_protocols(&mut self, alpn: Option) -> Result<(), ErrorStack> { - if let Some(alpn) = alpn { - self.set_alpn_protos(&alpn.encode())?; - } - Ok(()) - } - - #[inline] - fn set_alps_protocols( - &mut self, - alps_values: Option<&[AlpsProtocol]>, - use_new_codepoint: bool, - ) -> Result<(), ErrorStack> { - if let Some(values) = alps_values { - for alps in values { - self.add_application_settings(alps.value())?; - } - - // By default, the old endpoint is used. Avoid unnecessary FFI calls. - if use_new_codepoint { - self.set_alps_use_new_codepoint(use_new_codepoint); - } - } - - Ok(()) - } - - #[inline] - fn set_random_aes_hw_override(&mut self, enable: bool) { - if enable { - let random_bool = (crate::util::fast_random() % 2) == 0; - self.set_aes_hw_override(random_bool); - } - } -} diff --git a/src/tls/conn/mod.rs b/src/tls/conn/mod.rs index 6bdb22598..610cd0f86 100644 --- a/src/tls/conn/mod.rs +++ b/src/tls/conn/mod.rs @@ -40,7 +40,7 @@ use crate::{ sync::Mutex, tls::{ AlpnProtocol, AlpsProtocol, CertStore, Identity, KeyLogPolicy, TlsOptions, TlsVersion, - conn::ext::{ConnectConfigurationExt, SslConnectorBuilderExt}, + conn::ext::SslConnectorBuilderExt, }, }; @@ -218,17 +218,28 @@ impl Inner { // Set ECH grease cfg.set_enable_ech_grease(self.config.enable_ech_grease); - // Set AES hardware override - cfg.set_random_aes_hw_override(self.config.random_aes_hw_override); + // Set random AES hardware override + if self.config.random_aes_hw_override { + let random_bool = (crate::util::fast_random() & 1) == 0; + cfg.set_aes_hw_override(random_bool); + } // Set ALPS protos - cfg.set_alps_protocols( - self.config.alps_protocols.as_deref(), - self.config.alps_use_new_codepoint, - )?; + if let Some(ref alps_values) = self.config.alps_protocols { + for alps in alps_values.iter() { + cfg.add_application_settings(alps.value())?; + } + + // By default, the old endpoint is used. + if !alps_values.is_empty() && self.config.alps_use_new_codepoint { + cfg.set_alps_use_new_codepoint(true); + } + } // Set ALPN protocols - cfg.set_alpn_protocols(req.metadata().alpn_protocol())?; + if let Some(alpn) = req.metadata().alpn_protocol() { + cfg.set_alpn_protos(&alpn.encode())?; + } let uri = req.uri().clone(); let host = uri.host().ok_or("URI missing host")?; From 0933d601c000b695cb8244475d428d9b25af44d9 Mon Sep 17 00:00:00 2001 From: 0x676e67 Date: Sat, 2 Aug 2025 22:14:32 +0800 Subject: [PATCH 6/6] fmt --- src/tls/conn/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tls/conn/mod.rs b/src/tls/conn/mod.rs index 610cd0f86..7868a5cc9 100644 --- a/src/tls/conn/mod.rs +++ b/src/tls/conn/mod.rs @@ -220,8 +220,8 @@ impl Inner { // Set random AES hardware override if self.config.random_aes_hw_override { - let random_bool = (crate::util::fast_random() & 1) == 0; - cfg.set_aes_hw_override(random_bool); + let random = (crate::util::fast_random() & 1) == 0; + cfg.set_aes_hw_override(random); } // Set ALPS protos