Skip to content

Commit

Permalink
Auto merge of rust-lang#30430 - mmcco:master, r=alexcrichton
Browse files Browse the repository at this point in the history
Rust already supports Linux's getrandom(2), which is very similar and
was based on getentropy(2). This is a pretty clean, simple addition that
uses the same approach as the iOS randomness API support.
  • Loading branch information
bors committed Dec 19, 2015
2 parents cef0d0f + 9fde3e9 commit abf60b2
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/libstd/rand/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
//! if the entropy pool is very small, such as immediately after first booting.
//! Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
//! pool is not initialized yet, but it does not block once initialized.
//! `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD.
//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
//! If an application does not have `getrandom` and likely to be run soon after first booting,
//! or on a system with very few entropy sources, one should consider using `/dev/random` via
Expand Down
62 changes: 61 additions & 1 deletion src/libstd/rand/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
use self::OsRngInner::*;

Expand Down Expand Up @@ -131,6 +131,7 @@ mod imp {
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
/// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng {
Expand Down Expand Up @@ -178,6 +179,63 @@ mod imp {
}
}

#[cfg(target_os = "openbsd")]
mod imp {
use io;
use mem;
use libc::c_long;
use sys::os::errno;
use rand::Rng;

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
/// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
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 {
let mut v = [0; 4];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn next_u64(&mut self) -> u64 {
let mut v = [0; 8];
self.fill_bytes(&mut v);
unsafe { mem::transmute(v) }
}
fn fill_bytes(&mut self, v: &mut [u8]) {
// getentropy(2) permits a maximum buffer size of 256 bytes
for s in v.chunks_mut(256) {
let ret = unsafe {
libc::syscall(libc::NR_GETENTROPY, s.as_mut_ptr(), s.len())
};
if ret == -1 {
panic!("unexpected getentropy error: {}", errno());
}
}
}
}
}

#[cfg(target_os = "ios")]
mod imp {
#[cfg(stage0)] use prelude::v1::*;
Expand All @@ -196,6 +254,7 @@ mod imp {
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
/// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng {
Expand Down Expand Up @@ -261,6 +320,7 @@ mod imp {
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
/// - OpenBSD: uses the `getentropy(2)` system call.
///
/// This does not block.
pub struct OsRng {
Expand Down

0 comments on commit abf60b2

Please sign in to comment.