55// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
66// option. This file may not be copied, modified, or distributed
77// 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 reading from `/dev/random` once
16+ //! | Windows | [`RtlGenRandom`][3]
17+ //! | macOS, iOS | [`SecRandomCopyBytes`][4]
18+ //! | FreeBSD | [`kern.arandom`][5]
19+ //! | OpenBSD, Bitrig | [`getentropy`][6]
20+ //! | NetBSD | [`/dev/urandom`][7] after reading from `/dev/random` once
21+ //! | Dragonfly BSD | [`/dev/random`][8]
22+ //! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10]
23+ //! | Fuchsia OS | [`cprng_draw`][11]
24+ //! | Redox | [`rand:`][12]
25+ //! | CloudABI | [`random_get`][13]
26+ //! | Haiku | `/dev/random` (identical to `/dev/urandom`)
27+ //! | SGX | RDRAND
28+ //! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14])
29+ //! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16])
30+ //!
31+ //! Getrandom doesn't have a blanket implementation for all Unix-like operating
32+ //! systems that reads from `/dev/urandom`. This ensures all supported operating
33+ //! systems are using the recommended interface and respect maximum buffer
34+ //! sizes.
35+ //!
36+ //! ## Support for WebAssembly and ams.js
37+ //!
38+ //! The three Emscripten targets `asmjs-unknown-emscripten`,
39+ //! `wasm32-unknown-emscripten` and `wasm32-experimental-emscripten` use
40+ //! Emscripten's emulation of `/dev/random` on web browsers and Node.js.
41+ //!
42+ //! The bare WASM target `wasm32-unknown-unknown` tries to call the javascript
43+ //! methods directly, using either `stdweb` or `wasm-bindgen` depending on what
44+ //! features are activated for this crate. Note that if both features are
45+ //! enabled `wasm-bindgen` will be used. If neither feature is enabled,
46+ //! `getrandom` will always fail.
47+ //!
48+ //! ## Early boot
49+ //!
50+ //! It is possible that early in the boot process the OS hasn't had enough time
51+ //! yet to collect entropy to securely seed its RNG, especially on virtual
52+ //! machines.
53+ //!
54+ //! Some operating systems always block the thread until the RNG is securely
55+ //! seeded. This can take anywhere from a few seconds to more than a minute.
56+ //! Others make a best effort to use a seed from before the shutdown and don't
57+ //! document much.
58+ //!
59+ //! A few, Linux, NetBSD and Solaris, offer a choice between blocking and
60+ //! getting an error; in these cases we always choose to block.
61+ //!
62+ //! On Linux (when the `genrandom` system call is not available) and on NetBSD
63+ //! reading from `/dev/urandom` never blocks, even when the OS hasn't collected
64+ //! enough entropy yet. To avoid returning low-entropy bytes, we first read from
65+ //! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
66+ //!
67+ //! # Error handling
68+ //!
69+ //! We always choose failure over returning insecure "random" bytes. In general,
70+ //! on supported platforms, failure is unlikely, though not impossible. If an
71+ //! error does occur, then it is likely that it will occur on every call to
72+ //! `getrandom`, hence after the first successful call one can be reasonably
73+ //! confident that no errors will occur.
74+ //!
75+ //! On unsupported platforms, `getrandom` always fails.
76+ //!
77+ //! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
78+ //! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
79+ //! [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
80+ //! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
81+ //! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
82+ //! [6]: https://man.openbsd.org/getentropy.2
83+ //! [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current
84+ //! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4
85+ //! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
86+ //! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
87+ //! [11]: https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md
88+ //! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
89+ //! [13]: https://github.com/NuxiNL/cloudabi/blob/v0.20/cloudabi.txt#L1826
90+ //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
91+ //! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
92+ //! [16]: #support-for-webassembly-and-amsjs
93+
894#![ no_std]
995
1096#[ cfg( not( target_env = "sgx" ) ) ]
@@ -24,12 +110,17 @@ mod utils;
24110mod error;
25111pub use error:: { Error , UNKNOWN_ERROR , UNAVAILABLE_ERROR } ;
26112
113+
114+ // System-specific implementations.
115+ //
116+ // These should all provide getrandom_inner with the same signature as getrandom.
117+
27118macro_rules! mod_use {
28119 ( $cond: meta, $module: ident) => {
29120 #[ $cond]
30121 mod $module;
31122 #[ $cond]
32- pub use $module:: getrandom ;
123+ use $module:: getrandom_inner ;
33124 }
34125}
35126
@@ -100,3 +191,19 @@ mod_use!(
100191 ) ) ) ,
101192 dummy
102193) ;
194+
195+
196+ /// Fill `dest` with random bytes from the system's preferred random number
197+ /// source.
198+ ///
199+ /// This function returns an error on any failure, including partial reads. We
200+ /// make no guarantees regarding the contents of `dest` on error.
201+ ///
202+ /// Blocking is possible, at least during early boot; see module documentation.
203+ ///
204+ /// In general, `getrandom` will be fast enough for interactive usage, though
205+ /// significantly slower than a user-space CSPRNG; for the latter consider
206+ /// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
207+ pub fn getrandom ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
208+ getrandom_inner ( dest)
209+ }
0 commit comments