Skip to main content

security/random/
mod.rs

1//! Cryptographically secure random bytes from `SecRandomCopyBytes`.
2
3use crate::error::{Result, SecurityError};
4use crate::ffi;
5use crate::private::sec_error_message;
6
7/// Stateless wrapper around Apple's default CSPRNG.
8pub struct SecureRandom;
9
10impl SecureRandom {
11    /// Fill an existing buffer with cryptographically secure random bytes.
12    ///
13    /// # Errors
14    ///
15    /// Returns an error if Security.framework rejects the random-byte request.
16    pub fn fill(buffer: &mut [u8]) -> Result<()> {
17        if buffer.is_empty() {
18            return Ok(());
19        }
20        let status = unsafe {
21            ffi::SecRandomCopyBytes(
22                ffi::kSecRandomDefault,
23                buffer.len(),
24                buffer.as_mut_ptr().cast(),
25            )
26        };
27        if status == ffi::status::SUCCESS {
28            Ok(())
29        } else {
30            Err(SecurityError::from_status(
31                "SecRandomCopyBytes",
32                status,
33                sec_error_message(status),
34            ))
35        }
36    }
37
38    /// Allocate a new `Vec<u8>` and fill it with cryptographically secure random bytes.
39    ///
40    /// # Errors
41    ///
42    /// Returns an error if Security.framework rejects the random-byte request.
43    pub fn bytes(length: usize) -> Result<Vec<u8>> {
44        let mut buffer = vec![0_u8; length];
45        Self::fill(&mut buffer)?;
46        Ok(buffer)
47    }
48}