5
5
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6
6
// option. This file may not be copied, modified, or distributed
7
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 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.
46
+ //!
47
+ //! ## Early boot
48
+ //!
49
+ //! It is possible that early in the boot process the OS hasn't had enough time
50
+ //! yet to collect entropy to securely seed its RNG, especially on virtual
51
+ //! machines.
52
+ //!
53
+ //! Some operating systems always block the thread until the RNG is securely
54
+ //! seeded. This can take anywhere from a few seconds to more than a minute.
55
+ //! Others make a best effort to use a seed from before the shutdown and don't
56
+ //! document much.
57
+ //!
58
+ //! A few, Linux, NetBSD and Solaris, offer a choice between blocking and
59
+ //! getting an error; in these cases we always choose to block.
60
+ //!
61
+ //! On Linux (when the `genrandom` system call is not available) and on NetBSD
62
+ //! reading from `/dev/urandom` never blocks, even when the OS hasn't collected
63
+ //! enough entropy yet. To avoid returning low-entropy bytes, we first read from
64
+ //! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
65
+ //!
66
+ //! # Error handling
67
+ //!
68
+ //! We always choose failure over returning insecure "random" bytes. In general,
69
+ //! on supported platforms, failure is unlikely, though not impossible. If an
70
+ //! error does occur, then it is likely that it will occur on every call to
71
+ //! `getrandom`, hence after the first successful call one can be reasonably
72
+ //! confident that no errors will occur.
73
+ //!
74
+ //! On unsupported platforms, `getrandom` always fails.
75
+ //!
76
+ //! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
77
+ //! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
78
+ //! [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
79
+ //! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
80
+ //! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
81
+ //! [6]: https://man.openbsd.org/getentropy.2
82
+ //! [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current
83
+ //! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4
84
+ //! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
85
+ //! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
86
+ //! [11]: https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md
87
+ //! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
88
+ //! [13]: https://github.com/NuxiNL/cloudabi/blob/v0.20/cloudabi.txt#L1826
89
+ //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
90
+ //! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
91
+ //! [16]: #support-for-webassembly-and-amsjs
92
+
8
93
#![ no_std]
9
94
10
95
#[ cfg( not( target_env = "sgx" ) ) ]
@@ -24,12 +109,17 @@ mod utils;
24
109
mod error;
25
110
pub use error:: { Error , UNKNOWN_ERROR , UNAVAILABLE_ERROR } ;
26
111
112
+
113
+ // System-specific implementations.
114
+ //
115
+ // These should all provide getrandom_os with the same signature as getrandom.
116
+
27
117
macro_rules! mod_use {
28
118
( $cond: meta, $module: ident) => {
29
119
#[ $cond]
30
120
mod $module;
31
121
#[ $cond]
32
- pub use $module:: getrandom ;
122
+ use $module:: getrandom_os ;
33
123
}
34
124
}
35
125
@@ -100,3 +190,19 @@ mod_use!(
100
190
) ) ) ,
101
191
dummy
102
192
) ;
193
+
194
+
195
+ /// Fill `dest` with random bytes from the system's preferred random number
196
+ /// source.
197
+ ///
198
+ /// This function returns an error on any failure, including partial reads. We
199
+ /// make no guarantees regarding the contents of `dest` on error.
200
+ ///
201
+ /// Blocking is possible, at least during early boot; see module documentation.
202
+ ///
203
+ /// In general, `getrandom` will be fast enough for interactive usage, though
204
+ /// significantly slower than a user-space CSPRNG; for the latter consider
205
+ /// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
206
+ pub fn getrandom ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
207
+ getrandom_os ( dest)
208
+ }
0 commit comments