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}