Add support for kernel randomness for Fuchsia

Wire up cprng syscall as provider for rand::os::OsRng on Fuchsia.
This commit is contained in:
Raph Levien 2016-10-24 16:42:57 -07:00
parent 4879166194
commit 592d7bfb3a
2 changed files with 55 additions and 1 deletions

View File

@ -58,6 +58,8 @@ fn main() {
println!("cargo:rustc-link-lib=ws2_32");
println!("cargo:rustc-link-lib=userenv");
println!("cargo:rustc-link-lib=shell32");
} else if target.contains("fuchsia") {
println!("cargo:rustc-link-lib=magenta");
}
}

View File

@ -27,7 +27,8 @@ fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
#[cfg(all(unix,
not(target_os = "ios"),
not(target_os = "openbsd"),
not(target_os = "freebsd")))]
not(target_os = "freebsd"),
not(target_os = "fuchsia")))]
mod imp {
use self::OsRngInner::*;
use super::{next_u32, next_u64};
@ -339,3 +340,54 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
}
}
}
#[cfg(target_os = "fuchsia")]
mod imp {
use super::{next_u32, next_u64};
use io;
use rand::Rng;
#[link(name = "magenta")]
extern {
fn mx_cprng_draw(buffer: *mut u8, len: usize) -> isize;
}
fn getrandom(buf: &mut [u8]) -> isize {
unsafe { mx_cprng_draw(buf.as_mut_ptr(), buf.len()) }
}
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 mut buf = v;
while !buf.is_empty() {
let ret = getrandom(buf);
if ret < 0 {
panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
ret, buf.len());
}
let move_buf = buf;
buf = &mut move_buf[(ret as usize)..];
}
}
}
}