Auto merge of #35884 - habnabit:freebsd-arc4rand, r=alexcrichton
Use arc4rand(9) on FreeBSD From rust-lang-nursery/rand#112: >After reading through #30691 it seems that there's general agreement that using OS-provided facilities for seeding rust userland processes is fine as long as it doesn't use too much from libc. FreeBSD's `arc4random_buf(3)` is not only a whole lot of libc code, but also not even currently exposed in the libc crate. Fortunately, the mechanism `arc4random_buf(3)` et al. use for getting entropy from the kernel ([`arc4rand(9)`](https://www.freebsd.org/cgi/man.cgi?query=arc4random&apropos=0&sektion=9&manpath=FreeBSD+10.3-RELEASE&arch=default&format=html)) is exposed via `sysctl(3)` with constants that are already in the libc crate. >I haven't found too much documentation on `KERN_ARND`—it's missing or only briefly described in most of the places that cover sysctl mibs. But, from digging through the kernel source, it appears that the sysctl used in this PR is very close to just calling `arc4rand(9)` directly (with `reseed` set to 0 and no way to change it). I expected [rand](/rust-lang-nursery/rand) to reply quicker, so I tried submitting it there first. It's been a few weeks with no comment, so I don't know the state of it, but maybe someone will see it here and have an opinion. This is basically the same patch. It pains me to duplicate the code but I guess it hasn't been factored out into just one place yet.
This commit is contained in:
commit
528c6f3ed6
@ -10,14 +10,31 @@
|
||||
|
||||
pub use self::imp::OsRng;
|
||||
|
||||
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
|
||||
use mem;
|
||||
|
||||
fn next_u32(mut fill_buf: &mut FnMut(&mut [u8])) -> u32 {
|
||||
let mut buf: [u8; 4] = [0; 4];
|
||||
fill_buf(&mut buf);
|
||||
unsafe { mem::transmute::<[u8; 4], u32>(buf) }
|
||||
}
|
||||
|
||||
fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
fill_buf(&mut buf);
|
||||
unsafe { mem::transmute::<[u8; 8], u64>(buf) }
|
||||
}
|
||||
|
||||
#[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};
|
||||
|
||||
use fs::File;
|
||||
use io;
|
||||
use libc;
|
||||
use mem;
|
||||
use rand::Rng;
|
||||
use rand::reader::ReaderRng;
|
||||
use sys::os::errno;
|
||||
@ -87,18 +104,6 @@ mod imp {
|
||||
}
|
||||
}
|
||||
|
||||
fn getrandom_next_u32() -> u32 {
|
||||
let mut buf: [u8; 4] = [0; 4];
|
||||
getrandom_fill_bytes(&mut buf);
|
||||
unsafe { mem::transmute::<[u8; 4], u32>(buf) }
|
||||
}
|
||||
|
||||
fn getrandom_next_u64() -> u64 {
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
getrandom_fill_bytes(&mut buf);
|
||||
unsafe { mem::transmute::<[u8; 8], u64>(buf) }
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux",
|
||||
any(target_arch = "x86_64",
|
||||
target_arch = "x86",
|
||||
@ -163,13 +168,13 @@ mod imp {
|
||||
impl Rng for OsRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
match self.inner {
|
||||
OsGetrandomRng => getrandom_next_u32(),
|
||||
OsGetrandomRng => next_u32(&mut getrandom_fill_bytes),
|
||||
OsReaderRng(ref mut rng) => rng.next_u32(),
|
||||
}
|
||||
}
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
match self.inner {
|
||||
OsGetrandomRng => getrandom_next_u64(),
|
||||
OsGetrandomRng => next_u64(&mut getrandom_fill_bytes),
|
||||
OsReaderRng(ref mut rng) => rng.next_u64(),
|
||||
}
|
||||
}
|
||||
@ -184,9 +189,10 @@ mod imp {
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
mod imp {
|
||||
use super::{next_u32, next_u64};
|
||||
|
||||
use io;
|
||||
use libc;
|
||||
use mem;
|
||||
use sys::os::errno;
|
||||
use rand::Rng;
|
||||
|
||||
@ -205,14 +211,10 @@ mod imp {
|
||||
|
||||
impl Rng for OsRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
let mut v = [0; 4];
|
||||
self.fill_bytes(&mut v);
|
||||
unsafe { mem::transmute(v) }
|
||||
next_u32(&mut |v| self.fill_bytes(v))
|
||||
}
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
let mut v = [0; 8];
|
||||
self.fill_bytes(&mut v);
|
||||
unsafe { mem::transmute(v) }
|
||||
next_u64(&mut |v| self.fill_bytes(v))
|
||||
}
|
||||
fn fill_bytes(&mut self, v: &mut [u8]) {
|
||||
// getentropy(2) permits a maximum buffer size of 256 bytes
|
||||
@ -230,8 +232,9 @@ mod imp {
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
mod imp {
|
||||
use super::{next_u32, next_u64};
|
||||
|
||||
use io;
|
||||
use mem;
|
||||
use ptr;
|
||||
use rand::Rng;
|
||||
use libc::{c_int, size_t};
|
||||
@ -265,14 +268,10 @@ mod imp {
|
||||
|
||||
impl Rng for OsRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
let mut v = [0; 4];
|
||||
self.fill_bytes(&mut v);
|
||||
unsafe { mem::transmute(v) }
|
||||
next_u32(&mut |v| self.fill_bytes(v))
|
||||
}
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
let mut v = [0; 8];
|
||||
self.fill_bytes(&mut v);
|
||||
unsafe { mem::transmute(v) }
|
||||
next_u64(&mut |v| self.fill_bytes(v))
|
||||
}
|
||||
fn fill_bytes(&mut self, v: &mut [u8]) {
|
||||
let ret = unsafe {
|
||||
@ -286,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user