]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | // Copyright 2018 Developers of the Rand project. |
2 | // | |
3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
4 | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
5 | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your | |
6 | // option. This file may not be copied, modified, or distributed | |
7 | // except according to those terms. | |
8 | ||
9 | //! Implementation for Linux / Android | |
10 | use crate::{ | |
11 | util::LazyBool, | |
12 | util_libc::{last_os_error, sys_fill_exact}, | |
13 | {use_file, Error}, | |
14 | }; | |
15 | ||
16 | pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { | |
17 | static HAS_GETRANDOM: LazyBool = LazyBool::new(); | |
18 | if HAS_GETRANDOM.unsync_init(is_getrandom_available) { | |
19 | sys_fill_exact(dest, |buf| unsafe { | |
20 | getrandom(buf.as_mut_ptr() as *mut libc::c_void, buf.len(), 0) | |
21 | }) | |
22 | } else { | |
23 | use_file::getrandom_inner(dest) | |
24 | } | |
25 | } | |
26 | ||
27 | fn is_getrandom_available() -> bool { | |
28 | let res = unsafe { getrandom(core::ptr::null_mut(), 0, libc::GRND_NONBLOCK) }; | |
29 | if res < 0 { | |
30 | match last_os_error().raw_os_error() { | |
31 | Some(libc::ENOSYS) => false, // No kernel support | |
32 | Some(libc::EPERM) => false, // Blocked by seccomp | |
33 | _ => true, | |
34 | } | |
35 | } else { | |
36 | true | |
37 | } | |
38 | } | |
39 | ||
40 | unsafe fn getrandom( | |
41 | buf: *mut libc::c_void, | |
42 | buflen: libc::size_t, | |
43 | flags: libc::c_uint, | |
44 | ) -> libc::ssize_t { | |
45 | libc::syscall(libc::SYS_getrandom, buf, buflen, flags) as libc::ssize_t | |
46 | } |