Skip to content

Commit

Permalink
Encrypt in-place
Browse files Browse the repository at this point in the history
  • Loading branch information
Hasan6979 committed Dec 10, 2024
1 parent 82adf7b commit 8f50b1e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 26 deletions.
12 changes: 7 additions & 5 deletions neptun/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use std::thread;
use crate::noise::errors::WireGuardError;
use crate::noise::handshake::parse_handshake_anon;
use crate::noise::rate_limiter::RateLimiter;
use crate::noise::DATA_OFFSET;
use crate::noise::{Packet, Tunn, TunnResult};
use crate::x25519;
use allowed_ips::AllowedIps;
Expand Down Expand Up @@ -1025,8 +1026,9 @@ impl Device {

let peers = &d.peers_by_ip;
for _ in 0..MAX_ITR {
let src = match iface.read(&mut t.src_buf[..mtu]) {
Ok(src) => src,
let src_buf = &mut t.src_buf[DATA_OFFSET..];
let src_len = match iface.read(&mut src_buf[..mtu]) {
Ok(src) => src.len(),
Err(Error::IfaceRead(e)) => {
let ek = e.kind();
if ek == io::ErrorKind::Interrupted || ek == io::ErrorKind::WouldBlock {
Expand All @@ -1045,7 +1047,7 @@ impl Device {
}
};

let dst_addr = match Tunn::dst_address(src) {
let dst_addr = match Tunn::dst_address(&src_buf[..src_len]) {
Some(addr) => addr,
None => continue,
};
Expand All @@ -1057,14 +1059,14 @@ impl Device {


if let Some(callback) = &d.config.firewall_process_outbound_callback {
if !callback(&peer.public_key.0, src) {
if !callback(&peer.public_key.0, &src_buf[..src_len]) {
continue;
}
}

let res = {
let mut tun = peer.tunnel.lock();
tun.encapsulate(src, &mut t.dst_buf[..])
tun.encapsulate(&mut t.src_buf[..], src_len)
};
match res {
TunnResult::Done => {}
Expand Down
25 changes: 15 additions & 10 deletions neptun/src/noise/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const MAX_QUEUE_DEPTH: usize = 256;
/// number of sessions in the ring, better keep a PoT
const N_SESSIONS: usize = 8;

/// Where encrypted data resides in a data packet
pub const DATA_OFFSET: usize = 16;

#[derive(Debug)]
pub enum TunnResult<'a> {
Done,
Expand Down Expand Up @@ -271,29 +274,29 @@ impl Tunn {
/// # Panics
/// Panics if dst buffer is too small.
/// Size of dst should be at least src.len() + 32, and no less than 148 bytes.
pub fn encapsulate<'a>(&mut self, src: &[u8], dst: &'a mut [u8]) -> TunnResult<'a> {
pub fn encapsulate<'a>(&mut self, buffer: &'a mut [u8], data_len: usize) -> TunnResult<'a> {
let current = self.current;
if let Some(ref session) = self.sessions[current % N_SESSIONS] {
// Send the packet using an established session
let packet = session.format_packet_data(src, dst);
let packet = session.format_packet_data(buffer, data_len);
self.mark_timer_to_update(TimerName::TimeLastPacketSent);
// Exclude Keepalive packets from timer update.
if !src.is_empty() {
if !data_len != 0 {
self.mark_timer_to_update(TimerName::TimeLastDataPacketSent);
}
self.tx_bytes += packet.len();
return TunnResult::WriteToNetwork(packet);
}

if !src.is_empty() {
if !data_len != 0 {
// If there is no session, queue the packet for future retry,
// except if it's keepalive packet, new keepalive packets will be sent when session is created.
// This prevents double keepalive packets on initiation
self.queue_packet(src);
self.queue_packet(&buffer[..data_len]);
}

// Initiate a new handshake if none is in progress
self.format_handshake_initiation(dst, false)
self.format_handshake_initiation(buffer, false)
}

/// Receives a UDP datagram from the network and parses it.
Expand Down Expand Up @@ -393,7 +396,7 @@ impl Tunn {
// Increase the rx_bytes accordingly
self.rx_bytes += HANDSHAKE_RESP_SZ;

let keepalive_packet = session.format_packet_data(&[], dst);
let keepalive_packet = session.format_packet_data(dst, 0);
// Store new session in ring buffer
let l_idx = session.local_index();
let index = l_idx % N_SESSIONS;
Expand Down Expand Up @@ -560,7 +563,9 @@ impl Tunn {
/// Get a packet from the queue, and try to encapsulate it
fn send_queued_packet<'a>(&mut self, dst: &'a mut [u8]) -> TunnResult<'a> {
if let Some(packet) = self.dequeue_packet() {
match self.encapsulate(&packet, dst) {
let len = packet.len();
dst[..len].copy_from_slice(&packet);
match self.encapsulate(dst, len) {
TunnResult::Err(_) => {
// On error, return packet to the queue
self.requeue_packet(packet);
Expand Down Expand Up @@ -824,9 +829,9 @@ mod tests {
let mut my_dst = [0u8; 1024];
let mut their_dst = [0u8; 1024];

let sent_packet_buf = create_ipv4_udp_packet();
let mut sent_packet_buf = create_ipv4_udp_packet();

let data = my_tun.encapsulate(&sent_packet_buf, &mut my_dst);
let data = my_tun.encapsulate(&mut sent_packet_buf, sent_packet_buf.len());
assert!(matches!(data, TunnResult::WriteToNetwork(_)));
let data = if let TunnResult::WriteToNetwork(sent) = data {
sent
Expand Down
22 changes: 12 additions & 10 deletions neptun/src/noise/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: BSD-3-Clause

use super::PacketData;
use super::DATA_OFFSET;
use crate::noise::errors::WireGuardError;
use parking_lot::Mutex;
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
Expand All @@ -27,8 +28,6 @@ impl std::fmt::Debug for Session {
}
}

/// Where encrypted data resides in a data packet
const DATA_OFFSET: usize = 16;
/// The overhead of the AEAD
const AEAD_SIZE: usize = 16;

Expand Down Expand Up @@ -194,14 +193,18 @@ impl Session {
/// src - an IP packet from the interface
/// dst - pre-allocated space to hold the encapsulating UDP packet to send over the network
/// returns the size of the formatted packet
pub(super) fn format_packet_data<'a>(&self, src: &[u8], dst: &'a mut [u8]) -> &'a mut [u8] {
if dst.len() < src.len() + super::DATA_OVERHEAD_SZ {
pub(super) fn format_packet_data<'a>(
&self,
buffer: &'a mut [u8],
data_len: usize,
) -> &'a mut [u8] {
if buffer.len() < data_len + super::DATA_OVERHEAD_SZ {
panic!("The destination buffer is too small");
}

let sending_key_counter = self.sending_key_counter.fetch_add(1, Ordering::Relaxed) as u64;

let (message_type, rest) = dst.split_at_mut(4);
let (message_type, rest) = buffer.split_at_mut(4);
let (receiver_index, rest) = rest.split_at_mut(4);
let (counter, data) = rest.split_at_mut(8);

Expand All @@ -213,21 +216,20 @@ impl Session {
let n = {
let mut nonce = [0u8; 12];
nonce[4..12].copy_from_slice(&sending_key_counter.to_le_bytes());
data[..src.len()].copy_from_slice(src);
self.sender
.seal_in_place_separate_tag(
Nonce::assume_unique_for_key(nonce),
Aad::from(&[]),
&mut data[..src.len()],
&mut data[..data_len],
)
.map(|tag| {
data[src.len()..src.len() + AEAD_SIZE].copy_from_slice(tag.as_ref());
src.len() + AEAD_SIZE
data[data_len..data_len + AEAD_SIZE].copy_from_slice(tag.as_ref());
data_len + AEAD_SIZE
})
.unwrap()
};

&mut dst[..DATA_OFFSET + n]
&mut buffer[..DATA_OFFSET + n]
}

/// packet - a data packet we received from the network
Expand Down
2 changes: 1 addition & 1 deletion neptun/src/noise/timers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ impl Tunn {
}

if keepalive_required {
return self.encapsulate(&[], dst);
return self.encapsulate(&mut [], 0);
}

TunnResult::Done
Expand Down

0 comments on commit 8f50b1e

Please sign in to comment.