| 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 ] |
| 30 | extern crate cfg_if; |
| 31 | |
| 32 | use core::mem::MaybeUninit; |
| 33 | |
| 34 | mod backends; |
| 35 | mod error; |
| 36 | mod util; |
| 37 | |
| 38 | #[cfg (feature = "std" )] |
| 39 | mod error_std_impls; |
| 40 | |
| 41 | pub 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 ] |
| 65 | pub 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(dest:unsafe { util::slice_as_uninit_mut(slice: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 ] |
| 96 | pub 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(slice: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 ] |
| 126 | pub 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 ] |
| 140 | pub fn u64() -> Result<u64, Error> { |
| 141 | backends::inner_u64() |
| 142 | } |
| 143 | |