/
bsd_arandom.rs
54 lines (50 loc) · 1.83 KB
/
bsd_arandom.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Implementation for FreeBSD and NetBSD
use crate::{util_libc::sys_fill_exact, Error};
use core::ptr;
unsafe fn kern_arnd(dst: *mut u8, mut len: usize) -> libc::ssize_t {
static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND];
// TODO: use `cast` on MSRV bump to 1.38
let ret = libc::sysctl(
MIB.as_ptr(),
MIB.len() as libc::c_uint,
dst as *mut libc::c_void,
&mut len,
ptr::null(),
0,
);
if ret == -1 {
-1
} else {
len as libc::ssize_t
}
}
pub unsafe fn getrandom_inner(mut dst: *mut u8, mut len: usize) -> Result<(), Error> {
// getrandom(2) was introduced in FreeBSD 12.0 and NetBSD 10.0
#[cfg(target_os = "freebsd")]
{
use crate::util_libc::Weak;
static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") };
type GetRandomFn =
unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
if let Some(fptr) = GETRANDOM.ptr() {
let func: GetRandomFn = core::mem::transmute(fptr);
return sys_fill_exact(dst, len, |dst, len| func(dst, len, 0));
}
}
// Both FreeBSD and NetBSD will only return up to 256 bytes at a time, and
// older NetBSD kernels will fail on longer buffers.
while len != 0 {
let chunk_len = core::cmp::min(len, 256);
sys_fill_exact(dst, chunk_len, |dst, len| kern_arnd(dst, len))?;
dst = dst.add(chunk_len);
len -= chunk_len;
}
Ok(())
}