From 5a7f762d6ce6b5bbdbd10f5966adc909597f37d6 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Tue, 3 Dec 2019 21:49:08 +0100 Subject: Moving away from peer threads --- src/wireguard/router/outbound.rs | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/wireguard/router/outbound.rs (limited to 'src/wireguard/router/outbound.rs') diff --git a/src/wireguard/router/outbound.rs b/src/wireguard/router/outbound.rs new file mode 100644 index 0000000..30b7c2c --- /dev/null +++ b/src/wireguard/router/outbound.rs @@ -0,0 +1,104 @@ +use super::messages::{TransportHeader, TYPE_TRANSPORT}; +use super::peer::Peer; +use super::pool::*; +use super::types::Callbacks; +use super::KeyPair; +use super::REJECT_AFTER_MESSAGES; +use super::{tun, udp, Endpoint}; + +use std::sync::mpsc::Receiver; +use std::sync::Arc; + +use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; +use zerocopy::{AsBytes, LayoutVerified}; + +pub const SIZE_TAG: usize = 16; + +pub struct Outbound { + msg: Vec, + keypair: Arc, + counter: u64, +} + +impl Outbound { + pub fn new(msg: Vec, keypair: Arc, counter: u64) -> Outbound { + Outbound { + msg, + keypair, + counter, + } + } +} + +#[inline(always)] +fn parallel>( + _peer: &Peer, + body: &mut Outbound, +) { + // make space for the tag + body.msg.extend([0u8; SIZE_TAG].iter()); + + // cast to header (should never fail) + let (mut header, packet): (LayoutVerified<&mut [u8], TransportHeader>, &mut [u8]) = + LayoutVerified::new_from_prefix(&mut body.msg[..]) + .expect("earlier code should ensure that there is ample space"); + + // set header fields + debug_assert!( + body.counter < REJECT_AFTER_MESSAGES, + "should be checked when assigning counters" + ); + header.f_type.set(TYPE_TRANSPORT); + header.f_receiver.set(body.keypair.send.id); + header.f_counter.set(body.counter); + + // create a nonce object + let mut nonce = [0u8; 12]; + debug_assert_eq!(nonce.len(), CHACHA20_POLY1305.nonce_len()); + nonce[4..].copy_from_slice(header.f_counter.as_bytes()); + let nonce = Nonce::assume_unique_for_key(nonce); + + // do the weird ring AEAD dance + let key = + LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, &body.keypair.send.key[..]).unwrap()); + + // encrypt content of transport message in-place + let end = packet.len() - SIZE_TAG; + let tag = key + .seal_in_place_separate_tag(nonce, Aad::empty(), &mut packet[..end]) + .unwrap(); + + // append tag + packet[end..].copy_from_slice(tag.as_ref()); +} + +#[inline(always)] +fn sequential>( + peer: &Peer, + body: &mut Outbound, +) { + // send to peer + let xmit = peer.send(&body.msg[..]).is_ok(); + + // trigger callback + C::send( + &peer.opaque, + body.msg.len(), + xmit, + &body.keypair, + body.counter, + ); +} + +#[inline(always)] +pub fn queue>( + peer: &Peer, +) -> &InorderQueue, Outbound> { + &peer.outbound +} + +pub fn worker>( + receiver: Receiver, Outbound>>, +) { + worker_template(receiver, parallel, sequential, queue) +} -- cgit v1.2.3-59-g8ed1b