Skip to content

Commit 5c7a197

Browse files
authored
Unify crate docs and README (#533)
1 parent 350df46 commit 5c7a197

File tree

2 files changed

+290
-292
lines changed

2 files changed

+290
-292
lines changed

README.md

Lines changed: 285 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
1-
# getrandom
1+
# getrandom: (operating) system's random number generator
22

33
[![Build Status]][GitHub Actions] [![Crate]][crates.io] [![Documentation]][docs.rs] [![Dependency Status]][deps.rs] [![Downloads]][crates.io] [![License]][LICENSE-MIT]
44

5-
[GitHub Actions]: https://github.com/rust-random/getrandom/actions?query=workflow:Tests+branch:master
6-
[Build Status]: https://github.com/rust-random/getrandom/actions/workflows/tests.yml/badge.svg?branch=master
7-
[crates.io]: https://crates.io/crates/getrandom
8-
[Crate]: https://img.shields.io/crates/v/getrandom
9-
[docs.rs]: https://docs.rs/getrandom
10-
[Documentation]: https://docs.rs/getrandom/badge.svg
11-
[deps.rs]: https://deps.rs/repo/github/rust-random/getrandom
12-
[Dependency Status]: https://deps.rs/repo/github/rust-random/getrandom/status.svg
13-
[Downloads]: https://img.shields.io/crates/d/getrandom
14-
[LICENSE-MIT]: https://raw.githubusercontent.com/rust-random/getrandom/master/LICENSE-MIT
15-
[License]: https://img.shields.io/crates/l/getrandom
16-
5+
`getrandom` is a Rust library for retrieving random data from (operating) system sources.
176

18-
A Rust library for retrieving random data from (operating) system sources. It is
19-
assumed that the system always provides high-quality cryptographically secure random
7+
It is assumed that the system always provides high-quality cryptographically secure random
208
data, ideally backed by hardware entropy sources. This crate derives its name
219
from Linux's `getrandom` function, but is cross-platform, roughly supporting
2210
the same set of platforms as Rust's `std` lib.
@@ -35,7 +23,7 @@ Add this to your `Cargo.toml`:
3523
getrandom = "0.2"
3624
```
3725

38-
Then invoke the `getrandom` function:
26+
Then invoke the `fill` function:
3927

4028
```rust
4129
fn get_random_buf() -> Result<[u8; 32], getrandom::Error> {
@@ -45,22 +33,231 @@ fn get_random_buf() -> Result<[u8; 32], getrandom::Error> {
4533
}
4634
```
4735

48-
For more information about supported targets, entropy sources, `no_std` targets,
49-
crate features, WASM support and Custom RNGs see the
50-
[`getrandom` documentation](https://docs.rs/getrandom/latest) and
51-
[`getrandom::Error` documentation](https://docs.rs/getrandom/latest/getrandom/struct.Error.html).
36+
## Supported targets
5237

53-
## Minimum Supported Rust Version
38+
| Target | Target Triple | Implementation
39+
| ------------------ | ------------------ | --------------
40+
| Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
41+
| Windows 10+ | `*‑windows‑*` | [`ProcessPrng`]
42+
| Windows 7, 8 | `*-win7‑windows‑*` | [`RtlGenRandom`]
43+
| macOS | `*‑apple‑darwin` | [`getentropy`][3]
44+
| iOS, tvOS, watchOS | `*‑apple‑{ios,tvos,watchos}` | [`CCRandomGenerateBytes`]
45+
| FreeBSD | `*‑freebsd` | [`getrandom`][5]
46+
| OpenBSD | `*‑openbsd` | [`getentropy`][7]
47+
| NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8]
48+
| Dragonfly BSD | `*‑dragonfly` | [`getrandom`][9]
49+
| Solaris | `*‑solaris` | [`getrandom`][11] with `GRND_RANDOM`
50+
| illumos | `*‑illumos` | [`getrandom`][12]
51+
| Fuchsia OS | `*‑fuchsia` | [`cprng_draw`]
52+
| Redox | `*‑redox` | `/dev/urandom`
53+
| Haiku | `*‑haiku` | `/dev/urandom` (identical to `/dev/random`)
54+
| Hermit | `*-hermit` | [`sys_read_entropy`]
55+
| Hurd | `*-hurd-*` | [`getrandom`][17]
56+
| SGX | `x86_64‑*‑sgx` | [`RDRAND`]
57+
| VxWorks | `*‑wrs‑vxworks‑*` | `randABytes` after checking entropy pool initialization with `randSecure`
58+
| Emscripten | `*‑emscripten` | [`getentropy`][13]
59+
| WASI 0.1 | `wasm32‑wasip1` | [`random_get`]
60+
| WASI 0.2 | `wasm32‑wasip2` | [`get-random-u64`]
61+
| SOLID | `*-kmc-solid_*` | `SOLID_RNG_SampleRandomBytes`
62+
| Nintendo 3DS | `*-nintendo-3ds` | [`getrandom`][18]
63+
| PS Vita | `*-vita-*` | [`getentropy`][13]
64+
| QNX Neutrino | `*‑nto-qnx*` | [`/dev/urandom`][14] (identical to `/dev/random`)
65+
| AIX | `*-ibm-aix` | [`/dev/urandom`][15]
5466

55-
This crate requires Rust 1.60.0 or later.
67+
Pull Requests that add support for new targets to `getrandom` are always welcome.
68+
69+
### Opt-in backends
70+
71+
`getrandom` also provides optional backends which can be enabled using `getrandom_backend`
72+
configuration flag:
73+
74+
| Backend name | Target | Target Triple | Implementation
75+
| ----------------- | -------------------- | -------------------- | --------------
76+
| `linux_getrandom` | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call (without `/dev/urandom` fallback). Bumps minimum supported Linux kernel version to 3.17 and Android API level to 23 (Marshmallow).
77+
| `linux_rustix` | Linux, Android | `*‑linux‑*` | Same as `linux_getrandom`, but uses [`rustix`] instead of `libc`.
78+
| `rdrand` | x86, x86-64 | `x86_64-*`, `i686-*` | [`RDRAND`] instruction
79+
| `rndr` | AArch64 | `aarch64-*` | [`RNDR`] register
80+
| `esp_idf` | ESP-IDF | `*‑espidf` | [`esp_fill_random`]. WARNING: can return low quality entropy without proper hardware configuration!
81+
| `wasm_js` | Web Browser, Node.js | `wasm*‑*‑unknown` | [`Crypto.getRandomValues`] if available, then [`crypto.randomFillSync`] if on Node.js (see [WebAssembly support])
82+
| `custom` | All targets | `*` | User-provided custom implementation (see [custom backend])
83+
84+
The configuration flag can be enabled either by specifying the `rustflags` field in
85+
[`.cargo/config.toml`] (note that it can be done on a per-target basis), or by using
86+
`RUSTFLAGS` environment variable:
87+
88+
```sh
89+
RUSTFLAGS='--cfg getrandom_backend="linux_getrandom"' cargo build
90+
```
91+
92+
Enabling an opt-in backend will replace backend used by default. Doing it for a wrong target
93+
(e.g. using `linux_getrandom` while compiling for a Windows target) will result
94+
in a compilation error. Be extremely carefull while using opt-in backends, since incorrect
95+
configuration may result in vulnerable or in always panicking applications.
96+
97+
Note that using an opt-in backend in a library (e.g. for tests or benchmarks)
98+
WILL NOT have any effect on its downstream users.
99+
100+
[`.cargo/config.toml`]: https://doc.rust-lang.org/cargo/reference/config.html
101+
102+
### WebAssembly support
103+
104+
This crate fully supports the [WASI] and [Emscripten] targets. However,
105+
the `wasm32-unknown-unknown` target (i.e. the target used by `wasm-pack`)
106+
is not automatically supported since, from the target name alone, we cannot deduce
107+
which JavaScript interface should be used (or if JavaScript is available at all).
108+
109+
Instead, *if the `wasm_js` backend is enabled*, this crate will assume
110+
that you are building for an environment containing JavaScript, and will
111+
call the appropriate methods. Both web browser (main window and Web Workers)
112+
and Node.js environments are supported, invoking the methods
113+
[described above](#opt-in-backends) using the [`wasm-bindgen`] toolchain.
114+
115+
To enable the `wasm_js` backend, you can add the following lines to your
116+
project's `.cargo/config.toml` file:
117+
```toml
118+
[target.wasm32-unknown-unknown]
119+
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']
120+
```
121+
122+
#### Node.js ES module support
123+
124+
Node.js supports both [CommonJS modules] and [ES modules]. Due to
125+
limitations in wasm-bindgen's [`module`] support, we cannot directly
126+
support ES Modules running on Node.js. However, on Node v15 and later, the
127+
module author can add a simple shim to support the Web Cryptography API:
128+
```js
129+
import { webcrypto } from 'node:crypto'
130+
globalThis.crypto = webcrypto
131+
```
132+
This crate will then use the provided `webcrypto` implementation.
133+
134+
### Custom backend
135+
136+
If this crate does not support your target out of box or you have to use
137+
a non-default entropy source, then you can provide a custom implementation.
138+
You need to enable the custom backend as described in the [configuration flags]
139+
section. Next, you need to define an `extern` function with the following
140+
signature:
141+
142+
```rust
143+
use getrandom::Error;
144+
145+
#[no_mangle]
146+
unsafe extern "Rust" fn __getrandom_v03_custom(
147+
dest: *mut u8,
148+
len: usize,
149+
) -> Result<(), Error> {
150+
todo!()
151+
}
152+
```
153+
154+
This function ideally should be defined in the root crate of your project,
155+
e.g. in your `main.rs`. This function MUST be defined only once for your
156+
project, i.e. upstream library crates SHOULD NOT define it outside of
157+
tests and benchmarks. Improper configuration of this backend may result
158+
in linking errors.
159+
160+
The function accepts pointer to buffer which should be filled with random
161+
data and length in bytes. Note that the buffer MAY be uninitialized.
162+
On success the function should return 0 and fully fill the input buffer,
163+
every other return result will be interpreted as an error code.
164+
165+
If you are confident that `getrandom` is not used in your project, but
166+
it gets pulled nevertheless by one of your dependencies, then you can
167+
use the following custom backend which always returns "unsupported" error:
168+
```rust
169+
use getrandom::Error;
170+
171+
#[no_mangle]
172+
unsafe extern "Rust" fn __getrandom_v03_custom(
173+
dest: *mut u8,
174+
len: usize,
175+
) -> Result<(), Error> {
176+
Err(Error::UNSUPPORTED)
177+
}
178+
```
179+
180+
### Platform Support
181+
This crate generally supports the same operating system and platform versions
182+
that the Rust standard library does. Additional targets may be supported using
183+
pluggable custom implementations.
184+
185+
This means that as Rust drops support for old versions of operating systems
186+
(such as old Linux kernel versions, Android API levels, etc) in stable releases,
187+
`getrandom` may create new patch releases (`0.N.x`) that remove support for
188+
outdated platform versions.
189+
190+
### `/dev/urandom` fallback on Linux and Android
191+
192+
On Linux targets the fallback is present only if either `target_env` is `musl`,
193+
or `target_arch` is one of the following: `aarch64`, `arm`, `powerpc`, `powerpc64`,
194+
`s390x`, `x86`, `x86_64`. Other supported targets [require][platform-support]
195+
kernel versions which support `getrandom` system call, so fallback is not needed.
196+
197+
On Android targets the fallback is present only for the following `target_arch`es:
198+
`aarch64`, `arm`, `x86`, `x86_64`. Other `target_arch`es (e.g. RISC-V) require
199+
sufficiently high API levels.
200+
201+
The fallback can be disabled by enabling the `linux_getrandom` opt-in backend.
202+
Note that doing so will bump minimum supported Linux kernel version to 3.17 and
203+
Android API level to 23 (Marshmallow).
204+
205+
### Early boot
56206

57-
## Platform Support
207+
Sometimes, early in the boot process, the OS has not collected enough
208+
entropy to securely seed its RNG. This is especially common on virtual
209+
machines, where standard "random" events are hard to come by.
58210

59-
This crate generally supports the same operating system and platform versions that the Rust standard library does.
60-
Additional targets may be supported using pluggable custom implementations.
211+
Some operating system interfaces always block until the RNG is securely
212+
seeded. This can take anywhere from a few seconds to more than a minute.
213+
A few (Linux, NetBSD and Solaris) offer a choice between blocking and
214+
getting an error; in these cases, we always choose to block.
61215

62-
This means that as Rust drops support for old versions of operating systems (such as old Linux kernel versions, Android API levels, etc)
63-
in stable releases, `getrandom` may create new patch releases (`0.N.x`) that remove support for outdated platform versions.
216+
On Linux (when the `getrandom` system call is not available), reading from
217+
`/dev/urandom` never blocks, even when the OS hasn't collected enough
218+
entropy yet. To avoid returning low-entropy bytes, we first poll
219+
`/dev/random` and only switch to `/dev/urandom` once this has succeeded.
220+
221+
On OpenBSD, this kind of entropy accounting isn't available, and on
222+
NetBSD, blocking on it is discouraged. On these platforms, nonblocking
223+
interfaces are used, even when reliable entropy may not be available.
224+
On the platforms where it is used, the reliability of entropy accounting
225+
itself isn't free from controversy. This library provides randomness
226+
sourced according to the platform's best practices, but each platform has
227+
its own limits on the grade of randomness it can promise in environments
228+
with few sources of entropy.
229+
230+
## Error handling
231+
232+
We always choose failure over returning known insecure "random" bytes. In
233+
general, on supported platforms, failure is highly unlikely, though not
234+
impossible. If an error does occur, then it is likely that it will occur
235+
on every call to `getrandom`, hence after the first successful call one
236+
can be reasonably confident that no errors will occur.
237+
238+
## Panic handling
239+
240+
We strive to eliminate all potential panics from our implementation.
241+
In other words, when compiled with enabled optimizations, generated
242+
binary code for `getrandom` functions should not contain any panic
243+
branches. Even if platform misbiheaves and returns an unexpected
244+
result, our code should correctly handle it and return an error like
245+
[`Error::UNEXPECTED`].
246+
247+
## Sanitizer support
248+
249+
If your code uses [`fill_uninit`] and you use memory sanitizer
250+
(i.e. `-Zsanitizer=memory`), then you need to pass `getrandom_sanitize`
251+
configuration flag for `fill_uninit` to unpoison destination buffer.
252+
253+
For example, it can be done like this (requires Nightly compiler):
254+
```sh
255+
RUSTFLAGS="-Zsanitizer=memory --cfg getrandom_sanitize" cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu
256+
```
257+
258+
## Minimum Supported Rust Version
259+
260+
This crate requires Rust 1.60.0 or later.
64261

65262
## License
66263

@@ -77,5 +274,66 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
77274
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
78275
dual licensed as above, without any additional terms or conditions.
79276

277+
[//]: # (badges)
278+
279+
[GitHub Actions]: https://github.com/rust-random/getrandom/actions?query=workflow:Tests+branch:master
280+
[Build Status]: https://github.com/rust-random/getrandom/actions/workflows/tests.yml/badge.svg?branch=master
281+
[crates.io]: https://crates.io/crates/getrandom
282+
[Crate]: https://img.shields.io/crates/v/getrandom
283+
[docs.rs]: https://docs.rs/getrandom
284+
[Documentation]: https://docs.rs/getrandom/badge.svg
285+
[deps.rs]: https://deps.rs/repo/github/rust-random/getrandom
286+
[Dependency Status]: https://deps.rs/repo/github/rust-random/getrandom/status.svg
287+
[Downloads]: https://img.shields.io/crates/d/getrandom
288+
[License]: https://img.shields.io/crates/l/getrandom
289+
290+
[//]: # (supported targets)
291+
292+
[1]: https://manned.org/getrandom.2
293+
[2]: https://manned.org/urandom.4
294+
[3]: https://www.unix.com/man-page/mojave/2/getentropy/
295+
[4]: https://www.unix.com/man-page/mojave/4/urandom/
296+
[5]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
297+
[7]: https://man.openbsd.org/getentropy.2
298+
[8]: https://man.netbsd.org/sysctl.7
299+
[9]: https://leaf.dragonflybsd.org/cgi/web-man?command=getrandom
300+
[11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
301+
[12]: https://illumos.org/man/2/getrandom
302+
[13]: https://github.com/emscripten-core/emscripten/pull/12240
303+
[14]: https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.utilities/topic/r/random.html
304+
[15]: https://www.ibm.com/docs/en/aix/7.3?topic=files-random-urandom-devices
305+
[16]: https://man.netbsd.org/getrandom.2
306+
[17]: https://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getrandom
307+
[18]: https://github.com/rust3ds/shim-3ds/commit/b01d2568836dea2a65d05d662f8e5f805c64389d
308+
309+
[`ProcessPrng`]: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
310+
[`RtlGenRandom`]: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
311+
[`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
312+
[`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
313+
[`RNDR`]: https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers/RNDR--Random-Number
314+
[`CCRandomGenerateBytes`]: https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60074/include/CommonRandom.h.auto.html
315+
[`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
316+
[`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size
317+
[`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t
318+
[`random_get`]: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno
319+
[`get-random-u64`]: https://github.com/WebAssembly/WASI/blob/v0.2.1/wasip2/random/random.wit#L23-L28
320+
[WebAssembly support]: #webassembly-support
321+
[configuration flags]: #configuration-flags
322+
[custom backend]: #custom-backend
323+
[`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
324+
[`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html
325+
[CommonJS modules]: https://nodejs.org/api/modules.html
326+
[ES modules]: https://nodejs.org/api/esm.html
327+
[`sys_read_entropy`]: https://github.com/hermit-os/kernel/blob/315f58ff5efc81d9bf0618af85a59963ff55f8b1/src/syscalls/entropy.rs#L47-L55
328+
[platform-support]: https://doc.rust-lang.org/stable/rustc/platform-support.html
329+
[WASI]: https://github.com/CraneStation/wasi
330+
[Emscripten]: https://www.hellorust.com/setup/emscripten/
331+
[`rustix`]: https://docs.rs/rustix
332+
333+
[//]: # (licenses)
334+
80335
[LICENSE-APACHE]: https://github.com/rust-random/getrandom/blob/master/LICENSE-APACHE
81336
[LICENSE-MIT]: https://github.com/rust-random/getrandom/blob/master/LICENSE-MIT
337+
338+
[`Error::UNEXPECTED`]: https://docs.rs/getrandom/latest/getrandom/struct.Error.html#associatedconstant.UNEXPECTED
339+
[`fill_uninit`]: https://docs.rs/getrandom/latest/getrandom/fn.fill_uninit.html

0 commit comments

Comments
 (0)