|
| 1 | +use super::{BorrowedBuf, BorrowedCursor, Read, Result}; |
| 2 | +use crate::sys::entropy as sys; |
| 3 | + |
| 4 | +/// A reader which returns random bytes from the system entropy source. |
| 5 | +/// |
| 6 | +/// This struct is generally created by calling [`entropy()`]. Please |
| 7 | +/// see the documentation of [`entropy()`] for more details. |
| 8 | +#[derive(Debug)] |
| 9 | +#[unstable(feature = "io_entropy", issue = "none")] |
| 10 | +pub struct Entropy { |
| 11 | + insecure: bool, |
| 12 | +} |
| 13 | + |
| 14 | +impl Entropy { |
| 15 | + pub(crate) fn set_insecure(&mut self, insecure: bool) { |
| 16 | + self.insecure = insecure; |
| 17 | + } |
| 18 | +} |
| 19 | + |
| 20 | +#[unstable(feature = "io_entropy", issue = "none")] |
| 21 | +impl Read for Entropy { |
| 22 | + #[inline] |
| 23 | + fn read(&mut self, buf: &mut [u8]) -> Result<usize> { |
| 24 | + sys::Entropy { insecure: self.insecure }.read(buf) |
| 25 | + } |
| 26 | + |
| 27 | + #[inline] |
| 28 | + fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { |
| 29 | + let mut buf = BorrowedBuf::from(buf); |
| 30 | + self.read_buf_exact(buf.unfilled()) |
| 31 | + } |
| 32 | + |
| 33 | + #[inline] |
| 34 | + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { |
| 35 | + sys::Entropy { insecure: self.insecure }.read_buf(buf) |
| 36 | + } |
| 37 | + |
| 38 | + #[inline] |
| 39 | + fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { |
| 40 | + sys::Entropy { insecure: self.insecure }.read_buf_exact(buf) |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +/// Constructs a new handle to the system entropy source. |
| 45 | +/// |
| 46 | +/// Reads from the resulting reader will return high-quality random data that |
| 47 | +/// is suited for cryptographic purposes (by the standard of the platform defaults). |
| 48 | +/// |
| 49 | +/// Be aware that, because the data is of very high quality, reading high amounts |
| 50 | +/// of data can be very slow, and potentially slow down other processes requiring |
| 51 | +/// random data. Use a pseudo-random number generator if speed is important. |
| 52 | +/// |
| 53 | +/// # Platform sources |
| 54 | +/// |
| 55 | +/// | OS | Source |
| 56 | +/// |------------------|-------- |
| 57 | +/// | Linux, Android | [`getrandom`][1] if available, otherwise [`/dev/urandom`][2] after successfully polling [`/dev/random`][2] |
| 58 | +/// | Windows | [`BCryptGenRandom`][3], falling back to [`RtlGenRandom`][4] |
| 59 | +/// | macOS | [`getentropy`][5] if available, falling back to [`/dev/urandom`][6] |
| 60 | +/// | OpenBSD | [`getentropy`][7] |
| 61 | +/// | iOS, watchOS | [`SecRandomCopyBytes`][8] |
| 62 | +/// | FreeBSD | [`kern.arandom`][9] |
| 63 | +/// | NetBSD | [`kern.arandom`][10] |
| 64 | +/// | Fuchsia | [`zx_cprng_draw`][11] |
| 65 | +/// | WASM | *Unsupported* |
| 66 | +/// | WASI | [`random_get`][12] |
| 67 | +/// | Emscripten | [`getentropy`][7] |
| 68 | +/// | Redox | `rand:` |
| 69 | +/// | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure` |
| 70 | +/// | Haiku | `/dev/urandom` |
| 71 | +/// | ESP-IDF, Horizon | [`getrandom`][1] |
| 72 | +/// | Other UNIXes | `/dev/random` |
| 73 | +/// | Hermit | [`read_entropy`][13] |
| 74 | +/// | SGX | [`RDRAND`][14] |
| 75 | +/// | SOLID | `SOLID_RNG_SampleRandomBytes` |
| 76 | +/// |
| 77 | +/// [1]: https://man7.org/linux/man-pages/man2/getrandom.2.html |
| 78 | +/// [2]: https://man7.org/linux/man-pages/man7/random.7.html |
| 79 | +/// [3]: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom |
| 80 | +/// [4]: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom |
| 81 | +/// [5]: https://www.unix.com/man-page/mojave/2/getentropy/ |
| 82 | +/// [6]: https://www.unix.com/man-page/mojave/4/random/ |
| 83 | +/// [7]: https://man.openbsd.org/getentropy.2 |
| 84 | +/// [8]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc |
| 85 | +/// [9]: https://man.freebsd.org/cgi/man.cgi?query=random&sektion=4&manpath=FreeBSD+13.1-RELEASE+and+Ports |
| 86 | +/// [10]: https://man.netbsd.org/rnd.4 |
| 87 | +/// [11]: https://fuchsia.dev/fuchsia-src/reference/syscalls/cprng_draw |
| 88 | +/// [12]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md |
| 89 | +/// [13]: https://docs.rs/hermit-abi/latest/hermit_abi/fn.read_entropy.html |
| 90 | +/// [14]: https://www.intel.com/content/www/us/en/developer/articles/guide/intel-digital-random-number-generator-drng-software-implementation-guide.html |
| 91 | +/// |
| 92 | +/// # Examples |
| 93 | +/// |
| 94 | +/// Generating a seed for a random number generator: |
| 95 | +/// |
| 96 | +/// ```rust |
| 97 | +/// #![feature(io_entropy)] |
| 98 | +/// |
| 99 | +/// # use std::io::Result; |
| 100 | +/// # fn main() -> Result<()> { |
| 101 | +/// use std::io::{entropy, Read}; |
| 102 | +/// |
| 103 | +/// let mut seed = [0u8; 32]; |
| 104 | +/// entropy().read_exact(&mut seed)?; |
| 105 | +/// println!("seed: {seed:?}"); |
| 106 | +/// # Ok(()) |
| 107 | +/// # } |
| 108 | +/// ``` |
| 109 | +/// |
| 110 | +/// Implementing your very own `/dev/random`: |
| 111 | +/// |
| 112 | +/// ```rust, no_run |
| 113 | +/// #![feature(io_entropy)] |
| 114 | +/// |
| 115 | +/// use std::io::{copy, entropy, stdout}; |
| 116 | +/// |
| 117 | +/// fn main() { |
| 118 | +/// let _ = copy(&mut entropy(), &mut stdout()); |
| 119 | +/// } |
| 120 | +/// ``` |
| 121 | +#[inline] |
| 122 | +#[unstable(feature = "io_entropy", issue = "none")] |
| 123 | +pub fn entropy() -> Entropy { |
| 124 | + Entropy { insecure: false } |
| 125 | +} |
0 commit comments