Skip to content

Commit abf60b2

Browse files
committed
Auto merge of #30430 - mmcco:master, r=alexcrichton
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.
2 parents cef0d0f + 9fde3e9 commit abf60b2

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

src/libstd/rand/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
//! if the entropy pool is very small, such as immediately after first booting.
4848
//! Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
4949
//! pool is not initialized yet, but it does not block once initialized.
50+
//! `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD.
5051
//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
5152
//! If an application does not have `getrandom` and likely to be run soon after first booting,
5253
//! or on a system with very few entropy sources, one should consider using `/dev/random` via

src/libstd/rand/os.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
1414
pub use self::imp::OsRng;
1515

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

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

182+
#[cfg(target_os = "openbsd")]
183+
mod imp {
184+
use io;
185+
use mem;
186+
use libc::c_long;
187+
use sys::os::errno;
188+
use rand::Rng;
189+
190+
/// A random number generator that retrieves randomness straight from
191+
/// the operating system. Platform sources:
192+
///
193+
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
194+
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
195+
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
196+
/// service provider with the `PROV_RSA_FULL` type.
197+
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
198+
/// - OpenBSD: uses the `getentropy(2)` system call.
199+
///
200+
/// This does not block.
201+
pub struct OsRng {
202+
// dummy field to ensure that this struct cannot be constructed outside
203+
// of this module
204+
_dummy: (),
205+
}
206+
207+
impl OsRng {
208+
/// Create a new `OsRng`.
209+
pub fn new() -> io::Result<OsRng> {
210+
Ok(OsRng { _dummy: () })
211+
}
212+
}
213+
214+
impl Rng for OsRng {
215+
fn next_u32(&mut self) -> u32 {
216+
let mut v = [0; 4];
217+
self.fill_bytes(&mut v);
218+
unsafe { mem::transmute(v) }
219+
}
220+
fn next_u64(&mut self) -> u64 {
221+
let mut v = [0; 8];
222+
self.fill_bytes(&mut v);
223+
unsafe { mem::transmute(v) }
224+
}
225+
fn fill_bytes(&mut self, v: &mut [u8]) {
226+
// getentropy(2) permits a maximum buffer size of 256 bytes
227+
for s in v.chunks_mut(256) {
228+
let ret = unsafe {
229+
libc::syscall(libc::NR_GETENTROPY, s.as_mut_ptr(), s.len())
230+
};
231+
if ret == -1 {
232+
panic!("unexpected getentropy error: {}", errno());
233+
}
234+
}
235+
}
236+
}
237+
}
238+
181239
#[cfg(target_os = "ios")]
182240
mod imp {
183241
#[cfg(stage0)] use prelude::v1::*;
@@ -196,6 +254,7 @@ mod imp {
196254
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
197255
/// service provider with the `PROV_RSA_FULL` type.
198256
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
257+
/// - OpenBSD: uses the `getentropy(2)` system call.
199258
///
200259
/// This does not block.
201260
pub struct OsRng {
@@ -261,6 +320,7 @@ mod imp {
261320
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
262321
/// service provider with the `PROV_RSA_FULL` type.
263322
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
323+
/// - OpenBSD: uses the `getentropy(2)` system call.
264324
///
265325
/// This does not block.
266326
pub struct OsRng {

0 commit comments

Comments
 (0)