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