diff options
| author | Aaron Gallagher <_@habnab.it> | 2016-08-14 08:27:11 +0000 |
|---|---|---|
| committer | Aaron Gallagher <_@habnab.it> | 2016-08-21 16:41:44 -0700 |
| commit | 0a70944e043db082353ed05cfa80994f6c56feae (patch) | |
| tree | 336cf4fe42c19d9de488bc292bd5aa43bf3a008b /src/libstd/sys | |
| parent | ef6aab2935a504787d01b1d9165d41b184a6027c (diff) | |
| download | rust-0a70944e043db082353ed05cfa80994f6c56feae.tar.gz rust-0a70944e043db082353ed05cfa80994f6c56feae.zip | |
Use the kernel arc4rand for FreeBSD OsRng.
This means that /dev/urandom doesn't have to be opened.
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/unix/rand.rs | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 4e6d801d191..e4ca8344ee2 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -24,7 +24,10 @@ fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 { unsafe { mem::transmute::<[u8; 8], u64>(buf) } } -#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))] +#[cfg(all(unix, + not(target_os = "ios"), + not(target_os = "openbsd"), + not(target_os = "freebsd")))] mod imp { use self::OsRngInner::*; use super::{next_u32, next_u64}; @@ -282,3 +285,51 @@ mod imp { } } } + +#[cfg(target_os = "freebsd")] +mod imp { + use super::{next_u32, next_u64}; + + use io; + use libc; + use rand::Rng; + use ptr; + + pub struct OsRng { + // dummy field to ensure that this struct cannot be constructed outside + // of this module + _dummy: (), + } + + impl OsRng { + /// Create a new `OsRng`. + pub fn new() -> io::Result<OsRng> { + Ok(OsRng { _dummy: () }) + } + } + + impl Rng for OsRng { + fn next_u32(&mut self) -> u32 { + next_u32(&mut |v| self.fill_bytes(v)) + } + fn next_u64(&mut self) -> u64 { + next_u64(&mut |v| self.fill_bytes(v)) + } + fn fill_bytes(&mut self, v: &mut [u8]) { + let mib = [libc::CTL_KERN, libc::KERN_ARND]; + // kern.arandom permits a maximum buffer size of 256 bytes + for s in v.chunks_mut(256) { + let mut s_len = s.len(); + let ret = unsafe { + libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint, + s.as_mut_ptr() as *mut _, &mut s_len, + ptr::null(), 0) + }; + if ret == -1 || s_len != s.len() { + panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})", + ret, s.len(), s_len); + } + } + } + } +} |
