Skip to content

Commit 0389d46

Browse files
committed
Update docs for 0.2
The main things here are clarifying how fallback functionatliy works. Signed-off-by: Joe Richey <[email protected]>
1 parent c36dc82 commit 0389d46

File tree

5 files changed

+117
-77
lines changed

5 files changed

+117
-77
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@ wasm-bindgen = { version = "0.2.62", default-features = false, optional = true }
3535
wasm-bindgen-test = "0.3.12"
3636

3737
[features]
38+
# Implement std-only traits for getrandom::Error
3839
std = []
39-
# Feature to enable fallback RDRAND-based implementation
40+
# Feature to enable fallback RDRAND-based implementation on x86/x86_64
4041
rdrand = []
4142
# Feature to enable JavaScript bindings on wasm32-unknown-unknown
4243
js = ["stdweb", "wasm-bindgen"]
4344
# Feature to enable custom RNG implementations
4445
custom = []
4546
# Unstable feature to support being a libstd dependency
4647
rustc-dep-of-std = ["compiler_builtins", "core"]
47-
48-
# Test/wasm-bindgen only feature to run tests in a browser
48+
# Unstable/test-only feature to run wasm-bindgen tests in a browser
4949
test-in-browser = []
5050

5151
[package.metadata.docs.rs]

README.md

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,10 @@ fn get_random_buf() -> Result<[u8; 32], getrandom::Error> {
3737
}
3838
```
3939

40-
## Features
41-
42-
This library is `no_std` for every supported target. However, getting randomness
43-
usually requires calling some external system API. This means most platforms
44-
will require linking against system libraries (i.e. `libc` for Unix,
45-
`Advapi32.dll` for Windows, Security framework on iOS, etc...).
46-
47-
For the `wasm32-unknown-unknown` target, one of the following features should be
48-
enabled:
49-
50-
- [`wasm-bindgen`](https://crates.io/crates/wasm_bindgen)
51-
- [`stdweb`](https://crates.io/crates/stdweb)
52-
53-
By default, compiling `getrandom` for an unsupported target will result in
54-
a compilation error. If you want to build an application which uses `getrandom`
55-
for such target, you can either:
56-
- Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml`
57-
to switch to a custom implementation with a support of your target.
58-
59-
[replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section
60-
[patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section
40+
For more information about supported targets, entropy sources, `no_std` targets,
41+
crate features, WASM support and Custom RNGs see the
42+
[`getrandom` documentation](https://docs.rs/getrandom/latest) and
43+
[`getrandom::Error` documentation](https://docs.rs/getrandom/latest/getrandom/struct.Error.html).
6144

6245
## Minimum Supported Rust Version
6346

src/custom.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,43 @@
1010
use crate::Error;
1111
use core::num::NonZeroU32;
1212

13-
/// Register a function to be invoked by `getrandom` on custom targets.
13+
/// Register a function to be invoked by `getrandom` on unsupported targets.
1414
///
15-
/// This function will only be invoked on targets not supported by `getrandom`.
16-
/// This prevents crate dependencies from either inadvertently or maliciously
17-
/// overriding the secure RNG implementations in `getrandom`.
15+
/// *This API requires the following Cargo features to be activated: `"custom"`*
1816
///
19-
/// *This API requires the following crate features to be activated: `custom`*
17+
/// ## Writing your own custom `getrandom` implementation
18+
///
19+
/// Users can define custom implementations either in their root crate or in a
20+
/// target specific helper-crate. We will use the helper-crate approach in this
21+
/// example, defining `dummy-getrandom`, an implementation that always fails.
22+
///
23+
/// First, in `dummy-getrandom/Cargo.toml` we depend on `getrandom`:
24+
/// ```toml
25+
/// [dependencies]
26+
/// getrandom = { version = "0.2", features = ["custom"] }
27+
/// ```
28+
///
29+
/// Next, in `dummy-getrandom/src/lib.rs`, we define our custom implementation and register it:
30+
/// ```rust
31+
/// use core::num::NonZeroU32;
32+
/// use getrandom::{Error, register_custom_getrandom};
33+
///
34+
/// const MY_CUSTOM_ERROR_CODE: u32 = Error::CUSTOM_START + 42;
35+
/// fn always_fail(buf: &mut [u8]) -> Result<(), Error> {
36+
/// let code = NonZeroU32::new(MY_CUSTOM_ERROR_CODE).unwrap();
37+
/// Err(Error::from(code))
38+
/// }
39+
///
40+
/// register_custom_getrandom!(always_fail);
41+
/// ```
42+
/// the registered function must have the same type signature as
43+
/// [`getrandom::getrandom`](crate::getrandom).
44+
///
45+
/// Now any user of `getrandom` (direct or indirect) on this target will use the
46+
/// above custom implementation. Note that if you are using a helper-crate, some
47+
/// crate in the build needs to depend on `dummy-getrandom` via a
48+
/// `use dummy_getrandom;` statement. Failure to do this will result
49+
/// in linker errors.
2050
#[macro_export]
2151
macro_rules! register_custom_getrandom {
2252
($path:path) => {

src/error.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@
77
// except according to those terms.
88
use core::{fmt, num::NonZeroU32};
99

10-
/// A small and `no_std` compatible error type.
10+
/// A small and `no_std` compatible error type
1111
///
1212
/// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and
1313
/// if so, which error code the OS gave the application. If such an error is
1414
/// encountered, please consult with your system documentation.
1515
///
1616
/// Internally this type is a NonZeroU32, with certain values reserved for
1717
/// certain purposes, see [`Error::INTERNAL_START`] and [`Error::CUSTOM_START`].
18+
///
19+
/// *If this crate's `"std"` Cargo feature is enabled*, then:
20+
/// - [`getrandom::Error`][Error] implements
21+
/// [`std::error::Error`](https://doc.rust-lang.org/std/error/trait.Error.html)
22+
/// - [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) implements
23+
/// [`From<getrandom::Error>`](https://doc.rust-lang.org/std/convert/trait.From.html).
1824
#[derive(Copy, Clone, Eq, PartialEq)]
1925
pub struct Error(NonZeroU32);
2026

src/lib.rs

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
//! Interface to the random number generator of the operating system.
9+
//! Interface to the operating system's random number generator.
1010
//!
11-
//! # Platform sources
11+
//! # Supported targets
1212
//!
13-
//! | OS | interface
13+
//! | Target | Implementation
1414
//! |------------------|---------------------------------------------------------
1515
//! | Linux, Android | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
1616
//! | Windows | [`RtlGenRandom`][3]
17+
//! | [Windows UWP][22]| [`BCryptGenRandom`][23]
1718
//! | macOS | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`)
1819
//! | iOS | [`SecRandomCopyBytes`][4]
1920
//! | FreeBSD | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5]
@@ -27,75 +28,93 @@
2728
//! | Haiku | `/dev/random` (identical to `/dev/urandom`)
2829
//! | SGX | [RDRAND][18]
2930
//! | VxWorks | `randABytes` after checking entropy pool initialization with `randSecure`
30-
//! | Web browsers | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and asm.js][16])
31-
//! | Node.js | [`crypto.randomBytes`][15] (see [Support for WebAssembly and asm.js][16])
31+
//! | Emscripten | `/dev/random` (identical to `/dev/urandom`)
3232
//! | WASI | [`__wasi_random_get`][17]
33+
//! | Web Browser | [`Crypto.getRandomValues()`][14], see [support for WebAssembly][16]
34+
//! | Node.js | [`crypto.randomBytes`][15], see [support for WebAssembly][16]
3335
//!
34-
//! Getrandom doesn't have a blanket implementation for all Unix-like operating
35-
//! systems that reads from `/dev/urandom`. This ensures all supported operating
36-
//! systems are using the recommended interface and respect maximum buffer
37-
//! sizes.
36+
//! There is no blanket implementation on `unix` targets that reads from
37+
//! `/dev/urandom`. This ensures all supported targets are using the recommended
38+
//! interface and respect maximum buffer sizes.
39+
//!
40+
//! Pull Requests that add support for new targets to `getrandom` are always welcome.
3841
//!
3942
//! ## Unsupported targets
4043
//!
41-
//! By default, compiling `getrandom` for an unsupported target will result in
42-
//! a compilation error. If you want to build an application which uses `getrandom`
43-
//! for such target, you can either:
44-
//! - Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml`
45-
//! to switch to a custom implementation with a support of your target.
44+
//! By default, `getrandom` will not compile on unsupported targets, but certain
45+
//! features allow a user to select a "fallback" implementation if no supported
46+
//! implementation exists.
47+
//!
48+
//! All of the below mechanisms only affect unsupported
49+
//! targets. Supported targets will _always_ use their supported implementations.
50+
//! This prevents a crate from overriding a secure source of randomness
51+
//! (either accidentally or intentionally).
52+
//!
53+
//! ### RDRAND on x86
4654
//!
47-
//! [replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section
48-
//! [patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section
55+
//! *If the `"rdrand"` Cargo feature is enabled*, `getrandom` will fallback to using
56+
//! the [`RDRAND`][18] instruction to get randomness on `no_std` `x86`/`x86_64`
57+
//! targets. This feature has no effect on other CPU architectures.
4958
//!
50-
//! ## Support for WebAssembly and asm.js
59+
//! ### Support for WebAssembly
5160
//!
52-
//! Getrandom supports all of Rust's current `wasm32` targets, and it works with
53-
//! both Node.js and web browsers. The three Emscripten targets
54-
//! `asmjs-unknown-emscripten`, `wasm32-unknown-emscripten`, and
55-
//! `wasm32-experimental-emscripten` use Emscripten's `/dev/random` emulation.
56-
//! The WASI target `wasm32-wasi` uses the [`__wasi_random_get`][17] function
57-
//! defined by the WASI standard.
61+
//! This crate fully supports the `wasm32-wasi` and `wasm32-unknown-emscripten`
62+
//! targets. However, the `wasm32-unknown-unknown` target is not supported since,
63+
//! from the target name alone, we cannot deduce which JavaScript interface is
64+
//! in use (or if JavaScript is available at all).
5865
//!
59-
//! Getrandom also supports `wasm32-unknown-unknown` by directly calling
60-
//! JavaScript methods. Rust currently has two ways to do this: [bindgen] and
61-
//! [stdweb]. Getrandom supports using either one by enabling the
62-
//! `wasm-bindgen` or `stdweb` crate features. Note that if both features are
63-
//! enabled, `wasm-bindgen` will be used. If neither feature is enabled, calls
64-
//! to `getrandom` will always fail at runtime.
66+
//! Instead, *if the `"js"` Cargo feature is enabled*, this crate will assume
67+
//! that you are building for an environment containing JavaScript, and will
68+
//! call the appropriate methods. Both Browser and Node.js environments are
69+
//! supported (see above), and both [wasm-bindgen] and [stdweb] toolchains are
70+
//! supported.
6571
//!
66-
//! [bindgen]: https://github.com/rust-lang/rust-bindgen
72+
//! [wasm-bindgen]: https://github.com/rust-lang/rust-bindgen
6773
//! [stdweb]: https://github.com/koute/stdweb
6874
//!
75+
//! ### Use a custom implementation
76+
//!
77+
//! Some external crates define `getrandom` implementations for specific
78+
//! unsupported targets. If you depend on one of these external crates and you
79+
//! are building for an unsupported target, `getrandom` will use this external
80+
//! implementation instead of failing to compile.
81+
//!
82+
//! See [`register_custom_getrandom!`] for information about writing your own
83+
//! custom `getrandom` implementation for an unsupported target.
84+
//!
85+
//! ### Indirect Dependencies
86+
//!
87+
//! If `getrandom` is not a direct dependency of your crate, you can still
88+
//! enable any of above fallback behaviors by simply enabling the relevant
89+
//! feature in your root crate's `[dependencies]` section:
90+
//! ```toml
91+
//! getrandom = { version = "0.2", features = ["rdrand"] }
92+
//! ```
93+
//!
6994
//! ## Early boot
7095
//!
71-
//! It is possible that early in the boot process the OS hasn't had enough time
72-
//! yet to collect entropy to securely seed its RNG, especially on virtual
73-
//! machines.
96+
//! Sometimes, early in the boot process, the OS has not collected enough
97+
//! entropy to securely seed its RNG. This is especially common on virtual
98+
//! machines, where standard "random" events are hard to come by.
7499
//!
75-
//! Some operating systems always block the thread until the RNG is securely
100+
//! Some operating system interfaces always block until the RNG is securely
76101
//! seeded. This can take anywhere from a few seconds to more than a minute.
77-
//! Others make a best effort to use a seed from before the shutdown and don't
78-
//! document much.
102+
//! A few (Linux, NetBSD and Solaris) offer a choice between blocking and
103+
//! getting an error; in these cases, we always choose to block.
79104
//!
80-
//! A few, Linux, NetBSD and Solaris, offer a choice between blocking and
81-
//! getting an error; in these cases we always choose to block.
82-
//!
83-
//! On Linux (when the `getrandom` system call is not available) and on NetBSD
84-
//! reading from `/dev/urandom` never blocks, even when the OS hasn't collected
85-
//! enough entropy yet. To avoid returning low-entropy bytes, we first read from
105+
//! On Linux (when the `getrandom` system call is not available), reading from
106+
//! `/dev/urandom` never blocks, even when the OS hasn't collected enough
107+
//! entropy yet. To avoid returning low-entropy bytes, we first poll
86108
//! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
87109
//!
88-
//! # Error handling
110+
//! ## Error handling
89111
//!
90112
//! We always choose failure over returning insecure "random" bytes. In general,
91113
//! on supported platforms, failure is highly unlikely, though not impossible.
92114
//! If an error does occur, then it is likely that it will occur on every call to
93115
//! `getrandom`, hence after the first successful call one can be reasonably
94116
//! confident that no errors will occur.
95117
//!
96-
//! On unsupported platforms, `getrandom` always fails. See the [`Error`] type
97-
//! for more information on what data is returned on failure.
98-
//!
99118
//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
100119
//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
101120
//! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom
@@ -111,12 +130,14 @@
111130
//! [13]: https://github.com/nuxinl/cloudabi#random_get
112131
//! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
113132
//! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
114-
//! [16]: #support-for-webassembly-and-asmjs
133+
//! [16]: #support-for-webassembly
115134
//! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get
116135
//! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
117136
//! [19]: https://www.unix.com/man-page/mojave/2/getentropy/
118137
//! [20]: https://www.unix.com/man-page/mojave/4/random/
119138
//! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
139+
//! [22]: https://docs.microsoft.com/en-us/windows/uwp/
140+
//! [23]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
120141
121142
#![doc(
122143
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",

0 commit comments

Comments
 (0)