From 0fbf87b37e4ee8554234cbb0e6a4496209ef94bb Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Sun, 4 Mar 2018 20:53:26 -0800 Subject: [PATCH] Working stateless handshake --- src/endpoint.rs | 49 ++++++++++++++++++++++++-------------------- src/memory_stream.rs | 4 ---- tests/tests.rs | 39 ++++++++++++++++++----------------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/endpoint.rs b/src/endpoint.rs index 8339d9eb6..ae4603388 100644 --- a/src/endpoint.rs +++ b/src/endpoint.rs @@ -66,7 +66,6 @@ impl Endpoint { let cookie_factory = Arc::new(CookieFactory::new(&mut rng)); let mut tls = SslContext::builder(SslMethod::tls())?; - tls.set_cipher_list("TLS13-AES-128-GCM-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256")?; tls.set_options( SslOptions::NO_COMPRESSION | SslOptions::NO_SSLV2 | SslOptions::NO_SSLV3 | SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1 | SslOptions::NO_TLSV1_2 | SslOptions::DONT_INSERT_EMPTY_FRAGMENTS @@ -83,8 +82,8 @@ impl Endpoint { tls.set_cookie_verify_cb(move |tls, cookie| cookie_factory.verify(tls, cookie)); if let Some(ref listen) = config.listen { - tls.set_private_key(&listen.private_key); - tls.set_certificate(&listen.cert); + tls.set_private_key(&listen.private_key)?; + tls.set_certificate(&listen.cert)?; tls.check_private_key()?; } @@ -137,7 +136,7 @@ impl Endpoint { Header::Long { ref id, .. } | Header::Short { id: Some(ref id), .. } | Header::VersionNegotiate { ref id } => self.connection_ids.get(id), _ => None } { - self.handle_connected(ConnectionHandle(i), packet); + self.handle_connected(ConnectionHandle(i), remote, packet); return; } @@ -169,10 +168,10 @@ impl Endpoint { Err(e) => return Err(e.into()), }; let conn = self.add_connection(tls); + let mut buf = Vec::::new(); buf.reserve_exact(MIN_INITIAL_SIZE); encode_long_header(&mut buf, packet::INITIAL, self.connections[conn.0].id, self.connections[conn.0].get_tx_number() as u32); - match self.connections[conn.0].state.as_mut().unwrap() { &mut State::Handshake(ref mut x) => frame::stream(&mut buf, 0, None, true, false, &x.tls.get_mut().take_outgoing()), _ => unreachable!() @@ -223,7 +222,8 @@ impl Endpoint { Ok(_) => unreachable!(), Err(HandshakeError::WouldBlock(tls)) => { trace!(self.log, "stateless handshake complete"); - self.add_connection(tls); + let id = self.add_connection(tls); + self.events.push_back(Event::Connected(id)); } Err(e) => { debug!(self.log, "accept failed"; "reason" => %e); @@ -231,9 +231,10 @@ impl Endpoint { } } Err(e) => { + trace!(self.log, "stateless handshake failed"; "reason" => %e); let data = tls.get_mut().take_outgoing(); if data.len() != 0 { - trace!(self.log, "responding statelessly to initial packet"); + trace!(self.log, "responding statelessly"); let mut buf = Vec::::new(); buf.reserve_exact(17 + data.len()); encode_long_header(&mut buf, packet::RETRY, id, packet_number); @@ -246,22 +247,22 @@ impl Endpoint { } } - fn handle_connected(&mut self, handle: ConnectionHandle, packet: Packet) { - trace!(self.log, "connection got packet"; "id" => handle.0, "len" => packet.payload.len()); - match self.connections[handle.0].state.take().unwrap() { + fn handle_connected(&mut self, conn: ConnectionHandle, remote: SocketAddrV6, packet: Packet) { + trace!(self.log, "connection got packet"; "id" => conn.0, "len" => packet.payload.len()); + match self.connections[conn.0].state.take().unwrap() { State::Handshake(mut state) => { match packet.header { Header::Long { ty: packet::RETRY, .. } => {} // Proceed with handshake Header::Long { .. } => { unimplemented!() } Header::VersionNegotiate { .. } => { // TODO: MUST ignore if supported version is listed - self.connections.remove(handle.0); - self.events.push_back(Event::ConnectionLost { connection: handle, reason: ConnectionError::VersionMismatch }); + self.connections.remove(conn.0); + self.events.push_back(Event::ConnectionLost { connection: conn, reason: ConnectionError::VersionMismatch }); return; } // TODO: SHOULD buffer these. Header::Short { .. } => { - self.connections[handle.0].state = Some(State::Handshake(state)); + self.connections[conn.0].state = Some(State::Handshake(state)); return; } } @@ -277,31 +278,35 @@ impl Endpoint { } } } - self.connections[handle.0].state = Some(match state.tls.handshake() { + self.connections[conn.0].state = Some(match state.tls.handshake() { Ok(tls) => { trace!(self.log, "handshake complete"); - self.events.push_back(Event::Connected(handle)); + self.events.push_back(Event::Connected(conn)); State::Established(state::Established { tls }) } Err(HandshakeError::WouldBlock(mut tls)) => { - { - let data = tls.get_mut().take_outgoing(); - trace!(self.log, "handshake retry"; "data" => data.len()); - // TODO + trace!(self.log, "handshake retry"); + let mut buf = Vec::::new(); + buf.reserve_exact(MIN_INITIAL_SIZE); + encode_long_header(&mut buf, packet::INITIAL, self.connections[conn.0].id, self.connections[conn.0].get_tx_number() as u32); + frame::stream(&mut buf, 0, None, true, false, &tls.get_mut().take_outgoing()); + if buf.len() < MIN_INITIAL_SIZE { + buf.resize(MIN_INITIAL_SIZE, frame::tag::PADDING); } + self.transmit(remote, buf.into()); State::Handshake(state::Handshake { tls }) }, Err(e) => { debug!(self.log, "handshake failed"; "reason" => %e); - self.connections.remove(handle.0); - self.events.push_back(Event::ConnectionLost { connection: handle, reason: ConnectionError::HandshakeFailed(e.into()) }); + self.connections.remove(conn.0); + self.events.push_back(Event::ConnectionLost { connection: conn, reason: ConnectionError::HandshakeFailed(e.into()) }); return; } }) } State::Established(state) => { // TODO - self.connections[handle.0].state = Some(State::Established(state)) + self.connections[conn.0].state = Some(State::Established(state)) } } } diff --git a/src/memory_stream.rs b/src/memory_stream.rs index 72eeabf79..068619d14 100644 --- a/src/memory_stream.rs +++ b/src/memory_stream.rs @@ -28,10 +28,7 @@ impl Read for MemoryStream { self.incoming.get_mut().clear(); } if n == 0 { - eprintln!("read eof"); return Err(io::Error::new(io::ErrorKind::WouldBlock, "no data available")); - } else { - eprintln!("read {} bytes", n); } Ok(n) } @@ -39,7 +36,6 @@ impl Read for MemoryStream { impl Write for MemoryStream { fn write(&mut self, buf: &[u8]) -> Result { - eprintln!("write {} bytes", buf.len()); self.outgoing.write(buf) } diff --git a/tests/tests.rs b/tests/tests.rs index 03d5e5ffa..36fda10df 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -12,7 +12,7 @@ use std::net::SocketAddrV6; use std::ops::Deref; use openssl::pkey::{PKey, PKeyRef, Private}; -use openssl::ec::EcKey; +use openssl::rsa::Rsa; use openssl::x509::X509; use slog::{Logger, Drain}; @@ -24,21 +24,17 @@ fn logger() -> Logger { Logger::root(drain, o!()) } -lazy_static! { - static ref PRIVATE_KEY: EcKey = { - EcKey::generate( - &openssl::ec::EcGroup::from_curve_name( - openssl::nid::Nid::SECP224R1).unwrap() - ).unwrap() - }; - static ref CERT: X509 = { - let key = PKey::from_ec_key(PRIVATE_KEY.clone()).unwrap(); - let mut cert = X509::builder().unwrap(); - cert.set_pubkey(&key).unwrap(); - cert.sign(&key, openssl::hash::MessageDigest::sha256()).unwrap(); - cert.build() - }; -} + + +// lazy_static! { +// static ref PRIVATE_KEY: Rsa = { + +// }; +// static ref CERT: X509 = { +// let key = PKey::from_rsa(PRIVATE_KEY.clone()).unwrap(); + +// }; +// } struct Pair { @@ -52,12 +48,17 @@ struct Pair { impl Pair { fn new(log: Logger) -> Self { let server_addr = "[::1]:42".parse().unwrap(); + let key = PKey::from_rsa(Rsa::generate(2048).unwrap()).unwrap(); + let mut cert = X509::builder().unwrap(); + cert.set_pubkey(&key).unwrap(); + cert.sign(&key, openssl::hash::MessageDigest::sha256()).unwrap(); + let cert = cert.build(); let server = Endpoint::new( log.new(o!("peer" => "server")), Config { listen: Some(ListenConfig { - private_key: PKey::from_ec_key(PRIVATE_KEY.clone()).unwrap(), - cert: CERT.clone(), + private_key: key, + cert: cert, }), ..Config::default() }).unwrap(); @@ -98,6 +99,6 @@ fn connect() { panic!("{}", e); } pair.drive(); - assert_matches!(pair.client.poll().unwrap(), Event::Connected(_)); assert_matches!(pair.server.poll().unwrap(), Event::Connected(_)); + assert_matches!(pair.client.poll().unwrap(), Event::Connected(_)); }