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. 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
+
8
94
#![ no_std]
9
95
10
96
#[ cfg( not( target_env = "sgx" ) ) ]
@@ -24,12 +110,17 @@ mod utils;
24
110
mod error;
25
111
pub use error:: { Error , UNKNOWN_ERROR , UNAVAILABLE_ERROR } ;
26
112
113
+
114
+ // System-specific implementations.
115
+ //
116
+ // These should all provide getrandom_inner with the same signature as getrandom.
117
+
27
118
macro_rules! mod_use {
28
119
( $cond: meta, $module: ident) => {
29
120
#[ $cond]
30
121
mod $module;
31
122
#[ $cond]
32
- pub use $module:: getrandom ;
123
+ use $module:: getrandom_inner ;
33
124
}
34
125
}
35
126
@@ -100,3 +191,19 @@ mod_use!(
100
191
) ) ) ,
101
192
dummy
102
193
) ;
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