diff --git a/boring/src/ssl/async_callbacks.rs b/boring/src/ssl/async_callbacks.rs index 23464030d..6b64543db 100644 --- a/boring/src/ssl/async_callbacks.rs +++ b/boring/src/ssl/async_callbacks.rs @@ -96,9 +96,16 @@ impl SslContextBuilder { Poll::Pending => return Err(SelectCertError::RETRY), }; - let finish = fut_result.or(Err(SelectCertError::ERROR))?; - - finish(client_hello).or(Err(SelectCertError::ERROR)) + let finish = fut_result.map_err(|e| match e { + AsyncSelectCertError::Error => SelectCertError::ERROR, + AsyncSelectCertError::DisableEch => SelectCertError::DISABLE_ECH, + })?; + + match finish(client_hello) { + Ok(_) => Ok(()), + Err(AsyncSelectCertError::Error) => Err(SelectCertError::ERROR), + Err(AsyncSelectCertError::DisableEch) => Err(SelectCertError::DISABLE_ECH), + } }); } @@ -230,7 +237,12 @@ where /// A fatal error to be returned from async select certificate callbacks. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct AsyncSelectCertError; +pub enum AsyncSelectCertError { + /// A fatal error occurred and the handshake should be terminated. + Error, + /// Discard ECH ClientHelloInner and re-handshake with ClientHelloOuter. + DisableEch, +} /// Describes async private key hooks. This is used to off-load signing /// operations to a custom, potentially asynchronous, backend. Metadata about the diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index 139979078..2dc503eb8 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -563,6 +563,9 @@ impl SelectCertError { /// The operation could not be completed and should be retried later. pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_retry); + + /// Discard ECH ClientHelloInner and re-handshake with ClientHelloOuter. + pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_disable_ech); } /// Extension types, to be used with `ClientHello::get_extension`. diff --git a/tokio-boring/tests/async_select_certificate.rs b/tokio-boring/tests/async_select_certificate.rs index 91845f4ea..9ffe575b1 100644 --- a/tokio-boring/tests/async_select_certificate.rs +++ b/tokio-boring/tests/async_select_certificate.rs @@ -35,13 +35,13 @@ async fn test_async_select_certificate_callback_yield() { #[tokio::test] async fn test_async_select_certificate_callback_return_error() { - with_async_select_certificate_callback_error(|_| Err(AsyncSelectCertError)).await; + with_async_select_certificate_callback_error(|_| Err(AsyncSelectCertError::Error)).await; } #[tokio::test] async fn test_async_select_certificate_callback_future_error() { with_async_select_certificate_callback_error(|_| { - Ok(Box::pin(async move { Err(AsyncSelectCertError) })) + Ok(Box::pin(async move { Err(AsyncSelectCertError::Error) })) }) .await; } @@ -52,7 +52,7 @@ async fn test_async_select_certificate_callback_future_yield_error() { Ok(Box::pin(async move { yield_now().await; - Err(AsyncSelectCertError) + Err(AsyncSelectCertError::Error) })) }) .await; @@ -64,7 +64,10 @@ async fn test_async_select_certificate_callback_finish_error() { Ok(Box::pin(async move { yield_now().await; - Ok(Box::new(|_: ClientHello<'_>| Err(AsyncSelectCertError)) as BoxSelectCertFinish) + Ok( + Box::new(|_: ClientHello<'_>| Err(AsyncSelectCertError::Error)) + as BoxSelectCertFinish, + ) })) }) .await;