1#[cfg(windows)]
10fn os_fill(buf: &mut [u8]) -> bool {
11 #[link(name = "bcrypt", kind = "raw-dylib")]
12 unsafe extern "system" {
13 fn BCryptGenRandom(alg: usize, buf: *mut u8, len: u32, flags: u32) -> i32;
14 }
15 const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 2;
16 for chunk in buf.chunks_mut(1 << 30) {
17 let st = unsafe { BCryptGenRandom(0, chunk.as_mut_ptr(), chunk.len() as u32, BCRYPT_USE_SYSTEM_PREFERRED_RNG) };
19 if st != 0 {
20 return false;
21 }
22 }
23 true
24}
25
26#[cfg(target_os = "linux")]
27fn os_fill(buf: &mut [u8]) -> bool {
28 const EINTR: isize = 4;
29 let mut done = 0;
30 while done < buf.len() {
31 let want = (buf.len() - done).min(1 << 25);
32 let r = unsafe { rt::os::syscall3(rt::os::SYS_GETRANDOM, buf[done..].as_mut_ptr() as usize, want, 0) };
34 if r == -EINTR {
35 continue;
36 }
37 if r <= 0 {
38 return false;
39 }
40 done += r as usize;
41 }
42 true
43}
44
45pub fn fill_random(buf: &mut [u8]) {
47 if !os_fill(buf) {
48 crate::write_stderr(b"fatal: the system random number generator failed\n");
49 crate::exit(70);
50 }
51}
52
53pub fn random_bytes<const N: usize>() -> [u8; N] {
55 let mut b = [0u8; N];
56 fill_random(&mut b);
57 b
58}
59
60pub fn random_u64() -> u64 {
62 u64::from_le_bytes(random_bytes::<8>())
63}