From aa04fdfec0a4b24ccdedea71f9acdf138ca58fe8 Mon Sep 17 00:00:00 2001 From: xiaofei0800 <54530729+xiaofei0800@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:34:17 +0800 Subject: [PATCH] Add config for retry. (#36) --- apps/src/bin/tquic_server.rs | 5 +++++ include/tquic.h | 5 +++++ interop/run_endpoint.sh | 2 +- src/connection/connection.rs | 10 +--------- src/endpoint.rs | 4 ++-- src/ffi.rs | 6 ++++++ src/lib.rs | 24 ++++++++++++++++++++---- 7 files changed, 40 insertions(+), 16 deletions(-) diff --git a/apps/src/bin/tquic_server.rs b/apps/src/bin/tquic_server.rs index 1ca5ed5d6..66ba19dd4 100644 --- a/apps/src/bin/tquic_server.rs +++ b/apps/src/bin/tquic_server.rs @@ -86,6 +86,10 @@ pub struct ServerOpt { #[clap(long, value_name = "STR")] pub address_token_key: Option, + /// Enable stateless retry. + #[clap(long)] + pub enable_retry: bool, + /// Disable stateless reset. #[clap(long)] pub disable_stateless_reset: bool, @@ -150,6 +154,7 @@ impl Server { config.set_recv_udp_payload_size(option.recv_udp_payload_size); config.set_send_udp_payload_size(option.send_udp_payload_size); config.set_max_handshake_timeout(option.handshake_timeout); + config.enable_retry(option.enable_retry); config.enable_stateless_reset(!option.disable_stateless_reset); config.set_max_handshake_timeout(option.handshake_timeout); config.set_max_idle_timeout(option.idle_timeout); diff --git a/include/tquic.h b/include/tquic.h index 23f7c25f3..149573f5e 100644 --- a/include/tquic.h +++ b/include/tquic.h @@ -397,6 +397,11 @@ int quic_config_set_address_token_key(struct quic_config_t *config, const uint8_t *token_keys, size_t token_keys_len); +/** + * Set whether stateless retry is allowed. Default is not allowed. + */ +void quic_config_enable_retry(struct quic_config_t *config, bool enabled); + /** * Set the length of source cid. The length should not be greater than 20. */ diff --git a/interop/run_endpoint.sh b/interop/run_endpoint.sh index 124150656..e57aeb1c0 100644 --- a/interop/run_endpoint.sh +++ b/interop/run_endpoint.sh @@ -79,7 +79,7 @@ elif [ "$ROLE" == "server" ]; then SERVER_ARGS="-c /certs/cert.pem -k /certs/priv.key --listen [::]:443 --root $ROOT_DIR --keylog-file $SSLKEYLOGFILE" case $TESTCASE in retry) - SERVER_ARGS="$SERVER_ARGS --address-token-key=test" + SERVER_ARGS="$SERVER_ARGS --enable-retry" ;; *) ;; diff --git a/src/connection/connection.rs b/src/connection/connection.rs index dd803643f..6ba3c0069 100644 --- a/src/connection/connection.rs +++ b/src/connection/connection.rs @@ -297,14 +297,6 @@ impl Connection { conn.flags.insert(DerivedInitialSecrets); } - // Prepare resume address token if needed - if is_server && conf.retry { - let token = AddressToken::new_resume_token(remote); - if let Ok(token) = token.encode(&conf.address_token_key[0]) { - conn.token = Some(token); - } - } - if !conf.max_handshake_timeout.is_zero() { conn.timers.set( Timer::Handshake, @@ -313,7 +305,7 @@ impl Connection { } // Prepare resume address token if needed - if is_server && conf.retry { + if is_server { let token = AddressToken::new_resume_token(remote); if let Ok(token) = token.encode(&conf.address_token_key[0]) { conn.token = Some(token); diff --git a/src/endpoint.rs b/src/endpoint.rs index b8a57cc91..1782ac48a 100644 --- a/src/endpoint.rs +++ b/src/endpoint.rs @@ -1749,7 +1749,7 @@ mod tests { let cli_conf = TestPair::new_test_config(false)?; let mut srv_conf = TestPair::new_test_config(true)?; - srv_conf.set_address_token_key(vec![[1; 16]])?; + srv_conf.enable_retry(true); let mut case_conf = CaseConf::default(); case_conf.handshake_only = true; @@ -1785,7 +1785,7 @@ mod tests { let cli_conf = TestPair::new_test_config(false)?; let mut srv_conf = TestPair::new_test_config(true)?; - srv_conf.set_address_token_key(vec![token_key])?; + srv_conf.enable_retry(true); let mut case_conf = CaseConf::default(); case_conf.handshake_only = true; diff --git a/src/ffi.rs b/src/ffi.rs index 64b8e9271..a4e941f38 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -279,6 +279,12 @@ pub extern "C" fn quic_config_set_address_token_key( } } +/// Set whether stateless retry is allowed. Default is not allowed. +#[no_mangle] +pub extern "C" fn quic_config_enable_retry(config: &mut Config, enabled: bool) { + config.enable_retry(enabled); +} + /// Set the length of source cid. The length should not be greater than 20. #[no_mangle] pub extern "C" fn quic_config_set_cid_len(config: &mut Config, v: u8) { diff --git a/src/lib.rs b/src/lib.rs index 10e618846..270680900 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -393,7 +393,7 @@ impl Config { retry: false, stateless_reset: true, address_token_lifetime: Duration::from_secs(86400), - address_token_key: vec![], + address_token_key: Self::rand_address_token_key()?, reset_token_key, cid_len: 8, send_batch_size: 64, @@ -542,22 +542,29 @@ impl Config { self.address_token_lifetime = Duration::from_secs(seconds); } - /// Set the key for address token generation. It also enables retry. + /// Set the key for address token generation. pub fn set_address_token_key(&mut self, keys: Vec<[u8; 16]>) -> Result<()> { if keys.is_empty() { return Err(Error::InvalidConfig("address token key empty".into())); } + let mut address_token_key = vec![]; for key in keys { // AES-128 uses a 128-bit key length let key = UnboundKey::new(&aead::AES_128_GCM, &key).map_err(|_| Error::CryptoFail)?; let key = LessSafeKey::new(key); - self.address_token_key.push(key); + address_token_key.push(key); } - self.retry = true; + self.address_token_key = address_token_key; + Ok(()) } + /// Set whether stateless retry is allowed. Default is not allowed. + pub fn enable_retry(&mut self, enable_retry: bool) { + self.retry = enable_retry; + } + /// Set whether stateless reset is allowed. pub fn enable_stateless_reset(&mut self, enable_stateless_reset: bool) { self.stateless_reset = enable_stateless_reset; @@ -586,6 +593,15 @@ impl Config { self.tls_config_selector = Some(tls_config_selector); } + /// Generate random address token key. + fn rand_address_token_key() -> Result> { + let mut key = [0_u8; 16]; + rand::thread_rng().fill_bytes(&mut key); + Ok(vec![LessSafeKey::new( + UnboundKey::new(&aead::AES_128_GCM, &key).map_err(|_| Error::CryptoFail)?, + )]) + } + /// Create new tls session. fn new_tls_session( &mut self,