From 321d71028b7f2e99cd05dc1d04802688106a992a Mon Sep 17 00:00:00 2001 From: Tatsuya Kawano Date: Sun, 23 Oct 2016 23:06:40 +0800 Subject: [PATCH] Issue #316 - Replace `/dev/urandom` usage on *BSD Now OpenBSD and FreeBSD utilizes `arc4rand_buf()` function in their C stdlib. - Implement GFp_sysrand_chunk() in sysrand.c for OpenBSD and FreeBSD. - On OpenBSD and FreeBSD, mk/ring.mk now uses `-D_BSD_SOURCE` in `CPPFLAGS` instead of `-D_XOPEN_SOURCE=700`. TODOs: - Update docs. - Remove debug print. - Ensure FreeBSD's arc4rand_buf() is as safe as OpenBSD's. I agree to license my contributions to each file under the terms given at the top of each file I changed. --- crypto/rand/sysrand.c | 20 ++++++++++++++++++++ mk/ring.mk | 7 ++++++- src/lib.rs | 7 ++++--- src/rand.rs | 40 +++++++++++++++++++++++++++++++--------- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/crypto/rand/sysrand.c b/crypto/rand/sysrand.c index fc654b234..2510fcede 100644 --- a/crypto/rand/sysrand.c +++ b/crypto/rand/sysrand.c @@ -105,4 +105,24 @@ int GFp_sysrand_chunk(void *out, size_t requested) { return 1; } +#elif defined(__OpenBSD__) || defined(__FreeBSD__) + +#include +#include + +// DEBUG: +#include + +const size_t GFp_sysrand_chunk_max_len = ULONG_MAX; + +int GFp_sysrand_chunk(void *out, size_t requested) { + // DEBUG: + printf("calling arc4rand_buf()\n"); + + assert(requested <= GFp_sysrand_chunk_max_len); + // This function never fails so let's always return 1. + arc4random_buf(out, requested); + return 1; +} + #endif diff --git a/mk/ring.mk b/mk/ring.mk index c803f7340..29e420ce1 100644 --- a/mk/ring.mk +++ b/mk/ring.mk @@ -14,7 +14,12 @@ RING_PREFIX ?= ring/ -RING_CPPFLAGS = -I$(RING_PREFIX)include -D_XOPEN_SOURCE=700 +RING_CPPFLAGS = -I$(RING_PREFIX)include +ifneq (, $(filter openbsd freebsd, $(TARGET_SYS))) +RING_CPPFLAGS += -D_BSD_SOURCE +else +RING_CPPFLAGS += -D_XOPEN_SOURCE=700 +endif RING_SRCS = $(addprefix $(RING_PREFIX), \ crypto/aes/aes.c \ diff --git a/src/lib.rs b/src/lib.rs index b03f7ba2c..101fd826c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,9 +97,10 @@ #[cfg(feature = "internal_benches")] extern crate test as bench; -#[cfg(any(all(unix, - any(not(target_os = "linux"), - feature = "dev_urandom_fallback"))))] +#[cfg(all(unix, + any(not(target_os = "linux"), feature = "dev_urandom_fallback"), + not(any(target_os = "openbsd", + target_os = "freebsd"))))] #[macro_use] extern crate lazy_static; diff --git a/src/rand.rs b/src/rand.rs index acfeb3ab9..056ad20b4 100644 --- a/src/rand.rs +++ b/src/rand.rs @@ -25,8 +25,11 @@ //! (seccomp filters on Linux in particular). See `SystemRandom`'s //! documentation for more details. - -#[cfg(any(target_os = "linux", windows, test))] +#[cfg(any(target_os = "linux", + target_os = "openbsd", + target_os = "freebsd", + windows, + test))] use c; #[cfg(test)] @@ -107,17 +110,25 @@ impl SecureRandom for SystemRandom { } } -#[cfg(not(any(target_os = "linux", windows)))] +#[cfg(not(any(target_os = "linux", + target_os = "openbsd", + target_os = "freebsd", + windows)))] use self::urandom::fill as fill_impl; #[cfg(any(all(target_os = "linux", not(feature = "dev_urandom_fallback")), + target_os = "openbsd", + target_os = "freebsd", windows))] use self::sysrand::fill as fill_impl; #[cfg(all(target_os = "linux", feature = "dev_urandom_fallback"))] use self::sysrand_or_urandom::fill as fill_impl; -#[cfg(any(target_os = "linux", windows))] +#[cfg(any(target_os = "linux", + target_os = "openbsd", + target_os = "freebsd", + windows))] mod sysrand { use {bssl, error}; @@ -134,8 +145,10 @@ mod sysrand { // Keep the `cfg` conditions in sync with the conditions in lib.rs. #[cfg(all(unix, - not(all(target_os = "linux", - not(feature = "dev_urandom_fallback")))))] + not(any(all(target_os = "linux", + not(feature = "dev_urandom_fallback")), + target_os = "openbsd", + target_os = "freebsd"))))] mod urandom { extern crate std; use error; @@ -215,7 +228,10 @@ pub unsafe extern fn RAND_bytes(rng: *mut RAND, dest: *mut u8, } -#[cfg(any(target_os = "linux", windows))] +#[cfg(any(windows, + target_os = "linux", + target_os = "openbsd", + target_os = "freebsd"))] extern { static GFp_sysrand_chunk_max_len: c::size_t; fn GFp_sysrand_chunk(buf: *mut u8, len: c::size_t) -> c::int; @@ -333,10 +349,16 @@ mod tests { } } - #[cfg(any(target_os = "linux", windows))] + #[cfg(any(target_os = "linux", + target_os = "openbsd", + target_os = "freebsd", + windows))] fn max_chunk_len() -> usize { unsafe { super::GFp_sysrand_chunk_max_len } } - #[cfg(not(any(target_os = "linux", windows)))] + #[cfg(not(any(target_os = "linux", + target_os = "openbsd", + target_os = "freebsd", + windows)))] fn max_chunk_len() -> usize { use core; core::usize::MAX