diff options
| author | murilo ijanc | 2026-03-24 15:04:03 -0300 |
|---|---|---|
| committer | murilo ijanc | 2026-03-24 15:04:03 -0300 |
| commit | 9821aabf0b50d2487b07502d3d2cd89e7d62bdbe (patch) | |
| tree | 53da095ff90cc755bac3d4bf699172b5e8cd07d6 /src/sys.rs | |
| download | tesseras-dht-9821aabf0b50d2487b07502d3d2cd89e7d62bdbe.tar.gz | |
Initial commitv0.1.0
NAT-aware Kademlia DHT library for peer-to-peer networks.
Features:
- Distributed key-value storage (iterative FIND_NODE, FIND_VALUE, STORE)
- NAT traversal via DTUN hole-punching and proxy relay
- Reliable Datagram Protocol (RDP) with 7-state connection machine
- Datagram transport with automatic fragmentation/reassembly
- Ed25519 packet authentication
- 256-bit node IDs (Ed25519 public keys)
- Rate limiting, ban list, and eclipse attack mitigation
- Persistence and metrics
- OpenBSD and Linux support
Diffstat (limited to 'src/sys.rs')
| -rw-r--r-- | src/sys.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/sys.rs b/src/sys.rs new file mode 100644 index 0000000..e4d5b7e --- /dev/null +++ b/src/sys.rs @@ -0,0 +1,127 @@ +//! Cryptographically secure random bytes. +//! +//! Uses the best available platform source: +//! - OpenBSD/macOS: arc4random_buf(3) +//! - Linux/FreeBSD: getrandom(2) +//! - Fallback: /dev/urandom + +/// Fill buffer with cryptographically secure random +/// bytes. +pub fn random_bytes(buf: &mut [u8]) { + platform::fill(buf); +} + +#[cfg(any(target_os = "openbsd", target_os = "macos"))] +mod platform { + use std::ffi::c_void; + + // SAFETY: arc4random_buf always fills the entire + // buffer. Pointer valid from mutable slice. + unsafe extern "C" { + fn arc4random_buf(buf: *mut c_void, nbytes: usize); + } + + pub fn fill(buf: &mut [u8]) { + unsafe { + arc4random_buf(buf.as_mut_ptr() as *mut c_void, buf.len()); + } + } +} + +#[cfg(target_os = "linux")] +mod platform { + pub fn fill(buf: &mut [u8]) { + // getrandom(2) — available since Linux 3.17 + // Flags: 0 = block until entropy available + let ret = unsafe { + libc_getrandom( + buf.as_mut_ptr() as *mut std::ffi::c_void, + buf.len(), + 0, + ) + }; + if ret < 0 { + // Fallback to /dev/urandom + urandom_fill(buf); + } + } + + unsafe extern "C" { + fn getrandom( + buf: *mut std::ffi::c_void, + buflen: usize, + flags: std::ffi::c_uint, + ) -> isize; + } + + // Rename to avoid conflict with the syscall + unsafe fn libc_getrandom( + buf: *mut std::ffi::c_void, + buflen: usize, + flags: std::ffi::c_uint, + ) -> isize { + getrandom(buf, buflen, flags) + } + + fn urandom_fill(buf: &mut [u8]) { + use std::io::Read; + let mut f = std::fs::File::open("/dev/urandom").expect( + "FATAL: cannot open /dev/urandom — no secure randomness available", + ); + f.read_exact(buf).expect("FATAL: cannot read /dev/urandom"); + } +} + +#[cfg(target_os = "freebsd")] +mod platform { + use std::ffi::c_void; + + unsafe extern "C" { + fn arc4random_buf(buf: *mut c_void, nbytes: usize); + } + + pub fn fill(buf: &mut [u8]) { + unsafe { + arc4random_buf(buf.as_mut_ptr() as *mut c_void, buf.len()); + } + } +} + +#[cfg(not(any( + target_os = "openbsd", + target_os = "macos", + target_os = "linux", + target_os = "freebsd" +)))] +mod platform { + pub fn fill(buf: &mut [u8]) { + use std::io::Read; + let mut f = std::fs::File::open("/dev/urandom").expect( + "FATAL: cannot open /dev/urandom — no secure randomness available", + ); + f.read_exact(buf).expect("FATAL: cannot read /dev/urandom"); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn random_bytes_not_zero() { + let mut buf = [0u8; 32]; + random_bytes(&mut buf); + + // Probability of all zeros: 2^-256 + assert!(buf.iter().any(|&b| b != 0)); + } + + #[test] + fn random_bytes_different_calls() { + let mut a = [0u8; 32]; + let mut b = [0u8; 32]; + random_bytes(&mut a); + random_bytes(&mut b); + assert_ne!(a, b); + } +} |