getrandom/
lib.rs

1// Overwrite links to crate items with intra-crate links
2//! [`Error::UNEXPECTED`]: Error::UNEXPECTED
3//! [`fill_uninit`]: fill_uninit
4
5#![no_std]
6#![doc(
7    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
8    html_favicon_url = "https://www.rust-lang.org/favicon.ico"
9)]
10#![doc = include_str!("../README.md")]
11#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
12#![cfg_attr(docsrs, feature(doc_auto_cfg))]
13#![deny(
14    clippy::cast_lossless,
15    clippy::cast_possible_truncation,
16    clippy::cast_possible_wrap,
17    clippy::cast_precision_loss,
18    clippy::cast_ptr_alignment,
19    clippy::cast_sign_loss,
20    clippy::char_lit_as_u8,
21    clippy::checked_conversions,
22    clippy::fn_to_numeric_cast,
23    clippy::fn_to_numeric_cast_with_truncation,
24    clippy::ptr_as_ptr,
25    clippy::unnecessary_cast,
26    clippy::useless_conversion
27)]
28
29#[macro_use]
30extern crate cfg_if;
31
32use core::mem::MaybeUninit;
33
34mod backends;
35mod error;
36mod util;
37
38#[cfg(feature = "std")]
39mod error_std_impls;
40
41pub use crate::error::Error;
42
43/// Fill `dest` with random bytes from the system's preferred random number source.
44///
45/// This function returns an error on any failure, including partial reads. We
46/// make no guarantees regarding the contents of `dest` on error. If `dest` is
47/// empty, `getrandom` immediately returns success, making no calls to the
48/// underlying operating system.
49///
50/// Blocking is possible, at least during early boot; see module documentation.
51///
52/// In general, `getrandom` will be fast enough for interactive usage, though
53/// significantly slower than a user-space CSPRNG; for the latter consider
54/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
55///
56/// # Examples
57///
58/// ```
59/// # fn main() -> Result<(), getrandom::Error> {
60/// let mut buf = [0u8; 32];
61/// getrandom::fill(&mut buf)?;
62/// # Ok(()) }
63/// ```
64#[inline]
65pub fn fill(dest: &mut [u8]) -> Result<(), Error> {
66    // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape,
67    // and `fill_uninit` guarantees it will never de-initialize
68    // any part of `dest`.
69    fill_uninit(unsafe { util::slice_as_uninit_mut(dest) })?;
70    Ok(())
71}
72
73/// Fill potentially uninitialized buffer `dest` with random bytes from
74/// the system's preferred random number source and return a mutable
75/// reference to those bytes.
76///
77/// On successful completion this function is guaranteed to return a slice
78/// which points to the same memory as `dest` and has the same length.
79/// In other words, it's safe to assume that `dest` is initialized after
80/// this function has returned `Ok`.
81///
82/// No part of `dest` will ever be de-initialized at any point, regardless
83/// of what is returned.
84///
85/// # Examples
86///
87/// ```ignore
88/// # // We ignore this test since `uninit_array` is unstable.
89/// #![feature(maybe_uninit_uninit_array)]
90/// # fn main() -> Result<(), getrandom::Error> {
91/// let mut buf = core::mem::MaybeUninit::uninit_array::<1024>();
92/// let buf: &mut [u8] = getrandom::fill_uninit(&mut buf)?;
93/// # Ok(()) }
94/// ```
95#[inline]
96pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
97    if !dest.is_empty() {
98        backends::fill_inner(dest)?;
99    }
100
101    #[cfg(getrandom_msan)]
102    extern "C" {
103        fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize);
104    }
105
106    // SAFETY: `dest` has been fully initialized by `imp::fill_inner`
107    // since it returned `Ok`.
108    Ok(unsafe {
109        #[cfg(getrandom_msan)]
110        __msan_unpoison(dest.as_mut_ptr().cast(), dest.len());
111
112        util::slice_assume_init_mut(dest)
113    })
114}
115
116/// Get random `u32` from the system's preferred random number source.
117///
118/// # Examples
119///
120/// ```
121/// # fn main() -> Result<(), getrandom::Error> {
122/// let rng_seed = getrandom::u32()?;
123/// # Ok(()) }
124/// ```
125#[inline]
126pub fn u32() -> Result<u32, Error> {
127    backends::inner_u32()
128}
129
130/// Get random `u64` from the system's preferred random number source.
131///
132/// # Examples
133///
134/// ```
135/// # fn main() -> Result<(), getrandom::Error> {
136/// let rng_seed = getrandom::u64()?;
137/// # Ok(()) }
138/// ```
139#[inline]
140pub fn u64() -> Result<u64, Error> {
141    backends::inner_u64()
142}