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

Use arc4rand(9) on FreeBSD #112

Merged
merged 3 commits into from
Aug 23, 2016
Merged
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
110 changes: 73 additions & 37 deletions src/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! Interfaces to the operating system provided random number
//! generators.

use std::io;
use std::{io, mem};
use Rng;

/// A random number generator that retrieves randomness straight from
Expand Down Expand Up @@ -40,18 +40,31 @@ impl Rng for OsRng {
fn fill_bytes(&mut self, v: &mut [u8]) { self.0.fill_bytes(v) }
}

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 = "nacl")))]
not(target_os = "nacl"),
not(target_os = "freebsd")))]
mod imp {
extern crate libc;

use super::{next_u32, next_u64};
use self::OsRngInner::*;

use std::io;
use std::fs::File;
use Rng;
use read::ReadRng;
use std::mem;

#[cfg(all(target_os = "linux",
any(target_arch = "x86_64",
Expand Down Expand Up @@ -106,18 +119,6 @@ mod imp {
}
}

fn getrandom_next_u32() -> u32 {
let mut buf: [u8; 4] = [0u8; 4];
getrandom_fill_bytes(&mut buf);
unsafe { mem::transmute::<[u8; 4], u32>(buf) }
}

fn getrandom_next_u64() -> u64 {
let mut buf: [u8; 8] = [0u8; 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",
Expand Down Expand Up @@ -179,13 +180,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),
OsReadRng(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),
OsReadRng(ref mut rng) => rng.next_u64(),
}
}
Expand All @@ -202,8 +203,9 @@ mod imp {
mod imp {
extern crate libc;

use super::{next_u32, next_u64};

use std::io;
use std::mem;
use Rng;
use self::libc::{c_int, size_t};

Expand All @@ -228,14 +230,10 @@ mod imp {

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0u8; 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 = [0u8; 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 {
Expand All @@ -248,13 +246,57 @@ mod imp {
}
}

#[cfg(target_os = "freebsd")]
mod imp {
extern crate libc;

use std::{io, ptr};
use Rng;

use super::{next_u32, next_u64};

pub struct OsRng;

impl OsRng {
pub fn new() -> io::Result<OsRng> {
Ok(OsRng)
}
}

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);
}
}
}
}
}

#[cfg(windows)]
mod imp {
use std::io;
use std::mem;
use std::ptr;
use Rng;

use super::{next_u32, next_u64};

type BOOL = i32;
type LPCSTR = *const i8;
type DWORD = u32;
Expand Down Expand Up @@ -301,14 +343,10 @@ mod imp {

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0u8; 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 = [0u8; 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]) {
// CryptGenRandom takes a DWORD (u32) for the length so we need to
Expand Down Expand Up @@ -347,6 +385,8 @@ mod imp {
use std::mem;
use Rng;

use super::{next_u32, next_u64};

pub struct OsRng(extern fn(dest: *mut libc::c_void,
bytes: libc::size_t,
read: *mut libc::size_t) -> libc::c_int);
Expand Down Expand Up @@ -390,14 +430,10 @@ mod imp {

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let mut v = [0u8; 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 = [0u8; 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 mut read = 0;
Expand Down