Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP refactor: de-couple from Instant::now #393

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions boringtun/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ use socket2::{Domain, Protocol, Type};
use tun::TunSocket;

use dev_lock::{Lock, LockReadGuard};
use std::time::{Instant, SystemTime};

const HANDSHAKE_RATE_LIMIT: u64 = 100; // The number of handshakes per second we can tolerate before using cookies

Expand Down Expand Up @@ -334,6 +335,11 @@ impl Device {
keepalive,
next_index,
None,
Instant::now(),
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs(),
);

let peer = Peer::new(tunn, next_index, endpoint, allowed_ips, preshared_key);
Expand Down Expand Up @@ -461,7 +467,11 @@ impl Device {
return;
}

let rate_limiter = Arc::new(RateLimiter::new(&public_key, HANDSHAKE_RATE_LIMIT));
let rate_limiter = Arc::new(RateLimiter::new(
&public_key,
HANDSHAKE_RATE_LIMIT,
Instant::now(),
));

for peer in self.peers.values_mut() {
peer.lock().tunnel.set_static_private(
Expand Down Expand Up @@ -524,7 +534,7 @@ impl Device {
// Reset the rate limiter every second give or take
Box::new(|d, _| {
if let Some(r) = d.rate_limiter.as_ref() {
r.reset_count()
r.reset_count(Instant::now())
}
Action::Continue
}),
Expand Down Expand Up @@ -669,7 +679,8 @@ impl Device {
if flush {
// Flush pending queue
while let TunnResult::WriteToNetwork(packet) =
p.tunnel.decapsulate(None, &[], &mut t.dst_buf[..])
p.tunnel
.decapsulate(None, &[], &mut t.dst_buf[..], Instant::now())
{
let _: Result<_, _> = udp.send_to(packet, &addr);
}
Expand Down Expand Up @@ -724,6 +735,7 @@ impl Device {
Some(peer_addr),
&t.src_buf[..read_bytes],
&mut t.dst_buf[..],
Instant::now(),
) {
TunnResult::Done => {}
TunnResult::Err(e) => eprintln!("Decapsulate error {:?}", e),
Expand All @@ -746,7 +758,8 @@ impl Device {
if flush {
// Flush pending queue
while let TunnResult::WriteToNetwork(packet) =
p.tunnel.decapsulate(None, &[], &mut t.dst_buf[..])
p.tunnel
.decapsulate(None, &[], &mut t.dst_buf[..], Instant::now())
{
let _: Result<_, _> = udp.send(packet);
}
Expand Down Expand Up @@ -806,7 +819,10 @@ impl Device {
None => continue,
};

match peer.tunnel.encapsulate(src, &mut t.dst_buf[..]) {
match peer
.tunnel
.encapsulate(src, &mut t.dst_buf[..], Instant::now())
{
TunnResult::Done => {}
TunnResult::Err(e) => {
tracing::error!(message = "Encapsulate error", error = ?e)
Expand Down
3 changes: 2 additions & 1 deletion boringtun/src/device/peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::str::FromStr;

use crate::device::{AllowedIps, Error};
use crate::noise::{Tunn, TunnResult};
use std::time::Instant;

#[derive(Default, Debug)]
pub struct Endpoint {
Expand Down Expand Up @@ -71,7 +72,7 @@ impl Peer {
}

pub fn update_timers<'a>(&mut self, dst: &'a mut [u8]) -> TunnResult<'a> {
self.tunnel.update_timers(dst)
self.tunnel.update_timers(Instant::now(), dst)
}

pub fn endpoint(&self) -> parking_lot::RwLockReadGuard<'_, Endpoint> {
Expand Down
36 changes: 16 additions & 20 deletions boringtun/src/noise/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
use super::{HandshakeInit, HandshakeResponse, PacketCookieReply};
use crate::noise::errors::WireGuardError;
use crate::noise::session::Session;
#[cfg(not(feature = "mock-instant"))]
use crate::sleepyinstant::Instant;
use crate::x25519;
use aead::{Aead, Payload};
use blake2::digest::{FixedOutput, KeyInit};
Expand All @@ -14,10 +12,7 @@ use chacha20poly1305::XChaCha20Poly1305;
use rand_core::OsRng;
use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
use std::convert::TryInto;
use std::time::{Duration, SystemTime};

#[cfg(feature = "mock-instant")]
use mock_instant::Instant;
use std::time::{Duration, Instant};

pub(crate) const LABEL_MAC1: &[u8; 8] = b"mac1----";
pub(crate) const LABEL_COOKIE: &[u8; 8] = b"cookie--";
Expand Down Expand Up @@ -168,26 +163,24 @@ struct Tai64N {
#[derive(Debug)]
/// This struct computes a [Tai64N](https://cr.yp.to/libtai/tai64.html) timestamp from current system time
struct TimeStamper {
duration_at_start: Duration,
instant_at_start: Instant,
unix_start: Duration,
instant_now: Instant,
}

impl TimeStamper {
/// Create a new TimeStamper
pub fn new() -> TimeStamper {
pub fn new(instant_now: Instant, unix_now: u64) -> TimeStamper {
TimeStamper {
duration_at_start: SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap(),
instant_at_start: Instant::now(),
unix_start: Duration::from_secs(unix_now),
instant_now,
}
}

/// Take time reading and generate a 12 byte timestamp
pub fn stamp(&self) -> [u8; 12] {
pub fn stamp(&self, now: Instant) -> [u8; 12] {
const TAI64_BASE: u64 = (1u64 << 62) + 37;
let mut ext_stamp = [0u8; 12];
let stamp = Instant::now().duration_since(self.instant_at_start) + self.duration_at_start;
let stamp = now.duration_since(self.instant_now) + self.unix_start;
ext_stamp[0..8].copy_from_slice(&(stamp.as_secs() + TAI64_BASE).to_be_bytes());
ext_stamp[8..12].copy_from_slice(&stamp.subsec_nanos().to_be_bytes());
ext_stamp
Expand Down Expand Up @@ -414,6 +407,8 @@ impl Handshake {
peer_static_public: x25519::PublicKey,
global_idx: u32,
preshared_key: Option<[u8; 32]>,
now: Instant,
unix_now: u64,
) -> Handshake {
let params = NoiseParams::new(
static_private,
Expand All @@ -428,7 +423,7 @@ impl Handshake {
previous: HandshakeState::None,
state: HandshakeState::None,
last_handshake_timestamp: Tai64N::zero(),
stamper: TimeStamper::new(),
stamper: TimeStamper::new(now, unix_now),
cookies: Default::default(),
last_rtt: None,
}
Expand Down Expand Up @@ -565,6 +560,7 @@ impl Handshake {
pub(super) fn receive_handshake_response(
&mut self,
packet: HandshakeResponse,
now: Instant,
) -> Result<Session, WireGuardError> {
// Check if there is a handshake awaiting a response and return the correct one
let (state, is_previous) = match (&self.state, &self.previous) {
Expand Down Expand Up @@ -633,7 +629,7 @@ impl Handshake {
let temp2 = b2s_hmac(&temp1, &[0x01]);
let temp3 = b2s_hmac2(&temp1, &temp2, &[0x02]);

let rtt_time = Instant::now().duration_since(state.time_sent);
let rtt_time = now.duration_since(state.time_sent);
self.last_rtt = Some(rtt_time.as_millis() as u32);

if is_previous {
Expand Down Expand Up @@ -709,6 +705,7 @@ impl Handshake {
pub(super) fn format_handshake_initiation<'a>(
&mut self,
dst: &'a mut [u8],
now: Instant,
) -> Result<&'a mut [u8], WireGuardError> {
if dst.len() < super::HANDSHAKE_INIT_SZ {
return Err(WireGuardError::DestinationBufferTooSmall);
Expand Down Expand Up @@ -766,20 +763,19 @@ impl Handshake {
// key = HMAC(temp, initiator.chaining_key || 0x2)
let key = b2s_hmac2(&temp, &chaining_key, &[0x02]);
// msg.encrypted_timestamp = AEAD(key, 0, TAI64N(), initiator.hash)
let timestamp = self.stamper.stamp();
let timestamp = self.stamper.stamp(now);
aead_chacha20_seal(encrypted_timestamp, &key, 0, &timestamp, &hash);
// initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp)
hash = b2s_hash(&hash, encrypted_timestamp);

let time_now = Instant::now();
self.previous = std::mem::replace(
&mut self.state,
HandshakeState::InitSent(HandshakeInitSentState {
local_index,
chaining_key,
hash,
ephemeral_private,
time_sent: time_now,
time_sent: now,
}),
);

Expand Down
Loading