| Joel Galenson | 4be0c6d | 2020-07-07 13:20:14 -0700 | [diff] [blame] | 1 | // Copyright 2019 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 macOS |
| 10 | use crate::util_libc::{last_os_error, Weak}; |
| 11 | use crate::{use_file, Error}; |
| 12 | use core::mem; |
| 13 | |
| 14 | type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int; |
| 15 | |
| 16 | pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { |
| 17 | static GETENTROPY: Weak = unsafe { Weak::new("getentropy\0") }; |
| 18 | if let Some(fptr) = GETENTROPY.ptr() { |
| 19 | let func: GetEntropyFn = unsafe { mem::transmute(fptr) }; |
| 20 | for chunk in dest.chunks_mut(256) { |
| 21 | let ret = unsafe { func(chunk.as_mut_ptr(), chunk.len()) }; |
| 22 | if ret != 0 { |
| 23 | let err = last_os_error(); |
| 24 | error!("getentropy syscall failed"); |
| 25 | return Err(err); |
| 26 | } |
| 27 | } |
| 28 | Ok(()) |
| 29 | } else { |
| 30 | // We fallback to reading from /dev/random instead of SecRandomCopyBytes |
| 31 | // to avoid high startup costs and linking the Security framework. |
| 32 | use_file::getrandom_inner(dest) |
| 33 | } |
| 34 | } |