diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/consts.rs | 1 | ||||
-rw-r--r-- | src/interface/mod.rs | 8 | ||||
-rw-r--r-- | src/interface/peer_server.rs | 36 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/noise.rs | 16 | ||||
-rw-r--r-- | src/protocol/peer.rs | 9 |
6 files changed, 53 insertions, 18 deletions
diff --git a/src/consts.rs b/src/consts.rs index f5059d0..f810ad4 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -22,3 +22,4 @@ pub const AEAD_TAG_SIZE: usize = 16; pub const TRANSPORT_OVERHEAD: usize = TRANSPORT_HEADER_SIZE + AEAD_TAG_SIZE; pub const MAX_SEGMENT_SIZE: usize = (1 << 16) - 1; pub const MAX_CONTENT_SIZE: usize = MAX_SEGMENT_SIZE - TRANSPORT_OVERHEAD; +pub const PADDING_MULTIPLE: usize = 16; diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 41b4a66..38c306c 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -18,6 +18,7 @@ use std::collections::HashMap; use std::net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr}; use std::time::Duration; use types::{InterfaceInfo}; +use x25519_dalek as x25519; use pnet::packet::ipv4::Ipv4Packet; @@ -190,7 +191,10 @@ impl Interface { let mut state = state.borrow_mut(); match event { UpdateEvent::PrivateKey(private_key) => { + let pub_key = x25519::generate_public(&private_key); + info!("our pubkey: {}", base64::encode(pub_key.as_bytes())); state.interface_info.private_key = Some(private_key); + state.interface_info.pub_key = Some(*pub_key.as_bytes()); debug!("set new private key"); }, UpdateEvent::ListenPort(port) => { @@ -202,7 +206,7 @@ impl Interface { let mut peer = Peer::new(info.clone()); let private_key = &state.interface_info.private_key.expect("no private key!"); - let (init_packet, our_index) = peer.initiate_new_session(private_key).unwrap(); + let (init_packet, our_index) = peer.initiate_new_session(private_key).expect("initiate_new_session"); let peer = Rc::new(RefCell::new(peer)); @@ -219,7 +223,7 @@ impl Interface { future::ok(()) } - }).map_err(|_| ()); + }).map_err(|e| { warn!("error {:?}", e); () }); core.run(peer_server.join(utun_fut.join(config_fut.join(config_server)))).unwrap(); } diff --git a/src/interface/peer_server.rs b/src/interface/peer_server.rs index 2470335..1fe6724 100644 --- a/src/interface/peer_server.rs +++ b/src/interface/peer_server.rs @@ -122,6 +122,14 @@ impl PeerServer { let mut state = self.shared_state.borrow_mut(); match packet[0] { 1 => { + ensure!(packet.len() == 148, "handshake init packet length is incorrect"); + { + let pubkey = state.interface_info.pub_key.as_ref() + .ok_or_else(|| format_err!("must have local interface key"))?; + let (mac_in, mac_out) = packet.split_at(116); + Noise::verify_mac1(pubkey, mac_in, &mac_out[..16])?; + } + let their_index = LittleEndian::read_u32(&packet[4..]); let mut noise = Noise::build_responder( @@ -145,12 +153,19 @@ impl PeerServer { let _ = state.index_map.insert(next_index, peer_ref.clone()); self.send_to_peer((addr, response)); - info!("sent handshake response, ratcheted session."); + info!("sent handshake response, ratcheted session (index {}).", next_index); }, 2 => { - let our_index = LittleEndian::read_u32(&packet[8..]); - let peer_ref = state.index_map.get(&our_index) - .ok_or_else(|| format_err!("unknown our_index"))? + ensure!(packet.len() == 92, "handshake resp packet length is incorrect"); + { + let pubkey = state.interface_info.pub_key.as_ref() + .ok_or_else(|| format_err!("must have local interface key"))?; + let (mac_in, mac_out) = packet.split_at(60); + Noise::verify_mac1(pubkey, mac_in, &mac_out[..16])?; + } + let our_index = LittleEndian::read_u32(&packet[8..]); + let peer_ref = state.index_map.get(&our_index) + .ok_or_else(|| format_err!("unknown our_index ({})", our_index))? .clone(); let mut peer = peer_ref.borrow_mut(); let dead_index = peer.process_incoming_handshake_response(&packet)?; @@ -288,7 +303,9 @@ impl Future for PeerServer { // Handle pending state-changing timers loop { match self.timer_rx.poll() { - Ok(Async::Ready(Some(message))) => self.handle_timer(message).unwrap(), + Ok(Async::Ready(Some(message))) => { + let _ = self.handle_timer(message).map_err(|e| warn!("TIMER ERR: {:?}", e)); + }, Ok(Async::NotReady) => break, Ok(Async::Ready(None)) | Err(_) => return Err(()), } @@ -297,7 +314,9 @@ impl Future for PeerServer { // Handle UDP packets from the outside world loop { match self.udp_stream.poll() { - Ok(Async::Ready(Some((addr, packet)))) => self.handle_incoming_packet(addr, packet).unwrap(), + Ok(Async::Ready(Some((addr, packet)))) => { + let _ = self.handle_incoming_packet(addr, packet).map_err(|e| warn!("UDP ERR: {:?}", e)); + }, Ok(Async::NotReady) => break, Ok(Async::Ready(None)) | Err(_) => return Err(()), } @@ -305,9 +324,8 @@ impl Future for PeerServer { // Handle packets coming from the local tunnel loop { - match self.peek_from_tun_and_handle() { - Ok(false) => break, - Err(_) => return Err(()), + match self.peek_from_tun_and_handle().map_err(|e| { warn!("TUN ERR: {:?}", e); e }) { + Ok(false) | Err(_) => break, _ => {} } } diff --git a/src/main.rs b/src/main.rs index ddade34..4efebf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,7 @@ extern crate tokio_uds; extern crate tokio_utun; extern crate tokio_timer; extern crate treebitmap; +extern crate x25519_dalek; mod consts; mod error; diff --git a/src/noise.rs b/src/noise.rs index beddbfa..3e08099 100644 --- a/src/noise.rs +++ b/src/noise.rs @@ -2,6 +2,7 @@ use blake2_rfc::blake2s::{Blake2s, blake2s}; use failure::{Error, SyncFailure}; use snow::{NoiseBuilder, Session}; use snow::params::NoiseParams; +use snow::wrappers::crypto_wrapper::Dh25519; use types::{InterfaceInfo, PeerInfo}; @@ -30,10 +31,9 @@ impl Noise { Ok(Noise::new_foundation(local_privkey) .build_responder() .map_err(SyncFailure::new)?) - } - pub fn build_mac1(pub_key: &[u8], mac_input: &mut [u8], mac_output: &mut [u8]) { + pub fn build_mac1(pub_key: &[u8], mac_input: &[u8], mac_output: &mut [u8]) { debug_assert!(mac_output.len() == 16); let mut mac_key_input = [0; 40]; mac_key_input[..8].copy_from_slice(b"mac1----"); @@ -42,4 +42,16 @@ impl Noise { let mac = blake2s(16, mac_key.as_bytes(), mac_input); mac_output.copy_from_slice(mac.as_bytes()); } + + pub fn verify_mac1(pub_key: &[u8], mac_input: &[u8], mac: &[u8]) -> Result<(), Error> { + debug_assert!(mac.len() == 16); + let mut mac_key_input = [0; 40]; + mac_key_input[..8].copy_from_slice(b"mac1----"); + mac_key_input[8..40].copy_from_slice(pub_key); + let mac_key = blake2s(32, &[], &mac_key_input); + let our_mac = blake2s(16, mac_key.as_bytes(), mac_input); + + ensure!(mac == our_mac.as_bytes(), "mac mismatch"); + Ok(()) + } } diff --git a/src/protocol/peer.rs b/src/protocol/peer.rs index 2afb4c4..1852569 100644 --- a/src/protocol/peer.rs +++ b/src/protocol/peer.rs @@ -196,7 +196,7 @@ impl Peer { let mut next_session = Session::with_their_index(noise, their_index); let next_index = next_session.our_index; let response_packet = self.get_response_packet(&mut next_session)?; - self.set_next_session(next_session); + self.set_next_session(next_session.into_transport_mode()); self.info.endpoint = Some(addr); // update peer endpoint after successful authentication self.last_handshake_tai64n = Some(timestamp); @@ -205,14 +205,14 @@ impl Peer { } fn get_response_packet(&mut self, next_session: &mut Session) -> Result<Vec<u8>, Error> { - let mut packet = vec![0; 76]; + let mut packet = vec![0; 92]; packet[0] = 2; /* Type: Response */ LittleEndian::write_u32(&mut packet[4..], next_session.our_index); LittleEndian::write_u32(&mut packet[8..], next_session.their_index); next_session.noise.write_message(&[], &mut packet[12..]).map_err(SyncFailure::new)?; { - let (mac_in, mac_out) = packet.split_at_mut(44); + let (mac_in, mac_out) = packet.split_at_mut(60); Noise::build_mac1(&self.info.pub_key, mac_in, &mut mac_out[..16]); } @@ -222,9 +222,8 @@ impl Peer { pub fn process_incoming_handshake_response(&mut self, packet: &[u8]) -> Result<Option<u32>, Error> { let their_index = LittleEndian::read_u32(&packet[4..]); let mut session = mem::replace(&mut self.sessions.next, None).ok_or_else(|| format_err!("no next session"))?; - let len = session.noise.read_message(&packet[12..60], &mut []).map_err(SyncFailure::new)?; + let _ = session.noise.read_message(&packet[12..60], &mut []).map_err(SyncFailure::new)?; - ensure!(len == 0, "non-zero payload length in handshake response"); session.their_index = their_index; let session = session.into_transport_mode(); |