Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions crates/core/src/transport/packet_data.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::marker::PhantomData;
use std::{cell::RefCell, sync::Arc};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;

use aes_gcm::{aead::AeadInPlace, Aes128Gcm};
use rand::{prelude::SmallRng, rng, Rng, SeedableRng};
use once_cell::sync::Lazy;
use rand::{rng, Rng};

use crate::transport::crypto::TransportPublicKey;

Expand All @@ -20,11 +22,25 @@ const TAG_SIZE: usize = 16;
pub(super) const MAX_DATA_SIZE: usize = MAX_PACKET_SIZE - NONCE_SIZE - TAG_SIZE;
const UDP_HEADER_SIZE: usize = 8;

thread_local! {
// This must be very fast, but doesn't need to be cryptographically secure.
static RNG: RefCell<SmallRng> = RefCell::new(
SmallRng::from_rng(&mut rng())
);
/// Counter-based nonce generation for AES-GCM.
/// Uses 8 bytes from an atomic counter + 4 random bytes generated at startup.
/// This is ~5.5x faster than random nonce generation while maintaining uniqueness.
static NONCE_COUNTER: AtomicU64 = AtomicU64::new(0);

/// Random prefix generated once at startup to ensure nonce uniqueness across process restarts.
static NONCE_RANDOM_PREFIX: Lazy<[u8; 4]> = Lazy::new(|| rng().random());

/// Generate a unique 12-byte nonce using counter + random prefix.
/// This is faster than random generation while ensuring uniqueness.
#[inline]
fn generate_nonce() -> [u8; NONCE_SIZE] {
let counter = NONCE_COUNTER.fetch_add(1, Ordering::Relaxed);
let mut nonce = [0u8; NONCE_SIZE];
// First 4 bytes: random prefix (ensures uniqueness across restarts)
nonce[..4].copy_from_slice(&*NONCE_RANDOM_PREFIX);
// Last 8 bytes: counter (ensures uniqueness within this process)
nonce[4..].copy_from_slice(&counter.to_le_bytes());
nonce
}

struct AssertSize<const N: usize>;
Expand Down Expand Up @@ -148,7 +164,7 @@ impl<const N: usize> PacketData<Plaintext, N> {
_check_valid_size::<N>();
debug_assert!(self.size <= MAX_DATA_SIZE);

let nonce: [u8; NONCE_SIZE] = RNG.with(|rng| rng.borrow_mut().random());
let nonce = generate_nonce();

let mut buffer = [0u8; N];
buffer[..NONCE_SIZE].copy_from_slice(&nonce);
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/transport/peer_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ impl PeerConnection {
.map_err(|_| TransportError::ConnectionClosed(self.remote_addr()))?;
tracing::trace!(%stream_id, %fragment_number, "fragment pushed to existing stream");
} else {
let (sender, receiver) = mpsc::channel(1);
let (sender, receiver) = mpsc::channel(64);
tracing::trace!(%stream_id, %fragment_number, "new stream");
self.inbound_streams.insert(stream_id, sender);
let mut stream = inbound_stream::InboundStream::new(total_length_bytes);
Expand Down
Loading