From e435b56f34bea01a1a7613d1aa3158a97df40440 Mon Sep 17 00:00:00 2001 From: th4s Date: Wed, 3 Dec 2025 20:51:00 +0100 Subject: [PATCH] remove crate `client-async` --- Cargo.lock | 23 -- Cargo.toml | 2 - crates/mpc-tls/Cargo.toml | 1 - crates/mpc-tls/tests/test.rs | 160 ---------- crates/tls/client-async/Cargo.toml | 39 --- crates/tls/client-async/src/conn.rs | 89 ------ crates/tls/client-async/src/lib.rs | 269 ---------------- crates/tls/client-async/tests/test.rs | 438 -------------------------- crates/tlsn/Cargo.toml | 1 - crates/wasm/Cargo.toml | 1 - 10 files changed, 1023 deletions(-) delete mode 100644 crates/mpc-tls/tests/test.rs delete mode 100644 crates/tls/client-async/Cargo.toml delete mode 100644 crates/tls/client-async/src/conn.rs delete mode 100644 crates/tls/client-async/src/lib.rs delete mode 100644 crates/tls/client-async/tests/test.rs diff --git a/Cargo.lock b/Cargo.lock index 039cc9215..3a4ad02a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7214,7 +7214,6 @@ dependencies = [ "tlsn-server-fixture", "tlsn-server-fixture-certs", "tlsn-tls-client", - "tlsn-tls-client-async", "tlsn-tls-core", "tokio", "tokio-util", @@ -7530,7 +7529,6 @@ dependencies = [ "tlsn-key-exchange", "tlsn-tls-backend", "tlsn-tls-client", - "tlsn-tls-client-async", "tlsn-tls-core", "tokio", "tokio-util", @@ -7605,26 +7603,6 @@ dependencies = [ "webpki-roots 1.0.3", ] -[[package]] -name = "tlsn-tls-client-async" -version = "0.1.0-alpha.14-pre" -dependencies = [ - "bytes", - "futures", - "http-body-util", - "hyper", - "hyper-util", - "rstest", - "rustls-pki-types", - "rustls-webpki 0.103.7", - "thiserror 1.0.69", - "tls-server-fixture", - "tlsn-tls-client", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "tlsn-tls-core" version = "0.1.0-alpha.14-pre" @@ -7671,7 +7649,6 @@ dependencies = [ "tlsn", "tlsn-core", "tlsn-server-fixture-certs", - "tlsn-tls-client-async", "tlsn-tls-core", "tracing", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index 7681dd011..cb07a4c1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ members = [ "crates/server-fixture/server", "crates/tls/backend", "crates/tls/client", - "crates/tls/client-async", "crates/tls/core", "crates/mpc-tls", "crates/tls/server-fixture", @@ -57,7 +56,6 @@ tlsn-server-fixture = { path = "crates/server-fixture/server" } tlsn-server-fixture-certs = { path = "crates/server-fixture/certs" } tlsn-tls-backend = { path = "crates/tls/backend" } tlsn-tls-client = { path = "crates/tls/client" } -tlsn-tls-client-async = { path = "crates/tls/client-async" } tlsn-tls-core = { path = "crates/tls/core" } tlsn-utils = { git = "https://github.com/tlsnotary/tlsn-utils", rev = "6168663" } tlsn-harness-core = { path = "crates/harness/core" } diff --git a/crates/mpc-tls/Cargo.toml b/crates/mpc-tls/Cargo.toml index 13432069c..0b7a4c3ec 100644 --- a/crates/mpc-tls/Cargo.toml +++ b/crates/mpc-tls/Cargo.toml @@ -66,7 +66,6 @@ rand_chacha = { workspace = true } rstest = { workspace = true } tls-server-fixture = { workspace = true } tlsn-tls-client = { workspace = true } -tlsn-tls-client-async = { workspace = true } tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread"] } tokio-util = { workspace = true, features = ["compat"] } tracing-subscriber = { workspace = true } diff --git a/crates/mpc-tls/tests/test.rs b/crates/mpc-tls/tests/test.rs deleted file mode 100644 index 6b0b526ac..000000000 --- a/crates/mpc-tls/tests/test.rs +++ /dev/null @@ -1,160 +0,0 @@ -use std::sync::Arc; - -use futures::{AsyncReadExt, AsyncWriteExt}; -use mpc_tls::{Config, MpcTlsFollower, MpcTlsLeader}; -use mpz_common::context::test_mt_context; -use mpz_core::Block; -use mpz_ideal_vm::IdealVm; -use mpz_memory_core::correlated::Delta; -use mpz_ot::{ - ideal::rcot::ideal_rcot, - rcot::shared::{SharedRCOTReceiver, SharedRCOTSender}, -}; -use rand::{rngs::StdRng, SeedableRng}; -use rustls_pki_types::CertificateDer; -use tls_client::RootCertStore; -use tls_client_async::bind_client; -use tls_server_fixture::{bind_test_server_hyper, CA_CERT_DER, SERVER_DOMAIN}; -use tokio::sync::Mutex; -use tokio_util::compat::TokioAsyncReadCompatExt; -use webpki::anchor_from_trusted_cert; - -const CA_CERT: CertificateDer = CertificateDer::from_slice(CA_CERT_DER); - -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn mpc_tls_test() { - tracing_subscriber::fmt::init(); - - let config = Config::builder() - .defer_decryption(false) - .max_sent(1 << 13) - .max_recv_online(1 << 13) - .max_recv(1 << 13) - .build() - .unwrap(); - - let (leader, follower) = build_pair(config); - - tokio::try_join!( - tokio::spawn(leader_task(leader)), - tokio::spawn(follower_task(follower)) - ) - .unwrap(); -} - -async fn leader_task(mut leader: MpcTlsLeader) { - leader.alloc().unwrap(); - - leader.preprocess().await.unwrap(); - - let (leader_ctrl, leader_fut) = leader.run(); - tokio::spawn(async { leader_fut.await.unwrap() }); - - let config = tls_client::ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(RootCertStore { - roots: vec![anchor_from_trusted_cert(&CA_CERT).unwrap().to_owned()], - }) - .with_no_client_auth(); - - let server_name = SERVER_DOMAIN.try_into().unwrap(); - - let client = tls_client::ClientConnection::new( - Arc::new(config), - Box::new(leader_ctrl.clone()), - server_name, - ) - .unwrap(); - - let (client_socket, server_socket) = tokio::io::duplex(1 << 16); - tokio::spawn(bind_test_server_hyper(server_socket.compat())); - - let (mut conn, conn_fut) = bind_client(client_socket.compat(), client); - let handle = tokio::spawn(async { conn_fut.await.unwrap() }); - - let msg = concat!( - "POST /echo HTTP/1.1\r\n", - "Host: test-server.io\r\n", - "Connection: keep-alive\r\n", - "Accept-Encoding: identity\r\n", - "Content-Length: 5\r\n", - "\r\n", - "hello", - "\r\n" - ); - - conn.write_all(msg.as_bytes()).await.unwrap(); - - let mut buf = vec![0u8; 48]; - conn.read_exact(&mut buf).await.unwrap(); - - leader_ctrl.enable_decryption(false).await.unwrap(); - - let msg = concat!( - "POST /echo HTTP/1.1\r\n", - "Host: test-server.io\r\n", - "Connection: close\r\n", - "Accept-Encoding: identity\r\n", - "Content-Length: 5\r\n", - "\r\n", - "hello", - "\r\n" - ); - - conn.write_all(msg.as_bytes()).await.unwrap(); - conn.close().await.unwrap(); - - let mut buf = vec![0u8; 1024]; - conn.read_to_end(&mut buf).await.unwrap(); - - leader_ctrl.stop().await.unwrap(); - - handle.await.unwrap(); -} - -async fn follower_task(mut follower: MpcTlsFollower) { - follower.alloc().unwrap(); - follower.preprocess().await.unwrap(); - follower.run().await.unwrap(); -} - -fn build_pair(config: Config) -> (MpcTlsLeader, MpcTlsFollower) { - let mut rng = StdRng::seed_from_u64(0); - - let (mut mt_a, mut mt_b) = test_mt_context(8); - - let ctx_a = futures::executor::block_on(mt_a.new_context()).unwrap(); - let ctx_b = futures::executor::block_on(mt_b.new_context()).unwrap(); - - let delta_a = Delta::new(Block::random(&mut rng)); - let delta_b = Delta::new(Block::random(&mut rng)); - - let (rcot_send_a, rcot_recv_b) = ideal_rcot(Block::random(&mut rng), delta_a.into_inner()); - let (rcot_send_b, rcot_recv_a) = ideal_rcot(Block::random(&mut rng), delta_b.into_inner()); - - let rcot_send_a = SharedRCOTSender::new(rcot_send_a); - let rcot_send_b = SharedRCOTSender::new(rcot_send_b); - let rcot_recv_a = SharedRCOTReceiver::new(rcot_recv_a); - let rcot_recv_b = SharedRCOTReceiver::new(rcot_recv_b); - - let mpc_a = Arc::new(Mutex::new(IdealVm::new())); - let mpc_b = Arc::new(Mutex::new(IdealVm::new())); - - let leader = MpcTlsLeader::new( - config.clone(), - ctx_a, - mpc_a, - (rcot_send_a.clone(), rcot_send_a.clone(), rcot_send_a), - rcot_recv_a, - ); - - let follower = MpcTlsFollower::new( - config, - ctx_b, - mpc_b, - rcot_send_b, - (rcot_recv_b.clone(), rcot_recv_b.clone(), rcot_recv_b), - ); - - (leader, follower) -} diff --git a/crates/tls/client-async/Cargo.toml b/crates/tls/client-async/Cargo.toml deleted file mode 100644 index bd4475cb6..000000000 --- a/crates/tls/client-async/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "tlsn-tls-client-async" -authors = ["TLSNotary Team"] -description = "An async TLS client for TLSNotary" -keywords = ["tls", "mpc", "2pc", "client", "async"] -categories = ["cryptography"] -license = "MIT OR Apache-2.0" -version = "0.1.0-alpha.14-pre" -edition = "2021" - -[lints] -workspace = true - -[lib] -name = "tls_client_async" - -[features] -default = ["tracing"] -tracing = ["dep:tracing"] - -[dependencies] -tlsn-tls-client = { workspace = true } - -bytes = { workspace = true } -futures = { workspace = true } -thiserror = { workspace = true } -tokio-util = { workspace = true, features = ["io", "compat"] } -tracing = { workspace = true, optional = true } - -[dev-dependencies] -tls-server-fixture = { workspace = true } - -http-body-util = { workspace = true } -hyper = { workspace = true, features = ["client", "http1"] } -hyper-util = { workspace = true, features = ["full"] } -rstest = { workspace = true } -tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros"] } -rustls-webpki = { workspace = true } -rustls-pki-types = { workspace = true } diff --git a/crates/tls/client-async/src/conn.rs b/crates/tls/client-async/src/conn.rs deleted file mode 100644 index aec79c92b..000000000 --- a/crates/tls/client-async/src/conn.rs +++ /dev/null @@ -1,89 +0,0 @@ -use bytes::Bytes; -use futures::{ - channel::mpsc::{Receiver, SendError, Sender}, - sink::SinkMapErr, - AsyncRead, AsyncWrite, SinkExt, -}; -use std::{ - io::{Error as IoError, ErrorKind as IoErrorKind}, - pin::Pin, - task::{Context, Poll}, -}; -use tokio_util::{ - compat::{Compat, TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}, - io::{CopyToBytes, SinkWriter, StreamReader}, -}; - -type CompatSinkWriter = - Compat, fn(SendError) -> IoError>>>>; - -/// A TLS connection to a server. -/// -/// This type implements `AsyncRead` and `AsyncWrite` and can be used to -/// communicate with a server using TLS. -/// -/// # Note -/// -/// This connection is closed on a best-effort basis if this is dropped. To -/// ensure a clean close, you should call -/// [`AsyncWriteExt::close`](futures::io::AsyncWriteExt::close) to close the -/// connection. -#[derive(Debug)] -pub struct TlsConnection { - /// The data to be transmitted to the server is sent to this sink. - tx_sender: CompatSinkWriter, - /// The data to be received from the server is received from this stream. - rx_receiver: Compat>, Bytes>>, -} - -impl TlsConnection { - /// Creates a new TLS connection. - pub(crate) fn new( - tx_sender: Sender, - rx_receiver: Receiver>, - ) -> Self { - fn convert_error(err: SendError) -> IoError { - if err.is_disconnected() { - IoErrorKind::BrokenPipe.into() - } else { - IoErrorKind::WouldBlock.into() - } - } - - Self { - tx_sender: SinkWriter::new(CopyToBytes::new( - tx_sender.sink_map_err(convert_error as fn(SendError) -> IoError), - )) - .compat_write(), - rx_receiver: StreamReader::new(rx_receiver).compat(), - } - } -} - -impl AsyncRead for TlsConnection { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - Pin::new(&mut self.rx_receiver).poll_read(cx, buf) - } -} - -impl AsyncWrite for TlsConnection { - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - Pin::new(&mut self.tx_sender).poll_write(cx, buf) - } - - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.tx_sender).poll_flush(cx) - } - - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.tx_sender).poll_close(cx) - } -} diff --git a/crates/tls/client-async/src/lib.rs b/crates/tls/client-async/src/lib.rs deleted file mode 100644 index ca7ffaacc..000000000 --- a/crates/tls/client-async/src/lib.rs +++ /dev/null @@ -1,269 +0,0 @@ -//! Provides a TLS client which exposes an async socket. -//! -//! This library provides the [bind_client] function which attaches a TLS client -//! to a socket connection and then exposes a [TlsConnection] object, which -//! provides an async socket API for reading and writing cleartext. The TLS -//! client will then automatically encrypt and decrypt traffic and forward that -//! to the provided socket. - -#![deny(missing_docs, unreachable_pub, unused_must_use)] -#![deny(clippy::all)] -#![forbid(unsafe_code)] - -mod conn; - -use bytes::{Buf, Bytes}; -use futures::{ - channel::mpsc, future::Fuse, select_biased, stream::Next, AsyncRead, AsyncReadExt, AsyncWrite, - AsyncWriteExt, Future, FutureExt, SinkExt, StreamExt, -}; - -use std::{ - pin::Pin, - task::{Context, Poll}, -}; - -#[cfg(feature = "tracing")] -use tracing::{debug, debug_span, error, trace, warn, Instrument}; - -use tls_client::ClientConnection; - -pub use conn::TlsConnection; - -const RX_TLS_BUF_SIZE: usize = 1 << 13; // 8 KiB -const RX_BUF_SIZE: usize = 1 << 13; // 8 KiB - -/// An error that can occur during a TLS connection. -#[allow(missing_docs)] -#[derive(Debug, thiserror::Error)] -pub enum ConnectionError { - #[error(transparent)] - TlsError(#[from] tls_client::Error), - #[error(transparent)] - IOError(#[from] std::io::Error), -} - -/// Closed connection data. -#[derive(Debug)] -pub struct ClosedConnection { - /// The connection for the client - pub client: ClientConnection, - /// Sent plaintext bytes - pub sent: Vec, - /// Received plaintext bytes - pub recv: Vec, -} - -/// A future which runs the TLS connection to completion. -/// -/// This future must be polled in order for the connection to make progress. -#[must_use = "futures do nothing unless polled"] -pub struct ConnectionFuture { - fut: Pin> + Send>>, -} - -impl Future for ConnectionFuture { - type Output = Result; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - self.fut.poll_unpin(cx) - } -} - -/// Binds a client connection to the provided socket. -/// -/// Returns a connection handle and a future which runs the connection to -/// completion. -/// -/// # Errors -/// -/// Any connection errors that occur will be returned from the future, not -/// [`TlsConnection`]. -pub fn bind_client( - socket: T, - mut client: ClientConnection, -) -> (TlsConnection, ConnectionFuture) { - let (tx_sender, mut tx_receiver) = mpsc::channel(1 << 14); - let (mut rx_sender, rx_receiver) = mpsc::channel(1 << 14); - - let conn = TlsConnection::new(tx_sender, rx_receiver); - - let fut = async move { - client.start().await?; - let mut notify = client.get_notify().await?; - - let (mut server_rx, mut server_tx) = socket.split(); - - let mut rx_tls_buf = [0u8; RX_TLS_BUF_SIZE]; - let mut rx_buf = [0u8; RX_BUF_SIZE]; - - let mut handshake_done = false; - let mut client_closed = false; - let mut server_closed = false; - - let mut sent = Vec::with_capacity(1024); - let mut recv = Vec::with_capacity(1024); - - let mut rx_tls_fut = server_rx.read(&mut rx_tls_buf).fuse(); - // We don't start writing application data until the handshake is complete. - let mut tx_recv_fut: Fuse>> = Fuse::terminated(); - - // Runs both the tx and rx halves of the connection to completion. - // This loop does not terminate until the *SERVER* closes the connection and - // we've processed all received data. If an error occurs, the `TlsConnection` - // channels will be closed and the error will be returned from this future. - 'conn: loop { - // Write all pending TLS data to the server. - if client.wants_write() && !client_closed { - #[cfg(feature = "tracing")] - trace!("client wants to write"); - while client.wants_write() { - let _sent = client.write_tls_async(&mut server_tx).await?; - #[cfg(feature = "tracing")] - trace!("sent {} tls bytes to server", _sent); - } - server_tx.flush().await?; - } - - // Forward received plaintext to `TlsConnection`. - while !client.plaintext_is_empty() { - let read = client.read_plaintext(&mut rx_buf)?; - recv.extend(&rx_buf[..read]); - // Ignore if the receiver has hung up. - _ = rx_sender - .send(Ok(Bytes::copy_from_slice(&rx_buf[..read]))) - .await; - #[cfg(feature = "tracing")] - trace!("forwarded {} plaintext bytes to conn", read); - } - - if !client.is_handshaking() && !handshake_done { - #[cfg(feature = "tracing")] - debug!("handshake complete"); - handshake_done = true; - // Start reading application data that needs to be transmitted from the - // `TlsConnection`. - tx_recv_fut = tx_receiver.next().fuse(); - } - - if server_closed && client.plaintext_is_empty() && client.is_empty().await? { - break 'conn; - } - - select_biased! { - // Reads TLS data from the server and writes it into the client. - received = &mut rx_tls_fut => { - let received = received?; - #[cfg(feature = "tracing")] - trace!("received {} tls bytes from server", received); - - // Loop until we've processed all the data we received in this read. - // Note that we must make one iteration even if `received == 0`. - let mut processed = 0; - let mut reader = rx_tls_buf[..received].reader(); - loop { - processed += client.read_tls(&mut reader)?; - client.process_new_packets().await?; - - debug_assert!(processed <= received); - if processed >= received { - break; - } - } - - #[cfg(feature = "tracing")] - trace!("processed {} tls bytes from server", processed); - - // By convention if `AsyncRead::read` returns 0, it means EOF, i.e. the peer - // has closed the socket. - if received == 0 { - #[cfg(feature = "tracing")] - debug!("server closed connection"); - server_closed = true; - client.server_closed().await?; - // Do not read from the socket again. - rx_tls_fut = Fuse::terminated(); - } else { - // Reset the read future so next iteration we can read again. - rx_tls_fut = server_rx.read(&mut rx_tls_buf).fuse(); - } - } - // If we receive None from `TlsConnection`, it has closed, so we - // send a close_notify to the server. - data = &mut tx_recv_fut => { - if let Some(data) = data { - #[cfg(feature = "tracing")] - trace!("writing {} plaintext bytes to client", data.len()); - - sent.extend(&data); - client - .write_all_plaintext(&data)?; - client.process_new_packets().await?; - - tx_recv_fut = tx_receiver.next().fuse(); - } else { - if !server_closed { - if let Err(e) = send_close_notify(&mut client, &mut server_tx).await { - #[cfg(feature = "tracing")] - warn!("failed to send close_notify to server: {}", e); - } - } - - client_closed = true; - - tx_recv_fut = Fuse::terminated(); - } - } - // Waits for a notification from the backend that it is ready to decrypt data. - _ = &mut notify => { - #[cfg(feature = "tracing")] - trace!("backend is ready to decrypt"); - - client.process_new_packets().await?; - } - } - } - - #[cfg(feature = "tracing")] - debug!("client shutdown"); - - _ = server_tx.close().await; - tx_receiver.close(); - rx_sender.close_channel(); - - #[cfg(feature = "tracing")] - trace!( - "server close notify: {}, sent: {}, recv: {}", - client.received_close_notify(), - sent.len(), - recv.len() - ); - - Ok(ClosedConnection { client, sent, recv }) - }; - - #[cfg(feature = "tracing")] - let fut = fut.instrument(debug_span!("tls_connection")); - - let fut = ConnectionFuture { fut: Box::pin(fut) }; - - (conn, fut) -} - -async fn send_close_notify( - client: &mut ClientConnection, - server_tx: &mut (impl AsyncWrite + Unpin), -) -> Result<(), ConnectionError> { - #[cfg(feature = "tracing")] - trace!("sending close_notify to server"); - client.send_close_notify().await?; - client.process_new_packets().await?; - - // Flush all remaining plaintext - while client.wants_write() { - client.write_tls_async(server_tx).await?; - } - server_tx.flush().await?; - - Ok(()) -} diff --git a/crates/tls/client-async/tests/test.rs b/crates/tls/client-async/tests/test.rs deleted file mode 100644 index f588665db..000000000 --- a/crates/tls/client-async/tests/test.rs +++ /dev/null @@ -1,438 +0,0 @@ -use std::{str, sync::Arc}; - -use core::future::Future; -use futures::{AsyncReadExt, AsyncWriteExt}; -use http_body_util::{BodyExt as _, Full}; -use hyper::{body::Bytes, Request, StatusCode}; -use hyper_util::rt::TokioIo; -use rstest::{fixture, rstest}; -use rustls_pki_types::CertificateDer; -use tls_client::{ClientConfig, ClientConnection, RustCryptoBackend, ServerName}; -use tls_client_async::{bind_client, ClosedConnection, ConnectionError, TlsConnection}; -use tls_server_fixture::{ - bind_test_server, bind_test_server_hyper, APP_RECORD_LENGTH, CA_CERT_DER, CLOSE_DELAY, - SERVER_DOMAIN, -}; -use tokio::task::JoinHandle; -use tokio_util::compat::{FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; -use webpki::anchor_from_trusted_cert; - -const CA_CERT: CertificateDer = CertificateDer::from_slice(CA_CERT_DER); - -// An established client TLS connection -struct TlsFixture { - client_tls_conn: TlsConnection, - // a handle that must be `.await`ed to get the result of a TLS connection - closed_tls_task: JoinHandle>, -} - -// Sets up a TLS connection between client and server and sends a hello message -#[fixture] -async fn set_up_tls() -> TlsFixture { - let (client_socket, server_socket) = tokio::io::duplex(1 << 16); - - let _server_task = tokio::spawn(bind_test_server(server_socket.compat())); - - let mut root_store = tls_client::RootCertStore::empty(); - root_store - .roots - .push(anchor_from_trusted_cert(&CA_CERT).unwrap().to_owned()); - let config = ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(root_store) - .with_no_client_auth(); - let client = ClientConnection::new( - Arc::new(config), - Box::new(RustCryptoBackend::new()), - ServerName::try_from(SERVER_DOMAIN).unwrap(), - ) - .unwrap(); - - let (mut client_tls_conn, tls_fut) = bind_client(client_socket.compat(), client); - - let closed_tls_task = tokio::spawn(tls_fut); - - client_tls_conn - .write_all(&pad("expecting you to send back hello".to_string())) - .await - .unwrap(); - - // give the server some time to respond - std::thread::sleep(std::time::Duration::from_millis(10)); - - let mut plaintext = vec![0u8; 320]; - let n = client_tls_conn.read(&mut plaintext).await.unwrap(); - let s = str::from_utf8(&plaintext[0..n]).unwrap(); - - assert_eq!(s, "hello"); - - TlsFixture { - client_tls_conn, - closed_tls_task, - } -} - -// Expect the async tls client wrapped in `hyper::client` to make a successful -// request and receive the expected response -#[tokio::test] -async fn test_hyper_ok() { - let (client_socket, server_socket) = tokio::io::duplex(1 << 16); - - let server_task = tokio::spawn(bind_test_server_hyper(server_socket.compat())); - - let mut root_store = tls_client::RootCertStore::empty(); - root_store - .roots - .push(anchor_from_trusted_cert(&CA_CERT).unwrap().to_owned()); - let config = ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(root_store) - .with_no_client_auth(); - let client = ClientConnection::new( - Arc::new(config), - Box::new(RustCryptoBackend::new()), - ServerName::try_from(SERVER_DOMAIN).unwrap(), - ) - .unwrap(); - - let (conn, tls_fut) = bind_client(client_socket.compat(), client); - - let closed_tls_task = tokio::spawn(tls_fut); - - let (mut request_sender, connection) = - hyper::client::conn::http1::handshake(TokioIo::new(conn.compat())) - .await - .unwrap(); - - tokio::spawn(connection); - - let request = Request::builder() - .uri(format!("https://{SERVER_DOMAIN}/echo")) - .header("Host", SERVER_DOMAIN) - .header("Connection", "close") - .method("POST") - .body(Full::::new("hello".into())) - .unwrap(); - - let response = request_sender.send_request(request).await.unwrap(); - - assert!(response.status() == StatusCode::OK); - - // Process the response body - response.into_body().collect().await.unwrap().to_bytes(); - - let _ = server_task.await.unwrap(); - - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - - assert!(closed_conn.client.received_close_notify()); -} - -// Expect a clean TLS connection closure when server responds to the client's -// close_notify but doesn't close the socket -#[rstest] -#[tokio::test] -async fn test_ok_server_no_socket_close(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send close_notify back to us after 10 ms - client_tls_conn - .write_all(&pad("send_close_notify".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // closing `client_tls_conn` will cause close_notify to be sent by the client; - client_tls_conn.close().await.unwrap(); - - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - - assert!(closed_conn.client.received_close_notify()); -} - -// Expect a clean TLS connection closure when server responds to the client's -// close_notify AND also closes the socket -#[rstest] -#[tokio::test] -async fn test_ok_server_socket_close(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send close_notify back to us AND close the socket - // after 10 ms - client_tls_conn - .write_all(&pad("send_close_notify_and_close_socket".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // closing `client_tls_conn` will cause close_notify to be sent by the client; - client_tls_conn.close().await.unwrap(); - - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - - assert!(closed_conn.client.received_close_notify()); -} - -// Expect a clean TLS connection closure when server sends close_notify first -// but doesn't close the socket -#[rstest] -#[tokio::test] -async fn test_ok_server_close_notify(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send close_notify back to us after 10 ms - client_tls_conn - .write_all(&pad("send_close_notify".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // give enough time for server's close_notify to arrive - tokio::time::sleep(std::time::Duration::from_millis(20)).await; - - client_tls_conn.close().await.unwrap(); - - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - - assert!(closed_conn.client.received_close_notify()); -} - -// Expect a clean TLS connection closure when server sends close_notify first -// AND also closes the socket -#[rstest] -#[tokio::test] -async fn test_ok_server_close_notify_and_socket_close( - set_up_tls: impl Future, -) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send close_notify back to us after 10 ms - client_tls_conn - .write_all(&pad("send_close_notify_and_close_socket".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // give enough time for server's close_notify to arrive - tokio::time::sleep(std::time::Duration::from_millis(20)).await; - - client_tls_conn.close().await.unwrap(); - - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - - assert!(closed_conn.client.received_close_notify()); -} - -// Expect to be able to read the data after server closes the socket abruptly -#[rstest] -#[tokio::test] -async fn test_ok_read_after_close(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - .. - } = set_up_tls.await; - - // instruct the server to send us a hello message - client_tls_conn - .write_all(&pad("send a hello message".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // instruct the server to close the socket - client_tls_conn - .write_all(&pad("close_socket".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // give enough time to close the socket - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - - // try to read some more data - let mut buf = vec![0u8; 10]; - let n = client_tls_conn.read(&mut buf).await.unwrap(); - - assert_eq!(std::str::from_utf8(&buf[0..n]).unwrap(), "hello"); -} - -// Expect there to be no error when server DOES NOT send close_notify but just -// closes the socket -#[rstest] -#[tokio::test] -async fn test_ok_server_no_close_notify(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to close the socket - client_tls_conn - .write_all(&pad("close_socket".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // give enough time to close the socket - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - - client_tls_conn.close().await.unwrap(); - - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - - assert!(!closed_conn.client.received_close_notify()); -} - -// Expect to register a delay when the server delays closing the socket -#[rstest] -#[tokio::test] -async fn test_ok_delay_close(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - client_tls_conn - .write_all(&pad("must_delay_when_closing".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // closing `client_tls_conn` will cause close_notify to be sent by the client - client_tls_conn.close().await.unwrap(); - - use std::time::Instant; - let now = Instant::now(); - // this will resolve when the server stops delaying closing the socket - let closed_conn = closed_tls_task.await.unwrap().unwrap(); - let elapsed = now.elapsed(); - - // the elapsed time must be roughly equal to the server's delay - // (give or take timing variations) - assert!(elapsed.as_millis() as u64 > CLOSE_DELAY - 50); - - assert!(!closed_conn.client.received_close_notify()); -} - -// Expect client to error when server sends a corrupted message -#[rstest] -#[tokio::test] -async fn test_err_corrupted(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send a corrupted message - client_tls_conn - .write_all(&pad("send_corrupted_message".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - client_tls_conn.close().await.unwrap(); - - assert_eq!( - closed_tls_task.await.unwrap().err().unwrap().to_string(), - "received corrupt message" - ); -} - -// Expect client to error when server sends a TLS record with a bad MAC -#[rstest] -#[tokio::test] -async fn test_err_bad_mac(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send us a TLS record with a bad MAC - client_tls_conn - .write_all(&pad("send_record_with_bad_mac".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - client_tls_conn.close().await.unwrap(); - - assert_eq!( - closed_tls_task.await.unwrap().err().unwrap().to_string(), - "backend error: Decryption error: \"aead::Error\"" - ); -} - -// Expect client to error when server sends a fatal alert -#[rstest] -#[tokio::test] -async fn test_err_alert(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - closed_tls_task, - } = set_up_tls.await; - - // instruct the server to send us a TLS record with a bad MAC - client_tls_conn - .write_all(&pad("send_alert".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - client_tls_conn.close().await.unwrap(); - - assert_eq!( - closed_tls_task.await.unwrap().err().unwrap().to_string(), - "received fatal alert: BadRecordMac" - ); -} - -// Expect an error when trying to write data to a connection which server closed -// abruptly -#[rstest] -#[tokio::test] -async fn test_err_write_after_close(set_up_tls: impl Future) { - let TlsFixture { - mut client_tls_conn, - .. - } = set_up_tls.await; - - // instruct the server to close the socket - client_tls_conn - .write_all(&pad("close_socket".to_string())) - .await - .unwrap(); - client_tls_conn.flush().await.unwrap(); - - // give enough time to close the socket - tokio::time::sleep(std::time::Duration::from_millis(10)).await; - - // try to send some more data - let res = client_tls_conn - .write_all(&pad("more data".to_string())) - .await; - - assert_eq!(res.err().unwrap().kind(), std::io::ErrorKind::BrokenPipe); -} - -// Converts a string into a slice zero-padded to APP_RECORD_LENGTH -fn pad(s: String) -> Vec { - assert!(s.len() <= APP_RECORD_LENGTH); - let mut buf = vec![0u8; APP_RECORD_LENGTH]; - buf[..s.len()].copy_from_slice(s.as_bytes()); - buf -} diff --git a/crates/tlsn/Cargo.toml b/crates/tlsn/Cargo.toml index bc850576c..de9aed994 100644 --- a/crates/tlsn/Cargo.toml +++ b/crates/tlsn/Cargo.toml @@ -21,7 +21,6 @@ tlsn-attestation = { workspace = true } tlsn-core = { workspace = true } tlsn-deap = { workspace = true } tlsn-tls-client = { workspace = true } -tlsn-tls-client-async = { workspace = true } tlsn-tls-core = { workspace = true } tlsn-mpc-tls = { workspace = true } tlsn-cipher = { workspace = true } diff --git a/crates/wasm/Cargo.toml b/crates/wasm/Cargo.toml index 3393444c3..ace11d9c2 100644 --- a/crates/wasm/Cargo.toml +++ b/crates/wasm/Cargo.toml @@ -23,7 +23,6 @@ no-bundler = ["web-spawn/no-bundler"] tlsn-core = { workspace = true } tlsn = { workspace = true, features = ["web", "mozilla-certs"] } tlsn-server-fixture-certs = { workspace = true } -tlsn-tls-client-async = { workspace = true } tlsn-tls-core = { workspace = true } bincode = { workspace = true }