diff --git a/src/freebsd.rs b/src/freebsd.rs index 6e0dd970c..0ac4a61eb 100644 --- a/src/freebsd.rs +++ b/src/freebsd.rs @@ -14,21 +14,30 @@ use std::io; use core::ptr; use core::num::NonZeroU32; +fn kern_arnd(buf: &mut [u8]) -> Result { + static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND]; + let mut len = buf.len(); + let ret = unsafe { + libc::sysctl( + MIB.as_ptr(), + MIB.len() as libc::c_uint, + buf.as_mut_ptr() as *mut _, + &mut len, + ptr::null(), + 0, + ) + }; + if ret == -1 { + error!("freebsd: kern.arandom syscall failed"); + return Err(io::Error::last_os_error().into()); + } + Ok(len) +} + pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { - let mib = [libc::CTL_KERN, libc::KERN_ARND]; - // kern.arandom permits a maximum buffer size of 256 bytes - for chunk in dest.chunks_mut(256) { - let mut len = chunk.len(); - let ret = unsafe { - libc::sysctl( - mib.as_ptr(), mib.len() as libc::c_uint, - chunk.as_mut_ptr() as *mut _, &mut len, ptr::null(), 0, - ) - }; - if ret == -1 || len != chunk.len() { - error!("freebsd: kern.arandom syscall failed"); - return Err(io::Error::last_os_error().into()); - } + let mut start = 0; + while start < dest.len() { + start += kern_arnd(&mut dest[start..])?; } Ok(()) }