]> git.proxmox.com Git - rustc.git/blob - vendor/getrandom-0.1.16/src/lib.rs
Update unsuspicious file list
[rustc.git] / vendor / getrandom-0.1.16 / src / lib.rs
1 // Copyright 2019 Developers of the Rand project.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 //! Interface to the random number generator of the operating system.
10 //!
11 //! # Platform sources
12 //!
13 //! | OS | interface
14 //! |------------------|---------------------------------------------------------
15 //! | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
16 //! | Windows | [`RtlGenRandom`][3]
17 //! | macOS | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`)
18 //! | iOS | [`SecRandomCopyBytes`][4]
19 //! | FreeBSD | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5]
20 //! | OpenBSD | [`getentropy`][6]
21 //! | NetBSD | [`kern.arandom`][7]
22 //! | Dragonfly BSD | [`/dev/random`][8]
23 //! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10]
24 //! | Fuchsia OS | [`cprng_draw`][11]
25 //! | Redox | [`rand:`][12]
26 //! | CloudABI | [`cloudabi_sys_random_get`][13]
27 //! | Haiku | `/dev/random` (identical to `/dev/urandom`)
28 //! | L4RE, SGX, UEFI | [RDRAND][18]
29 //! | Hermit | [RDRAND][18] as [`sys_rand`][22] is currently broken.
30 //! | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure`
31 //! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and asm.js][16])
32 //! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and asm.js][16])
33 //! | WASI | [`__wasi_random_get`][17]
34 //!
35 //! Getrandom doesn't have a blanket implementation for all Unix-like operating
36 //! systems that reads from `/dev/urandom`. This ensures all supported operating
37 //! systems are using the recommended interface and respect maximum buffer
38 //! sizes.
39 //!
40 //! ## Unsupported targets
41 //!
42 //! By default, compiling `getrandom` for an unsupported target will result in
43 //! a compilation error. If you want to build an application which uses `getrandom`
44 //! for such target, you can either:
45 //! - Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml`
46 //! to switch to a custom implementation with a support of your target.
47 //! - Enable the `dummy` feature to have getrandom use an implementation that always
48 //! fails at run-time on unsupported targets.
49 //!
50 //! [replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section
51 //! [patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section
52 //!
53 //! ## Support for WebAssembly and asm.js
54 //!
55 //! Getrandom supports all of Rust's current `wasm32` targets, and it works with
56 //! both Node.js and web browsers. The three Emscripten targets
57 //! `asmjs-unknown-emscripten`, `wasm32-unknown-emscripten`, and
58 //! `wasm32-experimental-emscripten` use Emscripten's `/dev/random` emulation.
59 //! The WASI target `wasm32-wasi` uses the [`__wasi_random_get`][17] function
60 //! defined by the WASI standard.
61 //!
62 //! Getrandom also supports `wasm32-unknown-unknown` by directly calling
63 //! JavaScript methods. Rust currently has two ways to do this: [bindgen] and
64 //! [stdweb]. Getrandom supports using either one by enabling the
65 //! `wasm-bindgen` or `stdweb` crate features. Note that if both features are
66 //! enabled, `wasm-bindgen` will be used. If neither feature is enabled, calls
67 //! to `getrandom` will always fail at runtime.
68 //!
69 //! [bindgen]: https://github.com/rust-lang/rust-bindgen
70 //! [stdweb]: https://github.com/koute/stdweb
71 //!
72 //! ## Early boot
73 //!
74 //! It is possible that early in the boot process the OS hasn't had enough time
75 //! yet to collect entropy to securely seed its RNG, especially on virtual
76 //! machines.
77 //!
78 //! Some operating systems always block the thread until the RNG is securely
79 //! seeded. This can take anywhere from a few seconds to more than a minute.
80 //! Others make a best effort to use a seed from before the shutdown and don't
81 //! document much.
82 //!
83 //! A few, Linux, NetBSD and Solaris, offer a choice between blocking and
84 //! getting an error; in these cases we always choose to block.
85 //!
86 //! On Linux (when the `getrandom` system call is not available) and on NetBSD
87 //! reading from `/dev/urandom` never blocks, even when the OS hasn't collected
88 //! enough entropy yet. To avoid returning low-entropy bytes, we first read from
89 //! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
90 //!
91 //! # Error handling
92 //!
93 //! We always choose failure over returning insecure "random" bytes. In general,
94 //! on supported platforms, failure is highly unlikely, though not impossible.
95 //! If an error does occur, then it is likely that it will occur on every call to
96 //! `getrandom`, hence after the first successful call one can be reasonably
97 //! confident that no errors will occur.
98 //!
99 //! On unsupported platforms, `getrandom` always fails. See the [`Error`] type
100 //! for more information on what data is returned on failure.
101 //!
102 //! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
103 //! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
104 //! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom
105 //! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
106 //! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
107 //! [6]: https://man.openbsd.org/getentropy.2
108 //! [7]: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-8.0
109 //! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random&section=4
110 //! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
111 //! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
112 //! [11]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
113 //! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
114 //! [13]: https://github.com/nuxinl/cloudabi#random_get
115 //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
116 //! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
117 //! [16]: #support-for-webassembly-and-asmjs
118 //! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get
119 //! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
120 //! [19]: https://www.unix.com/man-page/mojave/2/getentropy/
121 //! [20]: https://www.unix.com/man-page/mojave/4/random/
122 //! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
123 //! [22]: https://github.com/hermitcore/libhermit-rs/blob/09c38b0371cee6f56a541400ba453e319e43db53/src/syscalls/random.rs#L21
124
125 #![doc(
126 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
127 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
128 html_root_url = "https://rust-random.github.io/rand/"
129 )]
130 #![no_std]
131 #![cfg_attr(feature = "stdweb", recursion_limit = "128")]
132 #![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
133
134 #[macro_use]
135 extern crate cfg_if;
136
137 cfg_if! {
138 if #[cfg(feature = "log")] {
139 #[allow(unused)]
140 #[macro_use]
141 extern crate log;
142 } else {
143 #[allow(unused)]
144 macro_rules! error {
145 ($($x:tt)*) => {};
146 }
147 #[allow(unused)]
148 macro_rules! warn {
149 ($($x:tt)*) => {};
150 }
151 #[allow(unused)]
152 macro_rules! info {
153 ($($x:tt)*) => {};
154 }
155 }
156 }
157
158 mod error;
159 pub use crate::error::Error;
160
161 mod util;
162
163 // For backwards compatibility, we provide the std-only trait implementations
164 // for some platforms, even if they don't enable the "std" feature.
165 #[cfg(any(
166 feature = "std",
167 all(windows, not(getrandom_uwp)),
168 target_os = "android",
169 target_os = "dragonfly",
170 target_os = "emscripten",
171 target_os = "freebsd",
172 target_os = "fuchsia",
173 target_os = "haiku",
174 target_os = "illumos",
175 target_os = "ios",
176 target_os = "linux",
177 target_os = "macos",
178 target_os = "netbsd",
179 target_os = "openbsd",
180 target_os = "redox",
181 target_os = "solaris",
182 ))]
183 mod error_impls;
184
185 // System-specific implementations.
186 //
187 // These should all provide getrandom_inner with the same signature as getrandom.
188 cfg_if! {
189 if #[cfg(target_os = "android")] {
190 mod util_libc;
191 mod use_file;
192 #[path = "linux_android.rs"] mod imp;
193 } else if #[cfg(target_os = "cloudabi")] {
194 #[path = "cloudabi.rs"] mod imp;
195 } else if #[cfg(target_os = "dragonfly")] {
196 mod util_libc;
197 #[path = "use_file.rs"] mod imp;
198 } else if #[cfg(target_os = "emscripten")] {
199 mod util_libc;
200 #[path = "use_file.rs"] mod imp;
201 } else if #[cfg(target_os = "freebsd")] {
202 mod util_libc;
203 #[path = "bsd_arandom.rs"] mod imp;
204 } else if #[cfg(target_os = "fuchsia")] {
205 #[path = "fuchsia.rs"] mod imp;
206 } else if #[cfg(target_os = "haiku")] {
207 mod util_libc;
208 #[path = "use_file.rs"] mod imp;
209 } else if #[cfg(target_os = "illumos")] {
210 mod util_libc;
211 mod use_file;
212 #[path = "solaris_illumos.rs"] mod imp;
213 } else if #[cfg(target_os = "ios")] {
214 #[path = "ios.rs"] mod imp;
215 } else if #[cfg(target_os = "linux")] {
216 mod util_libc;
217 mod use_file;
218 #[path = "linux_android.rs"] mod imp;
219 } else if #[cfg(target_os = "macos")] {
220 mod util_libc;
221 mod use_file;
222 #[path = "macos.rs"] mod imp;
223 } else if #[cfg(target_os = "netbsd")] {
224 mod util_libc;
225 #[path = "bsd_arandom.rs"] mod imp;
226 } else if #[cfg(target_os = "openbsd")] {
227 mod util_libc;
228 #[path = "openbsd.rs"] mod imp;
229 } else if #[cfg(target_os = "redox")] {
230 mod util_libc;
231 #[path = "use_file.rs"] mod imp;
232 } else if #[cfg(target_os = "solaris")] {
233 mod util_libc;
234 mod use_file;
235 #[path = "solaris_illumos.rs"] mod imp;
236 } else if #[cfg(target_os = "wasi")] {
237 #[path = "wasi.rs"] mod imp;
238 } else if #[cfg(target_os = "vxworks")] {
239 mod util_libc;
240 #[path = "vxworks.rs"] mod imp;
241 } else if #[cfg(all(windows, getrandom_uwp))] {
242 #[path = "windows_uwp.rs"] mod imp;
243 } else if #[cfg(windows)] {
244 #[path = "windows.rs"] mod imp;
245 } else if #[cfg(all(target_arch = "x86_64", any(
246 target_os = "hermit",
247 target_os = "l4re",
248 target_os = "uefi",
249 target_env = "sgx",
250 )))] {
251 #[path = "rdrand.rs"] mod imp;
252 } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
253 cfg_if! {
254 if #[cfg(feature = "wasm-bindgen")] {
255 #[path = "wasm32_bindgen.rs"] mod imp;
256 } else if #[cfg(feature = "stdweb")] {
257 #[path = "wasm32_stdweb.rs"] mod imp;
258 } else {
259 // Always have an implementation for wasm32-unknown-unknown.
260 // See https://github.com/rust-random/getrandom/issues/87
261 #[path = "dummy.rs"] mod imp;
262 }
263 }
264 } else if #[cfg(feature = "dummy")] {
265 #[path = "dummy.rs"] mod imp;
266 } else {
267 compile_error!("\
268 target is not supported, for more information see: \
269 https://docs.rs/getrandom/#unsupported-targets\
270 ");
271 }
272 }
273
274 /// Fill `dest` with random bytes from the system's preferred random number
275 /// source.
276 ///
277 /// This function returns an error on any failure, including partial reads. We
278 /// make no guarantees regarding the contents of `dest` on error. If `dest` is
279 /// empty, `getrandom` immediately returns success, making no calls to the
280 /// underlying operating system.
281 ///
282 /// Blocking is possible, at least during early boot; see module documentation.
283 ///
284 /// In general, `getrandom` will be fast enough for interactive usage, though
285 /// significantly slower than a user-space CSPRNG; for the latter consider
286 /// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
287 pub fn getrandom(dest: &mut [u8]) -> Result<(), error::Error> {
288 if dest.is_empty() {
289 return Ok(());
290 }
291 imp::getrandom_inner(dest)
292 }