diff --git a/src/custom.rs b/src/custom.rs index 71a1533c0..e9344b098 100644 --- a/src/custom.rs +++ b/src/custom.rs @@ -12,11 +12,11 @@ use core::num::NonZeroU32; /// Register a function to be invoked by `getrandom` on custom targets. /// -/// This function will only be invoked on targets not supported by `getrandom`. -/// This prevents crate dependencies from either inadvertently or maliciously -/// overriding the secure RNG implementations in `getrandom`. -/// /// *This API requires the following crate features to be activated: `custom`* +/// +/// ## Writing your own custom `getrandom` implementation crate +/// +/// TODO #[macro_export] macro_rules! register_custom_getrandom { ($path:path) => { diff --git a/src/lib.rs b/src/lib.rs index 8a03009a2..7d1b5a69c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,11 +6,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Interface to the random number generator of the operating system. +//! Interface to the operating system's random number generator. //! -//! # Platform sources +//! # Supported targets //! -//! | OS | interface +//! | Target | Implemnetation //! |------------------|--------------------------------------------------------- //! | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` //! | Windows | [`RtlGenRandom`][3] @@ -27,65 +27,89 @@ //! | Haiku | `/dev/random` (identical to `/dev/urandom`) //! | SGX | [RDRAND][18] //! | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure` -//! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and asm.js][16]) -//! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and asm.js][16]) +//! | Emcripten | `/dev/random` (identical to `/dev/urandom`) //! | WASI | [`__wasi_random_get`][17] //! -//! Getrandom doesn't have a blanket implementation for all Unix-like operating -//! systems that reads from `/dev/urandom`. This ensures all supported operating -//! systems are using the recommended interface and respect maximum buffer -//! sizes. +//! This crate doesn't have a blanket implementation for all `unix` targets that +//! reads from `/dev/urandom`. This ensures all supported targets are using the +//! recommended interface and respect maximum buffer sizes. //! //! ## Unsupported targets //! -//! By default, compiling `getrandom` for an unsupported target will result in -//! a compilation error. If you want to build an application which uses `getrandom` -//! for such target, you can either: -//! - Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml` -//! to switch to a custom implementation with a support of your target. -//! -//! [replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section -//! [patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section +//! By default, `getrandom` will not compile on an unsupported target. If you +//! want to use `getrandom` on such target, you can either: +//! +//! - Enable `getrandom`'s `"cpu"` feature +//! - This makes `getrandom` fallback to using CPU-specific RNG instructions. +//! - Currently only `x86`/`x86_64` targets are suppored. On these targets, +//! [RDRAND][18] will be used to generate the random data. +//! - If `getrandom` is not a direct dependancy of your crate, you can still +//! enable this fallback by adding the following to your crate's +//! `[dependancies]` section: +//! ```toml +//! getrandom = { version = "0.2", features = ["custom"] +//! ``` +//! +//! - Use a custom `getrandom` implementation via an external crate. +//! - Some external creates define `getrandom` implementations for specific +//! unsupported targets. +//! - To use one of these crates (for example [`stdweb-getradnom`][23]): +//! - Add `stdweb-getrandom = "0.1"` to your crate's `[dependancies]` section. +//! - Use `stdweb-getrandom` in your crate. This can be done by adding +//! `use stdweb_getrandom as _;` to `src/lib.rs`. Explict usage is needed +//! to avoid linker errors. +//! - Using `getrandom` on `wasm32-unknown-unknown` will now call into the +//! implementation defined by the `stdweb-getrandom` crate. +//! - See [`register_custom_getrandom!`] for information about writing your +//! own custom `getrandom` implementation for an unsupported target. +//! - Custom implementations take precedence over the `"cpu"` feature. +//! +//! Both of these mechanisms only affect unsupported targets. Supported targets +//! will always use their standard implementations. +//! +//! Of course, Pull Requests are welcome to add new targets to `getrandom`! //! //! ## Support for WebAssembly and asm.js //! -//! Getrandom supports all of Rust's current `wasm32` targets, and it works with -//! both Node.js and web browsers. The three Emscripten targets -//! `asmjs-unknown-emscripten`, `wasm32-unknown-emscripten`, and -//! `wasm32-experimental-emscripten` use Emscripten's `/dev/random` emulation. -//! The WASI target `wasm32-wasi` uses the [`__wasi_random_get`][17] function -//! defined by the WASI standard. -//! -//! Getrandom also supports `wasm32-unknown-unknown` by directly calling -//! JavaScript methods. Rust currently has two ways to do this: [bindgen] and -//! [stdweb]. Getrandom supports using either one by enabling the -//! `wasm-bindgen` or `stdweb` crate features. Note that if both features are -//! enabled, `wasm-bindgen` will be used. If neither feature is enabled, calls -//! to `getrandom` will always fail at runtime. -//! -//! [bindgen]: https://github.com/rust-lang/rust-bindgen +//! This crate supports the following `wasm32`/`asmjs` targets: +//! - `wasm32-wasi` +//! - `asmjs-unknown-emscripten` +//! - `wasm32-unknown-emscripten` +//! +//! For `wasm32-unknown-unknown`, the story ismessy. This target can interface +//! with JavaScript via either [wasm-bindgen] or [stdweb]. For this reason, +//! **`wasm32-unknown-unknown` is an unsupported target**. +//! +//! However, as with any unsupported target, users can use custom `getrandom` +//! implementation crates. For `wasm32-unknown-unknown`, there are: +//! - [`wasm-bindgen-getrandom`][22], for use with [wasm-bindgen] +//! - [`stdweb-getradnom`][23], for use with [stdweb] +//! +//! Both of these crates work with web browsers and Node.js by directly calling +//! the appropriate JavaScript functions. Specifically, +//! - On web browsers, [`Crypto.getRandomValues`][14] is used. +//! - On Node.js [`crypto.randomBytes`][15] is used. +//! +//! [wasm-bindgen]: https://github.com/rust-lang/rust-bindgen //! [stdweb]: https://github.com/koute/stdweb //! //! ## Early boot //! -//! It is possible that early in the boot process the OS hasn't had enough time -//! yet to collect entropy to securely seed its RNG, especially on virtual -//! machines. +//! Sometimes, early in the boot process, the OS has not collected enough +//! entropy to securely seed its RNG. This is especially common on virtual +//! machines, where standard "random" events are hard to come by. //! -//! Some operating systems always block the thread until the RNG is securely +//! Some operating system interfaces always block until the RNG is securely //! seeded. This can take anywhere from a few seconds to more than a minute. -//! Others make a best effort to use a seed from before the shutdown and don't -//! document much. -//! -//! A few, Linux, NetBSD and Solaris, offer a choice between blocking and -//! getting an error; in these cases we always choose to block. +//! A few (Linux, NetBSD and Solaris) offer a choice between blocking and +//! getting an error; in these cases, we always choose to block. //! -//! On Linux (when the `getrandom` system call is not available) and on NetBSD -//! reading from `/dev/urandom` never blocks, even when the OS hasn't collected -//! enough entropy yet. To avoid returning low-entropy bytes, we first read from +//! On Linux (when the `getrandom` system call is not available), reading from +//! `/dev/urandom` never blocks, even when the OS hasn't collected enough +//! entropy yet. To avoid returning low-entropy bytes, we first poll //! `/dev/random` and only switch to `/dev/urandom` once this has succeeded. //! -//! # Error handling +//! ## Error handling //! //! We always choose failure over returning insecure "random" bytes. In general, //! on supported platforms, failure is highly unlikely, though not impossible. @@ -93,9 +117,6 @@ //! `getrandom`, hence after the first successful call one can be reasonably //! confident that no errors will occur. //! -//! On unsupported platforms, `getrandom` always fails. See the [`Error`] type -//! for more information on what data is returned on failure. -//! //! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html //! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html //! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom @@ -111,12 +132,13 @@ //! [13]: https://github.com/nuxinl/cloudabi#random_get //! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues //! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback -//! [16]: #support-for-webassembly-and-asmjs //! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get //! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide //! [19]: https://www.unix.com/man-page/mojave/2/getentropy/ //! [20]: https://www.unix.com/man-page/mojave/4/random/ //! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable +//! [22]: https://docs.rs/wasm-bindgen-getrandom/ +//! [23]: https://docs.rs/stdweb-getrandom/ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",