Bug 1816953 - Update getrandom to 0.2.9. r=emilio,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D174965
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2043,9 +2043,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
|
||||
@@ -1183,6 +1183,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.2.7 -> 0.2.8"
|
||||
|
||||
[[audits.getrandom]]
|
||||
who = "Yannis Juglaret <yjuglaret@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.2.8 -> 0.2.9"
|
||||
|
||||
[[audits.gleam]]
|
||||
who = "Jamie Nicol <jnicol@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"CHANGELOG.md":"cb054908f44d0e7f229dcc4580bcc4f2c3e2da198c84292710f730b33cc3d5f6","Cargo.toml":"708a5d9c89443b937aa50260e26a01f9ebfdd50a7ae312956795834e3187baf3","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"7ae74633326a22fd6298d7f209fb14884277bd98049795f444945acbb2b0dfbd","benches/mod.rs":"c01b05c6d690a4b8937d25252f1385a6bff378517318ce832ea520036aabd571","src/3ds.rs":"0f48fc15f89b518fb92e06aaa4838b62dc073598e8f288df56ad1e5a9251af1e","src/bsd_arandom.rs":"d90c419d4def20f83e7535cd3f5ec07035045011a50c3652951d196a120c5d3e","src/custom.rs":"ce4640776d36872dbbd5e194bf29f6bcda3ef4549ca04fe59f5aeab1dea1d821","src/dragonfly.rs":"47f933eac189f6ea48ecf021efd0747ebce1b43d1bece6bbf72a951bab705987","src/error.rs":"ff09a7e02d7aff3e45eca6bbef6c686cc46f3c2371a0897a856e4dec4b942e46","src/error_impls.rs":"9c34832ebb99cd5e31bc5c8ffc5beb5b3fa6f7ff0226aaa1cdf8e10e6d64b324","src/espidf.rs":"19f101486584fde6dad962f4d9792de168658047312106641a5caf6866a5bbcf","src/fuchsia.rs":"470d8509deb5b06fa6417f294c0a49e0e35a580249a5d8944c3be5aa746f64ea","src/ios.rs":"4bad4f5c096a50338b86aeac91a937c18bc55b9555e6f34806ad13732e64523d","src/js.rs":"370610a19045012c87c986279aad6b150cd728a44015dcc5779256e4a2e6629b","src/lib.rs":"8e5c2c8edcbdbf2cee46b86d96d951cc6d5c00f7c11cfc9c27de27e756b5c4cc","src/linux_android.rs":"ec24575aa4ae71b6991290dadfdea931b05397c3faababf24bd794f1a9624835","src/macos.rs":"6c09827ad5292cd022e063efa79523bfdb50ed08b9867ebaa007cd321b8d218e","src/openbsd.rs":"450a23ead462d4a840fee4aa0bfdab1e3d88c8f48e4bb608d457429ddeca69c0","src/rdrand.rs":"79d23183b1905d61bd9df9729dc798505a2ed750d3339e342ab144e1709827e4","src/solaris_illumos.rs":"d52fee9dd7d661f960c01894edd563c1ff8a512c111f7803092d9aa2ff98718e","src/solid.rs":"997035d54c9762d22a5a14f54e7fbed4dd266cdeacbdf6aab7d8aee05537e8ba","src/use_file.rs":"16e42eb0a56e375c330c1ca8eb58c444e82ef3ad35230b961fdba96a02a68804","src/util.rs":"da6964dc1523f1cb8d26365fa6a8ece46360587e6974931624b271f0c72cda8b","src/util_libc.rs":"2a63ac0e6dab16b85c4728b79a16e0640301e8b876f151b0a1db0b4394fa219f","src/vxworks.rs":"a5aa0e40f890e0f35626458bb656a3340b8af3111e4bacd2e12505a8d50a3505","src/wasi.rs":"dfdd0a870581948bd03abe64d49ca4295d9cfa26e09b97a526fd5e17148ad9ca","src/windows.rs":"d0b4f2afd1959660aa9abcd9477764bd7dc0b7d7048aee748804b37963c77c6f","tests/common/mod.rs":"b6beee8f535d2d094a65711fe0af91a6fc220aa09729ed7269fe33cafdc9177f","tests/custom.rs":"9f2c0193193f6bcf641116ca0b3653b33d2015e0e98ce107ee1d1f60c5eeae3a","tests/normal.rs":"9e1c4b1e468a09ed0225370dfb6608f8b8135e0fabb09bbc1a718105164aade6","tests/rdrand.rs":"4474ccebf9d33c89288862a7e367018405968dddc55c7c6f97e21b5fe2264601"},"package":"c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"}
|
||||
{"files":{"CHANGELOG.md":"c113647d99ea60ff59abfe4e2c3136a47cdda64f22c7bde0d33bccbe56614450","Cargo.toml":"f55b6362cab48ec1f26c786f718487041bbb1c0b0889478158ade0a45c9b6e33","LICENSE-APACHE":"aaff376532ea30a0cd5330b9502ad4a4c8bf769c539c87ffe78819d188a18ebf","LICENSE-MIT":"209fbbe0ad52d9235e37badf9cadfe4dbdc87203179c0899e738b39ade42177b","README.md":"e6b00741964e2d1e3e3ca8cbf4688c88b882f6bcef8a9d6b53ec59f5ea6ccefb","benches/buffer.rs":"242f56eaeecd1d0a0f6f9419d1bf312b8d211215355022bd4aef5e5e0f53e2a5","src/3ds.rs":"e41b653723740ed89fa68f495b64125786e8dec002e3556d164c5795db62ea50","src/apple-other.rs":"3ff0abc72786a2ac063cdc5df4d18cc53dc493cd68fcb33734cf40cfdbb8f644","src/bsd_arandom.rs":"cfa0627a6b4d1f37065d415972ab813bf1c9f43979d2ff9440c92a53868123aa","src/custom.rs":"16bdf3bd6fca0f370f42c217a1e8737c0c549a6820c7b61919d5a2d2bf675b48","src/dragonfly.rs":"047008e742a7a8050e61ed9626b9f4146dfaa0675e11d6f3680eb8af498d9a6d","src/emscripten.rs":"084a146f3106d056bdb4521c2347ea0570bd885f6b9b74b23bde87fad03006c2","src/error.rs":"ff09a7e02d7aff3e45eca6bbef6c686cc46f3c2371a0897a856e4dec4b942e46","src/error_impls.rs":"9c34832ebb99cd5e31bc5c8ffc5beb5b3fa6f7ff0226aaa1cdf8e10e6d64b324","src/espidf.rs":"915ca14cbf9299de51a3c67f34fdd252461d6545f33a7232dfb7fa247ccc0209","src/fuchsia.rs":"d307b15db9f2d67b43050ae6027779a6eb2b8a69e1e89931b55b767aa2622250","src/hermit.rs":"18fdd7917c73f8b16aa82b18003948d32f9b314da10e16ef9cd2fa077b17af00","src/js.rs":"c4cd60bcfe63f8affe947773197e288536ab205a73001059f39fc2e5688e98b6","src/lib.rs":"ddf6ae4673ae7458644966fba324780d0ffd6f27c9f5538c5feed4b98e1c92a4","src/linux_android.rs":"e5f9e579bbde254fcab8f6b79b893d6b74054e023b21c56a3b2b21d8f4b4d825","src/macos.rs":"8f51e095906e751b68e837bfc63cc02b243e1698b66353566ccba507c81ddad3","src/openbsd.rs":"f6fd0aa74f704335a7e0532bf5e61a7ca90b0cbc398a9c01a0fd891b6fabca0c","src/rdrand.rs":"846ac7b8380a05a50e0592dca57338beb1634c0efc878d6d1e9421be3469a744","src/solaris_illumos.rs":"7209c8b1172fc4df5ad8a79f165556b403cdd90b9eb5f7f7f9ec97bf06f4d8d7","src/solid.rs":"58919109faf06e6d546f75f785d78d6c055e1f95110d1791d9191d1e404f1e20","src/use_file.rs":"ecfc1011b4a9c962ae9b4b75ca5149a4ee83cb0951a80224ce5417046ce11717","src/util.rs":"580fb7c4e41eb6007def8626e019829c22a63980fa4da68a1adef687c57953a2","src/util_libc.rs":"3db6d46a3248900df13519729bcd81ecc5941d7b1de07d2097b09c3c4ceb4825","src/vxworks.rs":"984726b6dd9638a38ceda83124683419b9d69a9041ad9117a470eaec5b386ce4","src/wasi.rs":"229a58af3f13a629571fb83a0c11ef0ed696ba7a44ee2e811c9f348a19b2fb69","src/windows.rs":"dd3d833979fb6b96c04b84dbf8461d5fc819bde93ad9dc26bd0f6c282656c733","tests/common/mod.rs":"b9a36043d71963ba43a9e2899ba8eea80ff9f3284d243d9b9b9f941afa4f4aa4","tests/custom.rs":"1e944ae523b62dba53fe3daf1b964a2498c8fdd21dfa7afe53781bff2fcf276e","tests/normal.rs":"9e1c4b1e468a09ed0225370dfb6608f8b8135e0fabb09bbc1a718105164aade6","tests/rdrand.rs":"156676b57f1e6bd4d66d85b8a999f1cf7a8fb749a10b8b2b4dbbcf803e8c4cd3"},"package":"c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"}
|
||||
55
third_party/rust/getrandom/CHANGELOG.md
vendored
55
third_party/rust/getrandom/CHANGELOG.md
vendored
@@ -4,6 +4,56 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.2.9] - 2023-04-03
|
||||
### Added
|
||||
- AIX support [#282]
|
||||
- `getrandom_uninit` function [#291]
|
||||
- `wasm64-unknown-unknown` support [#303]
|
||||
- tvOS and watchOS support [#317]
|
||||
- QNX/nto support [#325]
|
||||
- Support for `getrandom` syscall on NetBSD ≥ 10.0 [#331]
|
||||
- `RtlGenRandom` fallback for non-UWP Windows [#337]
|
||||
|
||||
### Breaking Changes
|
||||
- Update MSRV to 1.36 [#291]
|
||||
|
||||
### Fixed
|
||||
- Solaris/OpenBSD/Dragonfly build [#301]
|
||||
|
||||
### Changed
|
||||
- Update MSRV to 1.36 [#291]
|
||||
- Use getentropy on Emscripten [#307]
|
||||
- Solaris: consistantly use `/dev/random` source [#310]
|
||||
- Move 3ds selection above rdrand/js/custom fallback [#312]
|
||||
- Remove buffer zeroing from Node.js implementation [#315]
|
||||
- Use `open` instead of `open64` [#326]
|
||||
- Remove #cfg from bsd_arandom.rs [#332]
|
||||
- Hermit: use `sys_read_entropy` syscall [#333]
|
||||
- Eliminate potential panic in sys_fill_exact [#334]
|
||||
- rdrand: Remove checking for 0 and !0 and instead check CPU family and do a self-test [#335]
|
||||
- Move `__getrandom_custom` definition into a const block [#344]
|
||||
- Switch the custom backend to Rust ABI [#347]
|
||||
|
||||
[#282]: https://github.com/rust-random/getrandom/pull/282
|
||||
[#291]: https://github.com/rust-random/getrandom/pull/291
|
||||
[#301]: https://github.com/rust-random/getrandom/pull/301
|
||||
[#303]: https://github.com/rust-random/getrandom/pull/303
|
||||
[#307]: https://github.com/rust-random/getrandom/pull/307
|
||||
[#310]: https://github.com/rust-random/getrandom/pull/310
|
||||
[#312]: https://github.com/rust-random/getrandom/pull/312
|
||||
[#315]: https://github.com/rust-random/getrandom/pull/315
|
||||
[#317]: https://github.com/rust-random/getrandom/pull/317
|
||||
[#325]: https://github.com/rust-random/getrandom/pull/325
|
||||
[#326]: https://github.com/rust-random/getrandom/pull/326
|
||||
[#331]: https://github.com/rust-random/getrandom/pull/331
|
||||
[#332]: https://github.com/rust-random/getrandom/pull/332
|
||||
[#333]: https://github.com/rust-random/getrandom/pull/333
|
||||
[#334]: https://github.com/rust-random/getrandom/pull/334
|
||||
[#335]: https://github.com/rust-random/getrandom/pull/335
|
||||
[#337]: https://github.com/rust-random/getrandom/pull/337
|
||||
[#344]: https://github.com/rust-random/getrandom/pull/344
|
||||
[#347]: https://github.com/rust-random/getrandom/pull/347
|
||||
|
||||
## [0.2.8] - 2022-10-20
|
||||
### Changed
|
||||
- The [Web Cryptography API] will now be preferred on `wasm32-unknown-unknown`
|
||||
@@ -95,7 +145,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## [0.2.2] - 2021-01-19
|
||||
### Changed
|
||||
- Forward `rustc-dep-of-std` to dependencies. [#198]
|
||||
- Highlight feature-dependend functionality in documentation using the `doc_cfg` feature. [#200]
|
||||
- Highlight feature-dependent functionality in documentation using the `doc_cfg` feature. [#200]
|
||||
|
||||
[#198]: https://github.com/rust-random/getrandom/pull/198
|
||||
[#200]: https://github.com/rust-random/getrandom/pull/200
|
||||
@@ -225,7 +275,7 @@ disabled `dummy` feature. [#90]
|
||||
## [0.1.9] - 2019-08-14 [YANKED]
|
||||
### Changed
|
||||
- Remove `std` dependency for opening and reading files. [#58]
|
||||
- Use `wasi` isntead of `libc` on WASI target. [#64]
|
||||
- Use `wasi` instead of `libc` on WASI target. [#64]
|
||||
- By default emit a compile-time error when built for an unsupported target.
|
||||
This behaviour can be disabled by using the `dummy` feature. [#71]
|
||||
|
||||
@@ -331,6 +381,7 @@ Publish initial implementation.
|
||||
## [0.0.0] - 2019-01-19
|
||||
Publish an empty template library.
|
||||
|
||||
[0.2.9]: https://github.com/rust-random/getrandom/compare/v0.2.8...v0.2.9
|
||||
[0.2.8]: https://github.com/rust-random/getrandom/compare/v0.2.7...v0.2.8
|
||||
[0.2.7]: https://github.com/rust-random/getrandom/compare/v0.2.6...v0.2.7
|
||||
[0.2.6]: https://github.com/rust-random/getrandom/compare/v0.2.5...v0.2.6
|
||||
|
||||
11
third_party/rust/getrandom/Cargo.toml
vendored
11
third_party/rust/getrandom/Cargo.toml
vendored
@@ -12,7 +12,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
authors = ["The Rand Project Developers"]
|
||||
exclude = [".*"]
|
||||
description = "A small cross-platform library for retrieving random data from system source"
|
||||
@@ -63,21 +63,22 @@ rustc-dep-of-std = [
|
||||
std = []
|
||||
test-in-browser = []
|
||||
|
||||
[target."cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))".dependencies.js-sys]
|
||||
[target."cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))".dependencies.js-sys]
|
||||
version = "0.3"
|
||||
optional = true
|
||||
|
||||
[target."cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))".dependencies.wasm-bindgen]
|
||||
[target."cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))".dependencies.wasm-bindgen]
|
||||
version = "0.2.62"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[target."cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))".dev-dependencies.wasm-bindgen-test]
|
||||
[target."cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))".dev-dependencies.wasm-bindgen-test]
|
||||
version = "0.3.18"
|
||||
|
||||
[target."cfg(target_os = \"wasi\")".dependencies.wasi]
|
||||
version = "0.11"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(unix)".dependencies.libc]
|
||||
version = "0.2.120"
|
||||
version = "0.2.139"
|
||||
default-features = false
|
||||
|
||||
8
third_party/rust/getrandom/README.md
vendored
8
third_party/rust/getrandom/README.md
vendored
@@ -15,10 +15,10 @@
|
||||
[License]: https://img.shields.io/crates/l/getrandom
|
||||
|
||||
|
||||
A Rust library for retrieving random data from (operating) system source. It is
|
||||
assumed that system always provides high-quality cryptographically secure random
|
||||
A Rust library for retrieving random data from (operating) system sources. It is
|
||||
assumed that the system always provides high-quality cryptographically secure random
|
||||
data, ideally backed by hardware entropy sources. This crate derives its name
|
||||
from Linux's `getrandom` function, but is cross platform, roughly supporting
|
||||
from Linux's `getrandom` function, but is cross-platform, roughly supporting
|
||||
the same set of platforms as Rust's `std` lib.
|
||||
|
||||
This is a low-level API. Most users should prefer using high-level random-number
|
||||
@@ -52,7 +52,7 @@ crate features, WASM support and Custom RNGs see the
|
||||
|
||||
## Minimum Supported Rust Version
|
||||
|
||||
This crate requires Rust 1.34.0 or later.
|
||||
This crate requires Rust 1.36.0 or later.
|
||||
|
||||
# License
|
||||
|
||||
|
||||
71
third_party/rust/getrandom/benches/buffer.rs
vendored
Normal file
71
third_party/rust/getrandom/benches/buffer.rs
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
#![feature(test, maybe_uninit_uninit_array_transpose)]
|
||||
extern crate test;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
// Call getrandom on a zero-initialized stack buffer
|
||||
#[inline(always)]
|
||||
fn bench_getrandom<const N: usize>() {
|
||||
let mut buf = [0u8; N];
|
||||
getrandom::getrandom(&mut buf).unwrap();
|
||||
test::black_box(&buf as &[u8]);
|
||||
}
|
||||
|
||||
// Call getrandom_uninit on an uninitialized stack buffer
|
||||
#[inline(always)]
|
||||
fn bench_getrandom_uninit<const N: usize>() {
|
||||
let mut uninit = [MaybeUninit::uninit(); N];
|
||||
let buf: &[u8] = getrandom::getrandom_uninit(&mut uninit).unwrap();
|
||||
test::black_box(buf);
|
||||
}
|
||||
|
||||
// We benchmark using #[inline(never)] "inner" functions for two reasons:
|
||||
// - Avoiding inlining reduces a source of variance when running benchmarks.
|
||||
// - It is _much_ easier to get the assembly or IR for the inner loop.
|
||||
//
|
||||
// For example, using cargo-show-asm (https://github.com/pacak/cargo-show-asm),
|
||||
// we can get the assembly for a particular benchmark's inner loop by running:
|
||||
// cargo asm --bench buffer --release buffer::p384::bench_getrandom::inner
|
||||
macro_rules! bench {
|
||||
( $name:ident, $size:expr ) => {
|
||||
pub mod $name {
|
||||
#[bench]
|
||||
pub fn bench_getrandom(b: &mut test::Bencher) {
|
||||
#[inline(never)]
|
||||
fn inner() {
|
||||
super::bench_getrandom::<{ $size }>()
|
||||
}
|
||||
|
||||
b.bytes = $size as u64;
|
||||
b.iter(inner);
|
||||
}
|
||||
#[bench]
|
||||
pub fn bench_getrandom_uninit(b: &mut test::Bencher) {
|
||||
#[inline(never)]
|
||||
fn inner() {
|
||||
super::bench_getrandom_uninit::<{ $size }>()
|
||||
}
|
||||
|
||||
b.bytes = $size as u64;
|
||||
b.iter(inner);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 16 bytes (128 bits) is the size of an 128-bit AES key/nonce.
|
||||
bench!(aes128, 128 / 8);
|
||||
|
||||
// 32 bytes (256 bits) is the seed sized used for rand::thread_rng
|
||||
// and the `random` value in a ClientHello/ServerHello for TLS.
|
||||
// This is also the size of a 256-bit AES/HMAC/P-256/Curve25519 key
|
||||
// and/or nonce.
|
||||
bench!(p256, 256 / 8);
|
||||
|
||||
// A P-384/HMAC-384 key and/or nonce.
|
||||
bench!(p384, 384 / 8);
|
||||
|
||||
// Initializing larger buffers is not the primary use case of this library, as
|
||||
// this should normally be done by a userspace CSPRNG. However, we have a test
|
||||
// here to see the effects of a lower (amortized) syscall overhead.
|
||||
bench!(page, 4096);
|
||||
94
third_party/rust/getrandom/benches/mod.rs
vendored
94
third_party/rust/getrandom/benches/mod.rs
vendored
@@ -1,94 +0,0 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use std::{
|
||||
alloc::{alloc_zeroed, dealloc, Layout},
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
// AlignedBuffer is like a Box<[u8; N]> except that it is always N-byte aligned
|
||||
struct AlignedBuffer<const N: usize>(NonNull<[u8; N]>);
|
||||
|
||||
impl<const N: usize> AlignedBuffer<N> {
|
||||
fn layout() -> Layout {
|
||||
Layout::from_size_align(N, N).unwrap()
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
let p = unsafe { alloc_zeroed(Self::layout()) } as *mut [u8; N];
|
||||
Self(NonNull::new(p).unwrap())
|
||||
}
|
||||
|
||||
fn buf(&mut self) -> &mut [u8; N] {
|
||||
unsafe { self.0.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Drop for AlignedBuffer<N> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { dealloc(self.0.as_ptr() as *mut u8, Self::layout()) }
|
||||
}
|
||||
}
|
||||
|
||||
// Used to benchmark the throughput of getrandom in an optimal scenario.
|
||||
// The buffer is hot, and does not require initialization.
|
||||
#[inline(always)]
|
||||
fn bench<const N: usize>(b: &mut test::Bencher) {
|
||||
let mut ab = AlignedBuffer::<N>::new();
|
||||
let buf = ab.buf();
|
||||
b.iter(|| {
|
||||
getrandom::getrandom(&mut buf[..]).unwrap();
|
||||
test::black_box(&buf);
|
||||
});
|
||||
b.bytes = N as u64;
|
||||
}
|
||||
|
||||
// Used to benchmark the throughput of getrandom is a slightly less optimal
|
||||
// scenario. The buffer is still hot, but requires initialization.
|
||||
#[inline(always)]
|
||||
fn bench_with_init<const N: usize>(b: &mut test::Bencher) {
|
||||
let mut ab = AlignedBuffer::<N>::new();
|
||||
let buf = ab.buf();
|
||||
b.iter(|| {
|
||||
for byte in buf.iter_mut() {
|
||||
*byte = 0;
|
||||
}
|
||||
getrandom::getrandom(&mut buf[..]).unwrap();
|
||||
test::black_box(&buf);
|
||||
});
|
||||
b.bytes = N as u64;
|
||||
}
|
||||
|
||||
// 32 bytes (256-bit) is the seed sized used for rand::thread_rng
|
||||
const SEED: usize = 32;
|
||||
// Common size of a page, 4 KiB
|
||||
const PAGE: usize = 4096;
|
||||
// Large buffer to get asymptotic performance, 2 MiB
|
||||
const LARGE: usize = 1 << 21;
|
||||
|
||||
#[bench]
|
||||
fn bench_seed(b: &mut test::Bencher) {
|
||||
bench::<SEED>(b);
|
||||
}
|
||||
#[bench]
|
||||
fn bench_seed_init(b: &mut test::Bencher) {
|
||||
bench_with_init::<SEED>(b);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_page(b: &mut test::Bencher) {
|
||||
bench::<PAGE>(b);
|
||||
}
|
||||
#[bench]
|
||||
fn bench_page_init(b: &mut test::Bencher) {
|
||||
bench_with_init::<PAGE>(b);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_large(b: &mut test::Bencher) {
|
||||
bench::<LARGE>(b);
|
||||
}
|
||||
#[bench]
|
||||
fn bench_large_init(b: &mut test::Bencher) {
|
||||
bench_with_init::<LARGE>(b);
|
||||
}
|
||||
3
third_party/rust/getrandom/src/3ds.rs
vendored
3
third_party/rust/getrandom/src/3ds.rs
vendored
@@ -9,8 +9,9 @@
|
||||
//! Implementation for Nintendo 3DS
|
||||
use crate::util_libc::sys_fill_exact;
|
||||
use crate::Error;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
sys_fill_exact(dest, |buf| unsafe {
|
||||
libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, buf.len(), 0)
|
||||
})
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
|
||||
//! Implementation for iOS
|
||||
use crate::Error;
|
||||
use core::{ffi::c_void, ptr::null};
|
||||
use core::{ffi::c_void, mem::MaybeUninit, ptr::null};
|
||||
|
||||
#[link(name = "Security", kind = "framework")]
|
||||
extern "C" {
|
||||
fn SecRandomCopyBytes(rnd: *const c_void, count: usize, bytes: *mut u8) -> i32;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// Apple's documentation guarantees kSecRandomDefault is a synonym for NULL.
|
||||
let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), dest.as_mut_ptr()) };
|
||||
let ret = unsafe { SecRandomCopyBytes(null(), dest.len(), dest.as_mut_ptr() as *mut u8) };
|
||||
// errSecSuccess (from SecBase.h) is always zero.
|
||||
if ret != 0 {
|
||||
Err(Error::IOS_SEC_RANDOM)
|
||||
31
third_party/rust/getrandom/src/bsd_arandom.rs
vendored
31
third_party/rust/getrandom/src/bsd_arandom.rs
vendored
@@ -7,10 +7,13 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for FreeBSD and NetBSD
|
||||
use crate::{util_libc::sys_fill_exact, Error};
|
||||
use core::ptr;
|
||||
use crate::{
|
||||
util_libc::{sys_fill_exact, Weak},
|
||||
Error,
|
||||
};
|
||||
use core::{mem::MaybeUninit, ptr};
|
||||
|
||||
fn kern_arnd(buf: &mut [u8]) -> libc::ssize_t {
|
||||
fn kern_arnd(buf: &mut [MaybeUninit<u8>]) -> libc::ssize_t {
|
||||
static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND];
|
||||
let mut len = buf.len();
|
||||
let ret = unsafe {
|
||||
@@ -30,20 +33,18 @@ fn kern_arnd(buf: &mut [u8]) -> libc::ssize_t {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
// getrandom(2) was introduced in FreeBSD 12.0 and NetBSD 10.0
|
||||
#[cfg(target_os = "freebsd")]
|
||||
{
|
||||
use crate::util_libc::Weak;
|
||||
static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") };
|
||||
type GetRandomFn =
|
||||
unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
|
||||
type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
|
||||
|
||||
if let Some(fptr) = GETRANDOM.ptr() {
|
||||
let func: GetRandomFn = unsafe { core::mem::transmute(fptr) };
|
||||
return sys_fill_exact(dest, |buf| unsafe { func(buf.as_mut_ptr(), buf.len(), 0) });
|
||||
}
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// getrandom(2) was introduced in FreeBSD 12.0 and NetBSD 10.0
|
||||
static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") };
|
||||
if let Some(fptr) = GETRANDOM.ptr() {
|
||||
let func: GetRandomFn = unsafe { core::mem::transmute(fptr) };
|
||||
return sys_fill_exact(dest, |buf| unsafe {
|
||||
func(buf.as_mut_ptr() as *mut u8, buf.len(), 0)
|
||||
});
|
||||
}
|
||||
|
||||
// Both FreeBSD and NetBSD will only return up to 256 bytes at a time, and
|
||||
// older NetBSD kernels will fail on longer buffers.
|
||||
for chunk in dest.chunks_mut(256) {
|
||||
|
||||
38
third_party/rust/getrandom/src/custom.rs
vendored
38
third_party/rust/getrandom/src/custom.rs
vendored
@@ -7,8 +7,8 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! An implementation which calls out to an externally defined function.
|
||||
use crate::Error;
|
||||
use core::num::NonZeroU32;
|
||||
use crate::{util::uninit_slice_fill_zero, Error};
|
||||
use core::{mem::MaybeUninit, num::NonZeroU32};
|
||||
|
||||
/// Register a function to be invoked by `getrandom` on unsupported targets.
|
||||
///
|
||||
@@ -76,24 +76,36 @@ use core::num::NonZeroU32;
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "custom")))]
|
||||
macro_rules! register_custom_getrandom {
|
||||
($path:path) => {
|
||||
// We use an extern "C" function to get the guarantees of a stable ABI.
|
||||
#[no_mangle]
|
||||
extern "C" fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 {
|
||||
let f: fn(&mut [u8]) -> Result<(), $crate::Error> = $path;
|
||||
let slice = unsafe { ::core::slice::from_raw_parts_mut(dest, len) };
|
||||
match f(slice) {
|
||||
Ok(()) => 0,
|
||||
Err(e) => e.code().get(),
|
||||
// TODO(MSRV 1.37): change to unnamed block
|
||||
const __getrandom_internal: () = {
|
||||
// We use Rust ABI to be safe against potential panics in the passed function.
|
||||
#[no_mangle]
|
||||
unsafe fn __getrandom_custom(dest: *mut u8, len: usize) -> u32 {
|
||||
// Make sure the passed function has the type of getrandom::getrandom
|
||||
type F = fn(&mut [u8]) -> ::core::result::Result<(), $crate::Error>;
|
||||
let _: F = $crate::getrandom;
|
||||
let f: F = $path;
|
||||
let slice = ::core::slice::from_raw_parts_mut(dest, len);
|
||||
match f(slice) {
|
||||
Ok(()) => 0,
|
||||
Err(e) => e.code().get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
extern "C" {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
extern "Rust" {
|
||||
fn __getrandom_custom(dest: *mut u8, len: usize) -> u32;
|
||||
}
|
||||
// Previously we always passed a valid, initialized slice to
|
||||
// `__getrandom_custom`. Ensure `dest` has been initialized for backward
|
||||
// compatibility with implementations that rely on that (e.g. Rust
|
||||
// implementations that construct a `&mut [u8]` slice from `dest` and
|
||||
// `len`).
|
||||
let dest = uninit_slice_fill_zero(dest);
|
||||
let ret = unsafe { __getrandom_custom(dest.as_mut_ptr(), dest.len()) };
|
||||
match NonZeroU32::new(ret) {
|
||||
None => Ok(()),
|
||||
|
||||
7
third_party/rust/getrandom/src/dragonfly.rs
vendored
7
third_party/rust/getrandom/src/dragonfly.rs
vendored
@@ -12,15 +12,18 @@ use crate::{
|
||||
util_libc::{sys_fill_exact, Weak},
|
||||
Error,
|
||||
};
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") };
|
||||
type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
|
||||
|
||||
// getrandom(2) was introduced in DragonflyBSD 5.7
|
||||
if let Some(fptr) = GETRANDOM.ptr() {
|
||||
let func: GetRandomFn = unsafe { core::mem::transmute(fptr) };
|
||||
return sys_fill_exact(dest, |buf| unsafe { func(buf.as_mut_ptr(), buf.len(), 0) });
|
||||
return sys_fill_exact(dest, |buf| unsafe {
|
||||
func(buf.as_mut_ptr() as *mut u8, buf.len(), 0)
|
||||
});
|
||||
} else {
|
||||
use_file::getrandom_inner(dest)
|
||||
}
|
||||
|
||||
18
third_party/rust/getrandom/src/emscripten.rs
vendored
Normal file
18
third_party/rust/getrandom/src/emscripten.rs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
//! Implementation for Emscripten
|
||||
use crate::{util_libc::last_os_error, Error};
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
// Not yet defined in libc crate.
|
||||
extern "C" {
|
||||
fn getentropy(buffer: *mut libc::c_void, length: usize) -> libc::c_int;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// Emscripten 2.0.5 added getentropy, so we can use it unconditionally.
|
||||
// Unlike other getentropy implementations, there is no max buffer length.
|
||||
let ret = unsafe { getentropy(dest.as_mut_ptr() as *mut libc::c_void, dest.len()) };
|
||||
if ret < 0 {
|
||||
return Err(last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
4
third_party/rust/getrandom/src/espidf.rs
vendored
4
third_party/rust/getrandom/src/espidf.rs
vendored
@@ -8,13 +8,13 @@
|
||||
|
||||
//! Implementation for ESP-IDF
|
||||
use crate::Error;
|
||||
use core::ffi::c_void;
|
||||
use core::{ffi::c_void, mem::MaybeUninit};
|
||||
|
||||
extern "C" {
|
||||
fn esp_fill_random(buf: *mut c_void, len: usize) -> u32;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// Not that NOT enabling WiFi, BT, or the voltage noise entropy source (via `bootloader_random_enable`)
|
||||
// will cause ESP-IDF to return pseudo-random numbers based on the voltage noise entropy, after the initial boot process:
|
||||
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html
|
||||
|
||||
5
third_party/rust/getrandom/src/fuchsia.rs
vendored
5
third_party/rust/getrandom/src/fuchsia.rs
vendored
@@ -8,13 +8,14 @@
|
||||
|
||||
//! Implementation for Fuchsia Zircon
|
||||
use crate::Error;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
#[link(name = "zircon")]
|
||||
extern "C" {
|
||||
fn zx_cprng_draw(buffer: *mut u8, length: usize);
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
unsafe { zx_cprng_draw(dest.as_mut_ptr(), dest.len()) }
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
unsafe { zx_cprng_draw(dest.as_mut_ptr() as *mut u8, dest.len()) }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
21
third_party/rust/getrandom/src/hermit.rs
vendored
Normal file
21
third_party/rust/getrandom/src/hermit.rs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
use crate::Error;
|
||||
use core::{cmp::min, mem::MaybeUninit, num::NonZeroU32};
|
||||
|
||||
extern "C" {
|
||||
fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
while !dest.is_empty() {
|
||||
let res = unsafe { sys_read_entropy(dest.as_mut_ptr() as *mut u8, dest.len(), 0) };
|
||||
if res < 0 {
|
||||
// SAFETY: all Hermit error codes use i32 under the hood:
|
||||
// https://github.com/hermitcore/libhermit-rs/blob/master/src/errno.rs
|
||||
let code = unsafe { NonZeroU32::new_unchecked((-res) as u32) };
|
||||
return Err(code.into());
|
||||
}
|
||||
let len = min(res as usize, dest.len());
|
||||
dest = &mut dest[len..];
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
29
third_party/rust/getrandom/src/js.rs
vendored
29
third_party/rust/getrandom/src/js.rs
vendored
@@ -8,7 +8,7 @@
|
||||
use crate::Error;
|
||||
|
||||
extern crate std;
|
||||
use std::thread_local;
|
||||
use std::{mem::MaybeUninit, thread_local};
|
||||
|
||||
use js_sys::{global, Function, Uint8Array};
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
|
||||
@@ -16,6 +16,8 @@ use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
|
||||
// Size of our temporary Uint8Array buffer used with WebCrypto methods
|
||||
// Maximum is 65536 bytes see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
|
||||
const WEB_CRYPTO_BUFFER_SIZE: usize = 256;
|
||||
// Node.js's crypto.randomFillSync requires the size to be less than 2**31.
|
||||
const NODE_MAX_BUFFER_SIZE: usize = (1 << 31) - 1;
|
||||
|
||||
enum RngSource {
|
||||
Node(NodeCrypto),
|
||||
@@ -28,14 +30,27 @@ thread_local!(
|
||||
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
|
||||
);
|
||||
|
||||
pub(crate) fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub(crate) fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
RNG_SOURCE.with(|result| {
|
||||
let source = result.as_ref().map_err(|&e| e)?;
|
||||
|
||||
match source {
|
||||
RngSource::Node(n) => {
|
||||
if n.random_fill_sync(dest).is_err() {
|
||||
return Err(Error::NODE_RANDOM_FILL_SYNC);
|
||||
for chunk in dest.chunks_mut(NODE_MAX_BUFFER_SIZE) {
|
||||
// SAFETY: chunk is never used directly, the memory is only
|
||||
// modified via the Uint8Array view, which is passed
|
||||
// directly to JavaScript. Also, crypto.randomFillSync does
|
||||
// not resize the buffer. We know the length is less than
|
||||
// u32::MAX because of the chunking above.
|
||||
// Note that this uses the fact that JavaScript doesn't
|
||||
// have a notion of "uninitialized memory", this is purely
|
||||
// a Rust/C/C++ concept.
|
||||
let res = n.random_fill_sync(unsafe {
|
||||
Uint8Array::view_mut_raw(chunk.as_mut_ptr() as *mut u8, chunk.len())
|
||||
});
|
||||
if res.is_err() {
|
||||
return Err(Error::NODE_RANDOM_FILL_SYNC);
|
||||
}
|
||||
}
|
||||
}
|
||||
RngSource::Web(crypto, buf) => {
|
||||
@@ -49,7 +64,9 @@ pub(crate) fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
if crypto.get_random_values(&sub_buf).is_err() {
|
||||
return Err(Error::WEB_GET_RANDOM_VALUES);
|
||||
}
|
||||
sub_buf.copy_to(chunk);
|
||||
|
||||
// SAFETY: `sub_buf`'s length is the same length as `chunk`
|
||||
unsafe { sub_buf.raw_copy_to_ptr(chunk.as_mut_ptr() as *mut u8) };
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -120,7 +137,7 @@ extern "C" {
|
||||
type NodeCrypto;
|
||||
// crypto.randomFillSync()
|
||||
#[wasm_bindgen(method, js_name = randomFillSync, catch)]
|
||||
fn random_fill_sync(this: &NodeCrypto, buf: &mut [u8]) -> Result<(), JsValue>;
|
||||
fn random_fill_sync(this: &NodeCrypto, buf: Uint8Array) -> Result<(), JsValue>;
|
||||
|
||||
// Ideally, we would just use `fn require(s: &str)` here. However, doing
|
||||
// this causes a Webpack warning. So we instead return the function itself
|
||||
|
||||
111
third_party/rust/getrandom/src/lib.rs
vendored
111
third_party/rust/getrandom/src/lib.rs
vendored
@@ -14,25 +14,27 @@
|
||||
//! | ----------------- | ------------------ | --------------
|
||||
//! | Linux, Android | `*‑linux‑*` | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
|
||||
//! | Windows | `*‑windows‑*` | [`BCryptGenRandom`]
|
||||
//! | macOS | `*‑apple‑darwin` | [`getentropy`][3] if available, otherwise [`/dev/random`][4] (identical to `/dev/urandom`)
|
||||
//! | iOS | `*‑apple‑ios` | [`SecRandomCopyBytes`]
|
||||
//! | macOS | `*‑apple‑darwin` | [`getentropy`][3] if available, otherwise [`/dev/urandom`][4] (identical to `/dev/random`)
|
||||
//! | iOS, tvOS, watchOS | `*‑apple‑ios`, `*-apple-tvos`, `*-apple-watchos` | [`SecRandomCopyBytes`]
|
||||
//! | FreeBSD | `*‑freebsd` | [`getrandom`][5] if available, otherwise [`kern.arandom`][6]
|
||||
//! | OpenBSD | `*‑openbsd` | [`getentropy`][7]
|
||||
//! | NetBSD | `*‑netbsd` | [`kern.arandom`][8]
|
||||
//! | Dragonfly BSD | `*‑dragonfly` | [`getrandom`][9] if available, otherwise [`/dev/random`][10]
|
||||
//! | NetBSD | `*‑netbsd` | [`getrandom`][16] if available, otherwise [`kern.arandom`][8]
|
||||
//! | Dragonfly BSD | `*‑dragonfly` | [`getrandom`][9] if available, otherwise [`/dev/urandom`][10] (identical to `/dev/random`)
|
||||
//! | Solaris, illumos | `*‑solaris`, `*‑illumos` | [`getrandom`][11] if available, otherwise [`/dev/random`][12]
|
||||
//! | Fuchsia OS | `*‑fuchsia` | [`cprng_draw`]
|
||||
//! | Redox | `*‑redox` | `/dev/urandom`
|
||||
//! | Haiku | `*‑haiku` | `/dev/random` (identical to `/dev/urandom`)
|
||||
//! | Hermit | `x86_64-*-hermit` | [`RDRAND`]
|
||||
//! | Haiku | `*‑haiku` | `/dev/urandom` (identical to `/dev/random`)
|
||||
//! | Hermit | `*-hermit` | [`sys_read_entropy`]
|
||||
//! | SGX | `x86_64‑*‑sgx` | [`RDRAND`]
|
||||
//! | VxWorks | `*‑wrs‑vxworks‑*` | `randABytes` after checking entropy pool initialization with `randSecure`
|
||||
//! | ESP-IDF | `*‑espidf` | [`esp_fill_random`]
|
||||
//! | Emscripten | `*‑emscripten` | `/dev/random` (identical to `/dev/urandom`)
|
||||
//! | Emscripten | `*‑emscripten` | [`getentropy`][13]
|
||||
//! | WASI | `wasm32‑wasi` | [`random_get`]
|
||||
//! | Web Browser and Node.js | `wasm32‑*‑unknown` | [`Crypto.getRandomValues`] if available, then [`crypto.randomFillSync`] if on Node.js, see [WebAssembly support]
|
||||
//! | Web Browser and Node.js | `wasm*‑*‑unknown` | [`Crypto.getRandomValues`] if available, then [`crypto.randomFillSync`] if on Node.js, see [WebAssembly support]
|
||||
//! | SOLID | `*-kmc-solid_*` | `SOLID_RNG_SampleRandomBytes`
|
||||
//! | Nintendo 3DS | `armv6k-nintendo-3ds` | [`getrandom`][1]
|
||||
//! | QNX Neutrino | `*‑nto-qnx*` | [`/dev/urandom`][14] (identical to `/dev/random`)
|
||||
//! | AIX | `*-ibm-aix` | [`/dev/urandom`][15]
|
||||
//!
|
||||
//! There is no blanket implementation on `unix` targets that reads from
|
||||
//! `/dev/urandom`. This ensures all supported targets are using the recommended
|
||||
@@ -150,7 +152,7 @@
|
||||
//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
|
||||
//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
|
||||
//! [3]: https://www.unix.com/man-page/mojave/2/getentropy/
|
||||
//! [4]: https://www.unix.com/man-page/mojave/4/random/
|
||||
//! [4]: https://www.unix.com/man-page/mojave/4/urandom/
|
||||
//! [5]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
|
||||
//! [6]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
|
||||
//! [7]: https://man.openbsd.org/getentropy.2
|
||||
@@ -159,6 +161,10 @@
|
||||
//! [10]: https://leaf.dragonflybsd.org/cgi/web-man?command=random§ion=4
|
||||
//! [11]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
|
||||
//! [12]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
|
||||
//! [13]: https://github.com/emscripten-core/emscripten/pull/12240
|
||||
//! [14]: https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.utilities/topic/r/random.html
|
||||
//! [15]: https://www.ibm.com/docs/en/aix/7.3?topic=files-random-urandom-devices
|
||||
//! [16]: https://man.netbsd.org/getrandom.2
|
||||
//!
|
||||
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
|
||||
//! [`Crypto.getRandomValues`]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
|
||||
@@ -173,11 +179,12 @@
|
||||
//! [`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html
|
||||
//! [CommonJS modules]: https://nodejs.org/api/modules.html
|
||||
//! [ES modules]: https://nodejs.org/api/esm.html
|
||||
//! [`sys_read_entropy`]: https://hermitcore.github.io/libhermit-rs/hermit/fn.sys_read_entropy.html
|
||||
|
||||
#![doc(
|
||||
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
|
||||
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://docs.rs/getrandom/0.2.8"
|
||||
html_root_url = "https://docs.rs/getrandom/0.2.9"
|
||||
)]
|
||||
#![no_std]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
|
||||
@@ -186,6 +193,9 @@
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
|
||||
use crate::util::{slice_as_uninit_mut, slice_assume_init_mut};
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
mod error;
|
||||
mod util;
|
||||
// To prevent a breaking change when targets are added, we always export the
|
||||
@@ -199,10 +209,13 @@ pub use crate::error::Error;
|
||||
|
||||
// System-specific implementations.
|
||||
//
|
||||
// These should all provide getrandom_inner with the same signature as getrandom.
|
||||
// These should all provide getrandom_inner with the signature
|
||||
// `fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>`.
|
||||
// The function MUST fully initialize `dest` when `Ok(())` is returned.
|
||||
// The function MUST NOT ever write uninitialized bytes into `dest`,
|
||||
// regardless of what value it returns.
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "emscripten", target_os = "haiku",
|
||||
target_os = "redox"))] {
|
||||
if #[cfg(any(target_os = "haiku", target_os = "redox", target_os = "nto", target_os = "aix"))] {
|
||||
mod util_libc;
|
||||
#[path = "use_file.rs"] mod imp;
|
||||
} else if #[cfg(any(target_os = "android", target_os = "linux"))] {
|
||||
@@ -222,8 +235,8 @@ cfg_if! {
|
||||
#[path = "dragonfly.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "fuchsia")] {
|
||||
#[path = "fuchsia.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "ios")] {
|
||||
#[path = "ios.rs"] mod imp;
|
||||
} else if #[cfg(any(target_os = "ios", target_os = "watchos", target_os = "tvos"))] {
|
||||
#[path = "apple-other.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "macos")] {
|
||||
mod util_libc;
|
||||
mod use_file;
|
||||
@@ -231,10 +244,10 @@ cfg_if! {
|
||||
} else if #[cfg(target_os = "openbsd")] {
|
||||
mod util_libc;
|
||||
#[path = "openbsd.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "wasi")] {
|
||||
} else if #[cfg(all(target_arch = "wasm32", target_os = "wasi"))] {
|
||||
#[path = "wasi.rs"] mod imp;
|
||||
} else if #[cfg(all(target_arch = "x86_64", target_os = "hermit"))] {
|
||||
#[path = "rdrand.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
#[path = "hermit.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "vxworks")] {
|
||||
mod util_libc;
|
||||
#[path = "vxworks.rs"] mod imp;
|
||||
@@ -244,23 +257,28 @@ cfg_if! {
|
||||
#[path = "espidf.rs"] mod imp;
|
||||
} else if #[cfg(windows)] {
|
||||
#[path = "windows.rs"] mod imp;
|
||||
} else if #[cfg(all(target_os = "horizon", target_arch = "arm"))] {
|
||||
// We check for target_arch = "arm" because the Nintendo Switch also
|
||||
// uses Horizon OS (it is aarch64).
|
||||
mod util_libc;
|
||||
#[path = "3ds.rs"] mod imp;
|
||||
} else if #[cfg(target_os = "emscripten")] {
|
||||
mod util_libc;
|
||||
#[path = "emscripten.rs"] mod imp;
|
||||
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
|
||||
#[path = "rdrand.rs"] mod imp;
|
||||
} else if #[cfg(all(feature = "rdrand",
|
||||
any(target_arch = "x86_64", target_arch = "x86")))] {
|
||||
#[path = "rdrand.rs"] mod imp;
|
||||
} else if #[cfg(all(feature = "js",
|
||||
target_arch = "wasm32", target_os = "unknown"))] {
|
||||
any(target_arch = "wasm32", target_arch = "wasm64"),
|
||||
target_os = "unknown"))] {
|
||||
#[path = "js.rs"] mod imp;
|
||||
} else if #[cfg(all(target_os = "horizon", target_arch = "arm"))] {
|
||||
// We check for target_arch = "arm" because the Nintendo Switch also
|
||||
// uses Horizon OS (it is aarch64).
|
||||
mod util_libc;
|
||||
#[path = "3ds.rs"] mod imp;
|
||||
} else if #[cfg(feature = "custom")] {
|
||||
use custom as imp;
|
||||
} else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
|
||||
compile_error!("the wasm32-unknown-unknown target is not supported by \
|
||||
} else if #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"),
|
||||
target_os = "unknown"))] {
|
||||
compile_error!("the wasm*-unknown-unknown targets are not supported by \
|
||||
default, you may need to enable the \"js\" feature. \
|
||||
For more information see: \
|
||||
https://docs.rs/getrandom/#webassembly-support");
|
||||
@@ -283,9 +301,42 @@ cfg_if! {
|
||||
/// In general, `getrandom` will be fast enough for interactive usage, though
|
||||
/// significantly slower than a user-space CSPRNG; for the latter consider
|
||||
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
|
||||
#[inline]
|
||||
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
|
||||
if dest.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
imp::getrandom_inner(dest)
|
||||
// SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape, and
|
||||
// `getrandom_uninit` guarantees it will never de-initialize any part of
|
||||
// `dest`.
|
||||
getrandom_uninit(unsafe { slice_as_uninit_mut(dest) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Version of the `getrandom` function which fills `dest` with random bytes
|
||||
/// returns a mutable reference to those bytes.
|
||||
///
|
||||
/// On successful completion this function is guaranteed to return a slice
|
||||
/// which points to the same memory as `dest` and has the same length.
|
||||
/// In other words, it's safe to assume that `dest` is initialized after
|
||||
/// this function has returned `Ok`.
|
||||
///
|
||||
/// No part of `dest` will ever be de-initialized at any point, regardless
|
||||
/// of what is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// # // We ignore this test since `uninit_array` is unstable.
|
||||
/// #![feature(maybe_uninit_uninit_array)]
|
||||
/// # fn main() -> Result<(), getrandom::Error> {
|
||||
/// let mut buf = core::mem::MaybeUninit::uninit_array::<1024>();
|
||||
/// let buf: &mut [u8] = getrandom::getrandom_uninit(&mut buf)?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn getrandom_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
|
||||
if !dest.is_empty() {
|
||||
imp::getrandom_inner(dest)?;
|
||||
}
|
||||
// SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
|
||||
// since it returned `Ok`.
|
||||
Ok(unsafe { slice_assume_init_mut(dest) })
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ use crate::{
|
||||
util_libc::{last_os_error, sys_fill_exact},
|
||||
{use_file, Error},
|
||||
};
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// getrandom(2) was introduced in Linux 3.17
|
||||
static HAS_GETRANDOM: LazyBool = LazyBool::new();
|
||||
if HAS_GETRANDOM.unsync_init(is_getrandom_available) {
|
||||
|
||||
6
third_party/rust/getrandom/src/macos.rs
vendored
6
third_party/rust/getrandom/src/macos.rs
vendored
@@ -12,17 +12,17 @@ use crate::{
|
||||
util_libc::{last_os_error, Weak},
|
||||
Error,
|
||||
};
|
||||
use core::mem;
|
||||
use core::mem::{self, MaybeUninit};
|
||||
|
||||
type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// getentropy(2) was added in 10.12, Rust supports 10.7+
|
||||
static GETENTROPY: Weak = unsafe { Weak::new("getentropy\0") };
|
||||
if let Some(fptr) = GETENTROPY.ptr() {
|
||||
let func: GetEntropyFn = unsafe { mem::transmute(fptr) };
|
||||
for chunk in dest.chunks_mut(256) {
|
||||
let ret = unsafe { func(chunk.as_mut_ptr(), chunk.len()) };
|
||||
let ret = unsafe { func(chunk.as_mut_ptr() as *mut u8, chunk.len()) };
|
||||
if ret != 0 {
|
||||
return Err(last_os_error());
|
||||
}
|
||||
|
||||
3
third_party/rust/getrandom/src/openbsd.rs
vendored
3
third_party/rust/getrandom/src/openbsd.rs
vendored
@@ -8,8 +8,9 @@
|
||||
|
||||
//! Implementation for OpenBSD
|
||||
use crate::{util_libc::last_os_error, Error};
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// getentropy(2) was added in OpenBSD 5.6, so we can use it unconditionally.
|
||||
for chunk in dest.chunks_mut(256) {
|
||||
let ret = unsafe { libc::getentropy(chunk.as_mut_ptr() as *mut libc::c_void, chunk.len()) };
|
||||
|
||||
123
third_party/rust/getrandom/src/rdrand.rs
vendored
123
third_party/rust/getrandom/src/rdrand.rs
vendored
@@ -5,10 +5,11 @@
|
||||
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Implementation for SGX using RDRAND instruction
|
||||
use crate::Error;
|
||||
use core::mem;
|
||||
use crate::{
|
||||
util::{slice_as_uninit, LazyBool},
|
||||
Error,
|
||||
};
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")] {
|
||||
@@ -24,74 +25,106 @@ cfg_if! {
|
||||
// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
|
||||
// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
|
||||
const RETRY_LIMIT: usize = 10;
|
||||
const WORD_SIZE: usize = mem::size_of::<usize>();
|
||||
|
||||
#[target_feature(enable = "rdrand")]
|
||||
unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
|
||||
unsafe fn rdrand() -> Option<usize> {
|
||||
for _ in 0..RETRY_LIMIT {
|
||||
let mut el = mem::zeroed();
|
||||
if rdrand_step(&mut el) == 1 {
|
||||
// AMD CPUs from families 14h to 16h (pre Ryzen) sometimes fail to
|
||||
// set CF on bogus random data, so we check these values explicitly.
|
||||
// See https://github.com/systemd/systemd/issues/11810#issuecomment-489727505
|
||||
// We perform this check regardless of target to guard against
|
||||
// any implementation that incorrectly fails to set CF.
|
||||
if el != 0 && el != !0 {
|
||||
return Ok(el.to_ne_bytes());
|
||||
}
|
||||
// Keep looping in case this was a false positive.
|
||||
let mut val = 0;
|
||||
if rdrand_step(&mut val) == 1 {
|
||||
return Some(val as usize);
|
||||
}
|
||||
}
|
||||
Err(Error::FAILED_RDRAND)
|
||||
None
|
||||
}
|
||||
|
||||
// "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653.
|
||||
// "rdrand" target feature requires "+rdrand" flag, see https://github.com/rust-lang/rust/issues/49653.
|
||||
#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))]
|
||||
compile_error!(
|
||||
"SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrnd."
|
||||
"SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrand."
|
||||
);
|
||||
|
||||
#[cfg(target_feature = "rdrand")]
|
||||
fn is_rdrand_supported() -> bool {
|
||||
true
|
||||
// Run a small self-test to make sure we aren't repeating values
|
||||
// Adapted from Linux's test in arch/x86/kernel/cpu/rdrand.c
|
||||
// Fails with probability < 2^(-90) on 32-bit systems
|
||||
#[target_feature(enable = "rdrand")]
|
||||
unsafe fn self_test() -> bool {
|
||||
// On AMD, RDRAND returns 0xFF...FF on failure, count it as a collision.
|
||||
let mut prev = !0; // TODO(MSRV 1.43): Move to usize::MAX
|
||||
let mut fails = 0;
|
||||
for _ in 0..8 {
|
||||
match rdrand() {
|
||||
Some(val) if val == prev => fails += 1,
|
||||
Some(val) => prev = val,
|
||||
None => return false,
|
||||
};
|
||||
}
|
||||
fails <= 2
|
||||
}
|
||||
|
||||
// TODO use is_x86_feature_detected!("rdrand") when that works in core. See:
|
||||
// https://github.com/rust-lang-nursery/stdsimd/issues/464
|
||||
#[cfg(not(target_feature = "rdrand"))]
|
||||
fn is_rdrand_supported() -> bool {
|
||||
use crate::util::LazyBool;
|
||||
fn is_rdrand_good() -> bool {
|
||||
#[cfg(not(target_feature = "rdrand"))]
|
||||
{
|
||||
// SAFETY: All Rust x86 targets are new enough to have CPUID, and we
|
||||
// check that leaf 1 is supported before using it.
|
||||
let cpuid0 = unsafe { arch::__cpuid(0) };
|
||||
if cpuid0.eax < 1 {
|
||||
return false;
|
||||
}
|
||||
let cpuid1 = unsafe { arch::__cpuid(1) };
|
||||
|
||||
// SAFETY: All Rust x86 targets are new enough to have CPUID, and if CPUID
|
||||
// is supported, CPUID leaf 1 is always supported.
|
||||
const FLAG: u32 = 1 << 30;
|
||||
static HAS_RDRAND: LazyBool = LazyBool::new();
|
||||
HAS_RDRAND.unsync_init(|| unsafe { (arch::__cpuid(1).ecx & FLAG) != 0 })
|
||||
}
|
||||
let vendor_id = [
|
||||
cpuid0.ebx.to_le_bytes(),
|
||||
cpuid0.edx.to_le_bytes(),
|
||||
cpuid0.ecx.to_le_bytes(),
|
||||
];
|
||||
if vendor_id == [*b"Auth", *b"enti", *b"cAMD"] {
|
||||
let mut family = (cpuid1.eax >> 8) & 0xF;
|
||||
if family == 0xF {
|
||||
family += (cpuid1.eax >> 20) & 0xFF;
|
||||
}
|
||||
// AMD CPUs families before 17h (Zen) sometimes fail to set CF when
|
||||
// RDRAND fails after suspend. Don't use RDRAND on those families.
|
||||
// See https://bugzilla.redhat.com/show_bug.cgi?id=1150286
|
||||
if family < 0x17 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
if !is_rdrand_supported() {
|
||||
return Err(Error::NO_RDRAND);
|
||||
const RDRAND_FLAG: u32 = 1 << 30;
|
||||
if cpuid1.ecx & RDRAND_FLAG == 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: After this point, rdrand is supported, so calling the rdrand
|
||||
// functions is not undefined behavior.
|
||||
unsafe { rdrand_exact(dest) }
|
||||
// SAFETY: We have already checked that rdrand is available.
|
||||
unsafe { self_test() }
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
static RDRAND_GOOD: LazyBool = LazyBool::new();
|
||||
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
|
||||
return Err(Error::NO_RDRAND);
|
||||
}
|
||||
// SAFETY: After this point, we know rdrand is supported.
|
||||
unsafe { rdrand_exact(dest) }.ok_or(Error::FAILED_RDRAND)
|
||||
}
|
||||
|
||||
// TODO: make this function safe when we have feature(target_feature_11)
|
||||
#[target_feature(enable = "rdrand")]
|
||||
unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> {
|
||||
unsafe fn rdrand_exact(dest: &mut [MaybeUninit<u8>]) -> Option<()> {
|
||||
// We use chunks_exact_mut instead of chunks_mut as it allows almost all
|
||||
// calls to memcpy to be elided by the compiler.
|
||||
let mut chunks = dest.chunks_exact_mut(WORD_SIZE);
|
||||
let mut chunks = dest.chunks_exact_mut(size_of::<usize>());
|
||||
for chunk in chunks.by_ref() {
|
||||
chunk.copy_from_slice(&rdrand()?);
|
||||
let src = rdrand()?.to_ne_bytes();
|
||||
chunk.copy_from_slice(slice_as_uninit(&src));
|
||||
}
|
||||
|
||||
let tail = chunks.into_remainder();
|
||||
let n = tail.len();
|
||||
if n > 0 {
|
||||
tail.copy_from_slice(&rdrand()?[..n]);
|
||||
let src = rdrand()?.to_ne_bytes();
|
||||
tail.copy_from_slice(slice_as_uninit(&src[..n]));
|
||||
}
|
||||
Ok(())
|
||||
Some(())
|
||||
}
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
|
||||
//! Implementation for the Solaris family
|
||||
//!
|
||||
//! Read from `/dev/random`, with chunks of limited size (256 bytes).
|
||||
//! `/dev/random` uses the Hash_DRBG with SHA512 algorithm from NIST SP 800-90A.
|
||||
//! `/dev/urandom` uses the FIPS 186-2 algorithm, which is considered less
|
||||
//! secure. We choose to read from `/dev/random`.
|
||||
//! secure. We choose to read from `/dev/random` (and use GRND_RANDOM).
|
||||
//!
|
||||
//! Since Solaris 11.3 and mid-2015 illumos, the `getrandom` syscall is available.
|
||||
//! Solaris 11.3 and late-2018 illumos added the getrandom(2) libc function.
|
||||
//! To make sure we can compile on both Solaris and its derivatives, as well as
|
||||
//! function, we check for the existence of getrandom(2) in libc by calling
|
||||
//! libc::dlsym.
|
||||
@@ -22,23 +21,25 @@ use crate::{
|
||||
util_libc::{sys_fill_exact, Weak},
|
||||
Error,
|
||||
};
|
||||
use core::mem;
|
||||
use core::mem::{self, MaybeUninit};
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
|
||||
#[cfg(target_os = "solaris")]
|
||||
type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::c_int;
|
||||
static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") };
|
||||
type GetRandomFn =
|
||||
unsafe extern "C" fn(*mut libc::c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
// getrandom(2) was introduced in Solaris 11.3 for Illumos in 2015.
|
||||
static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") };
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
if let Some(fptr) = GETRANDOM.ptr() {
|
||||
let func: GetRandomFn = unsafe { mem::transmute(fptr) };
|
||||
// 256 bytes is the lowest common denominator across all the Solaris
|
||||
// derived platforms for atomically obtaining random data.
|
||||
for chunk in dest.chunks_mut(256) {
|
||||
sys_fill_exact(chunk, |buf| unsafe {
|
||||
func(buf.as_mut_ptr(), buf.len(), 0) as libc::ssize_t
|
||||
// A cast is needed for the flags as libc uses the wrong type.
|
||||
func(
|
||||
buf.as_mut_ptr() as *mut libc::c_void,
|
||||
buf.len(),
|
||||
libc::GRND_RANDOM as libc::c_uint,
|
||||
)
|
||||
})?
|
||||
}
|
||||
Ok(())
|
||||
|
||||
6
third_party/rust/getrandom/src/solid.rs
vendored
6
third_party/rust/getrandom/src/solid.rs
vendored
@@ -8,14 +8,14 @@
|
||||
|
||||
//! Implementation for SOLID
|
||||
use crate::Error;
|
||||
use core::num::NonZeroU32;
|
||||
use core::{mem::MaybeUninit, num::NonZeroU32};
|
||||
|
||||
extern "C" {
|
||||
pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> i32;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
let ret = unsafe { SOLID_RNG_SampleRandomBytes(dest.as_mut_ptr(), dest.len()) };
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
let ret = unsafe { SOLID_RNG_SampleRandomBytes(dest.as_mut_ptr() as *mut u8, dest.len()) };
|
||||
if ret >= 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
|
||||
33
third_party/rust/getrandom/src/use_file.rs
vendored
33
third_party/rust/getrandom/src/use_file.rs
vendored
@@ -14,34 +14,33 @@ use crate::{
|
||||
};
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
mem::MaybeUninit,
|
||||
sync::atomic::{AtomicUsize, Ordering::Relaxed},
|
||||
};
|
||||
|
||||
// We prefer using /dev/urandom and only use /dev/random if the OS
|
||||
// documentation indicates that /dev/urandom is insecure.
|
||||
// On Solaris/Illumos, see src/solaris_illumos.rs
|
||||
// On Dragonfly, Haiku, macOS, and QNX Neutrino the devices are identical.
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||
const FILE_PATH: &str = "/dev/random\0";
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "redox",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "macos",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos"
|
||||
target_os = "nto",
|
||||
))]
|
||||
const FILE_PATH: &str = "/dev/random\0";
|
||||
#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
|
||||
const FILE_PATH: &str = "/dev/urandom\0";
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
let fd = get_rng_fd()?;
|
||||
let read = |buf: &mut [u8]| unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };
|
||||
|
||||
if cfg!(target_os = "emscripten") {
|
||||
// `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes.
|
||||
for chunk in dest.chunks_mut(65536) {
|
||||
sys_fill_exact(chunk, read)?;
|
||||
}
|
||||
} else {
|
||||
sys_fill_exact(dest, read)?;
|
||||
}
|
||||
Ok(())
|
||||
sys_fill_exact(dest, |buf| unsafe {
|
||||
libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len())
|
||||
})
|
||||
}
|
||||
|
||||
// Returns the file descriptor for the device file used to retrieve random
|
||||
|
||||
39
third_party/rust/getrandom/src/util.rs
vendored
39
third_party/rust/getrandom/src/util.rs
vendored
@@ -6,7 +6,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
#![allow(dead_code)]
|
||||
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
||||
use core::{
|
||||
mem::MaybeUninit,
|
||||
ptr,
|
||||
sync::atomic::{AtomicUsize, Ordering::Relaxed},
|
||||
};
|
||||
|
||||
// This structure represents a lazily initialized static usize value. Useful
|
||||
// when it is preferable to just rerun initialization instead of locking.
|
||||
@@ -62,3 +66,36 @@ impl LazyBool {
|
||||
self.0.unsync_init(|| init() as usize) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Polyfill for `maybe_uninit_slice` feature's
|
||||
/// `MaybeUninit::slice_assume_init_mut`. Every element of `slice` must have
|
||||
/// been initialized.
|
||||
#[inline(always)]
|
||||
pub unsafe fn slice_assume_init_mut<T>(slice: &mut [MaybeUninit<T>]) -> &mut [T] {
|
||||
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
|
||||
&mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn uninit_slice_fill_zero(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
|
||||
unsafe { ptr::write_bytes(slice.as_mut_ptr(), 0, slice.len()) };
|
||||
unsafe { slice_assume_init_mut(slice) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn slice_as_uninit<T>(slice: &[T]) -> &[MaybeUninit<T>] {
|
||||
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
|
||||
// There is no risk of writing a `MaybeUninit<T>` into the result since
|
||||
// the result isn't mutable.
|
||||
unsafe { &*(slice as *const [T] as *const [MaybeUninit<T>]) }
|
||||
}
|
||||
|
||||
/// View an mutable initialized array as potentially-uninitialized.
|
||||
///
|
||||
/// This is unsafe because it allows assigning uninitialized values into
|
||||
/// `slice`, which would be undefined behavior.
|
||||
#[inline(always)]
|
||||
pub unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
|
||||
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
|
||||
&mut *(slice as *mut [T] as *mut [MaybeUninit<T>])
|
||||
}
|
||||
|
||||
23
third_party/rust/getrandom/src/util_libc.rs
vendored
23
third_party/rust/getrandom/src/util_libc.rs
vendored
@@ -8,6 +8,8 @@
|
||||
#![allow(dead_code)]
|
||||
use crate::Error;
|
||||
use core::{
|
||||
cmp::min,
|
||||
mem::MaybeUninit,
|
||||
num::NonZeroU32,
|
||||
ptr::NonNull,
|
||||
sync::atomic::{fence, AtomicPtr, Ordering},
|
||||
@@ -25,12 +27,16 @@ cfg_if! {
|
||||
use libc::__error as errno_location;
|
||||
} else if #[cfg(target_os = "haiku")] {
|
||||
use libc::_errnop as errno_location;
|
||||
} else if #[cfg(target_os = "nto")] {
|
||||
use libc::__get_errno_ptr as errno_location;
|
||||
} else if #[cfg(all(target_os = "horizon", target_arch = "arm"))] {
|
||||
extern "C" {
|
||||
// Not provided by libc: https://github.com/rust-lang/libc/issues/1995
|
||||
fn __errno() -> *mut libc::c_int;
|
||||
}
|
||||
use __errno as errno_location;
|
||||
} else if #[cfg(target_os = "aix")] {
|
||||
use libc::_Errno as errno_location;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +65,8 @@ pub fn last_os_error() -> Error {
|
||||
// - should return -1 and set errno on failure
|
||||
// - should return the number of bytes written on success
|
||||
pub fn sys_fill_exact(
|
||||
mut buf: &mut [u8],
|
||||
sys_fill: impl Fn(&mut [u8]) -> libc::ssize_t,
|
||||
mut buf: &mut [MaybeUninit<u8>],
|
||||
sys_fill: impl Fn(&mut [MaybeUninit<u8>]) -> libc::ssize_t,
|
||||
) -> Result<(), Error> {
|
||||
while !buf.is_empty() {
|
||||
let res = sys_fill(buf);
|
||||
@@ -73,7 +79,8 @@ pub fn sys_fill_exact(
|
||||
} else {
|
||||
// We don't check for EOF (ret = 0) as the data we are reading
|
||||
// should be an infinite stream of random bytes.
|
||||
buf = &mut buf[(res as usize)..];
|
||||
let len = min(res as usize, buf.len());
|
||||
buf = &mut buf[len..];
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -135,19 +142,11 @@ impl Weak {
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "linux", target_os = "emscripten"))] {
|
||||
use libc::open64 as open;
|
||||
} else {
|
||||
use libc::open;
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: path must be null terminated, FD must be manually closed.
|
||||
pub unsafe fn open_readonly(path: &str) -> Result<libc::c_int, Error> {
|
||||
debug_assert_eq!(path.as_bytes().last(), Some(&0));
|
||||
loop {
|
||||
let fd = open(path.as_ptr() as *const _, libc::O_RDONLY | libc::O_CLOEXEC);
|
||||
let fd = libc::open(path.as_ptr() as *const _, libc::O_RDONLY | libc::O_CLOEXEC);
|
||||
if fd >= 0 {
|
||||
return Ok(fd);
|
||||
}
|
||||
|
||||
9
third_party/rust/getrandom/src/vxworks.rs
vendored
9
third_party/rust/getrandom/src/vxworks.rs
vendored
@@ -8,9 +8,12 @@
|
||||
|
||||
//! Implementation for VxWorks
|
||||
use crate::{util_libc::last_os_error, Error};
|
||||
use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
|
||||
use core::{
|
||||
mem::MaybeUninit,
|
||||
sync::atomic::{AtomicBool, Ordering::Relaxed},
|
||||
};
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
static RNG_INIT: AtomicBool = AtomicBool::new(false);
|
||||
while !RNG_INIT.load(Relaxed) {
|
||||
let ret = unsafe { libc::randSecure() };
|
||||
@@ -25,7 +28,7 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
|
||||
// Prevent overflow of i32
|
||||
for chunk in dest.chunks_mut(i32::max_value() as usize) {
|
||||
let ret = unsafe { libc::randABytes(chunk.as_mut_ptr(), chunk.len() as i32) };
|
||||
let ret = unsafe { libc::randABytes(chunk.as_mut_ptr() as *mut u8, chunk.len() as i32) };
|
||||
if ret != 0 {
|
||||
return Err(last_os_error());
|
||||
}
|
||||
|
||||
20
third_party/rust/getrandom/src/wasi.rs
vendored
20
third_party/rust/getrandom/src/wasi.rs
vendored
@@ -8,12 +8,18 @@
|
||||
|
||||
//! Implementation for WASI
|
||||
use crate::Error;
|
||||
use core::num::NonZeroU32;
|
||||
use wasi::wasi_snapshot_preview1::random_get;
|
||||
use core::{
|
||||
mem::MaybeUninit,
|
||||
num::{NonZeroU16, NonZeroU32},
|
||||
};
|
||||
use wasi::random_get;
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
match unsafe { random_get(dest.as_mut_ptr() as i32, dest.len() as i32) } {
|
||||
0 => Ok(()),
|
||||
err => Err(unsafe { NonZeroU32::new_unchecked(err as u32) }.into()),
|
||||
}
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
unsafe { random_get(dest.as_mut_ptr() as *mut u8, dest.len()) }.map_err(|e| {
|
||||
// The WASI errno will always be non-zero, but we check just in case.
|
||||
match NonZeroU16::new(e.raw()) {
|
||||
Some(r) => Error::from(NonZeroU32::from(r)),
|
||||
None => Error::ERRNO_NOT_POSITIVE,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
23
third_party/rust/getrandom/src/windows.rs
vendored
23
third_party/rust/getrandom/src/windows.rs
vendored
@@ -7,7 +7,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use crate::Error;
|
||||
use core::{ffi::c_void, num::NonZeroU32, ptr};
|
||||
use core::{ffi::c_void, mem::MaybeUninit, num::NonZeroU32, ptr};
|
||||
|
||||
const BCRYPT_USE_SYSTEM_PREFERRED_RNG: u32 = 0x00000002;
|
||||
|
||||
@@ -21,20 +21,37 @@ extern "system" {
|
||||
) -> u32;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
|
||||
// Forbidden when targetting UWP
|
||||
#[cfg(not(target_vendor = "uwp"))]
|
||||
#[link(name = "advapi32")]
|
||||
extern "system" {
|
||||
#[link_name = "SystemFunction036"]
|
||||
fn RtlGenRandom(RandomBuffer: *mut c_void, RandomBufferLength: u32) -> u8;
|
||||
}
|
||||
|
||||
pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
|
||||
// Prevent overflow of u32
|
||||
for chunk in dest.chunks_mut(u32::max_value() as usize) {
|
||||
// BCryptGenRandom was introduced in Windows Vista
|
||||
let ret = unsafe {
|
||||
BCryptGenRandom(
|
||||
ptr::null_mut(),
|
||||
chunk.as_mut_ptr(),
|
||||
chunk.as_mut_ptr() as *mut u8,
|
||||
chunk.len() as u32,
|
||||
BCRYPT_USE_SYSTEM_PREFERRED_RNG,
|
||||
)
|
||||
};
|
||||
// NTSTATUS codes use the two highest bits for severity status.
|
||||
if ret >> 30 == 0b11 {
|
||||
// Failed. Try RtlGenRandom as a fallback.
|
||||
#[cfg(not(target_vendor = "uwp"))]
|
||||
{
|
||||
let ret =
|
||||
unsafe { RtlGenRandom(chunk.as_mut_ptr() as *mut c_void, chunk.len() as u32) };
|
||||
if ret != 0 {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// We zeroize the highest bit, so the error code will reside
|
||||
// inside the range designated for OS codes.
|
||||
let code = ret ^ (1 << 31);
|
||||
|
||||
46
third_party/rust/getrandom/tests/common/mod.rs
vendored
46
third_party/rust/getrandom/tests/common/mod.rs
vendored
@@ -12,7 +12,19 @@ fn test_zero() {
|
||||
getrandom_impl(&mut [0u8; 0]).unwrap();
|
||||
}
|
||||
|
||||
// Return the number of bits in which s1 and s2 differ
|
||||
#[cfg(not(feature = "custom"))]
|
||||
fn num_diff_bits(s1: &[u8], s2: &[u8]) -> usize {
|
||||
assert_eq!(s1.len(), s2.len());
|
||||
s1.iter()
|
||||
.zip(s2.iter())
|
||||
.map(|(a, b)| (a ^ b).count_ones() as usize)
|
||||
.sum()
|
||||
}
|
||||
|
||||
// Tests the quality of calling getrandom on two large buffers
|
||||
#[test]
|
||||
#[cfg(not(feature = "custom"))]
|
||||
fn test_diff() {
|
||||
let mut v1 = [0u8; 1000];
|
||||
getrandom_impl(&mut v1).unwrap();
|
||||
@@ -20,13 +32,35 @@ fn test_diff() {
|
||||
let mut v2 = [0u8; 1000];
|
||||
getrandom_impl(&mut v2).unwrap();
|
||||
|
||||
let mut n_diff_bits = 0;
|
||||
for i in 0..v1.len() {
|
||||
n_diff_bits += (v1[i] ^ v2[i]).count_ones();
|
||||
}
|
||||
// Between 3.5 and 4.5 bits per byte should differ. Probability of failure:
|
||||
// ~ 2^(-94) = 2 * CDF[BinomialDistribution[8000, 0.5], 3500]
|
||||
let d = num_diff_bits(&v1, &v2);
|
||||
assert!(d > 3500);
|
||||
assert!(d < 4500);
|
||||
}
|
||||
|
||||
// Check at least 1 bit per byte differs. p(failure) < 1e-1000 with random input.
|
||||
assert!(n_diff_bits >= v1.len() as u32);
|
||||
// Tests the quality of calling getrandom repeatedly on small buffers
|
||||
#[test]
|
||||
#[cfg(not(feature = "custom"))]
|
||||
fn test_small() {
|
||||
// For each buffer size, get at least 256 bytes and check that between
|
||||
// 3 and 5 bits per byte differ. Probability of failure:
|
||||
// ~ 2^(-91) = 64 * 2 * CDF[BinomialDistribution[8*256, 0.5], 3*256]
|
||||
for size in 1..=64 {
|
||||
let mut num_bytes = 0;
|
||||
let mut diff_bits = 0;
|
||||
while num_bytes < 256 {
|
||||
let mut s1 = vec![0u8; size];
|
||||
getrandom_impl(&mut s1).unwrap();
|
||||
let mut s2 = vec![0u8; size];
|
||||
getrandom_impl(&mut s2).unwrap();
|
||||
|
||||
num_bytes += size;
|
||||
diff_bits += num_diff_bits(&s1, &s2);
|
||||
}
|
||||
assert!(diff_bits > 3 * num_bytes);
|
||||
assert!(diff_bits < 5 * num_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
26
third_party/rust/getrandom/tests/custom.rs
vendored
26
third_party/rust/getrandom/tests/custom.rs
vendored
@@ -7,13 +7,8 @@
|
||||
))]
|
||||
|
||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||
#[cfg(feature = "test-in-browser")]
|
||||
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
use core::{
|
||||
num::NonZeroU32,
|
||||
sync::atomic::{AtomicU8, Ordering},
|
||||
};
|
||||
use core::num::NonZeroU32;
|
||||
use getrandom::{getrandom, register_custom_getrandom, Error};
|
||||
|
||||
fn len7_err() -> Error {
|
||||
@@ -21,27 +16,36 @@ fn len7_err() -> Error {
|
||||
}
|
||||
|
||||
fn super_insecure_rng(buf: &mut [u8]) -> Result<(), Error> {
|
||||
// `getrandom` guarantees it will not call any implementation if the output
|
||||
// buffer is empty.
|
||||
assert!(!buf.is_empty());
|
||||
// Length 7 buffers return a custom error
|
||||
if buf.len() == 7 {
|
||||
return Err(len7_err());
|
||||
}
|
||||
// Otherwise, increment an atomic counter
|
||||
static COUNTER: AtomicU8 = AtomicU8::new(0);
|
||||
// Otherwise, fill bytes based on input length
|
||||
let mut start = buf.len() as u8;
|
||||
for b in buf {
|
||||
*b = COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
*b = start;
|
||||
start = start.wrapping_mul(3);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
register_custom_getrandom!(super_insecure_rng);
|
||||
|
||||
use getrandom::getrandom as getrandom_impl;
|
||||
mod common;
|
||||
|
||||
#[test]
|
||||
fn custom_rng_output() {
|
||||
let mut buf = [0u8; 4];
|
||||
assert_eq!(getrandom(&mut buf), Ok(()));
|
||||
assert_eq!(buf, [0, 1, 2, 3]);
|
||||
assert_eq!(buf, [4, 12, 36, 108]);
|
||||
|
||||
let mut buf = [0u8; 3];
|
||||
assert_eq!(getrandom(&mut buf), Ok(()));
|
||||
assert_eq!(buf, [4, 5, 6, 7]);
|
||||
assert_eq!(buf, [3, 9, 27]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
7
third_party/rust/getrandom/tests/rdrand.rs
vendored
7
third_party/rust/getrandom/tests/rdrand.rs
vendored
@@ -11,5 +11,10 @@ mod rdrand;
|
||||
#[path = "../src/util.rs"]
|
||||
mod util;
|
||||
|
||||
use rdrand::getrandom_inner as getrandom_impl;
|
||||
// The rdrand implementation has the signature of getrandom_uninit(), but our
|
||||
// tests expect getrandom_impl() to have the signature of getrandom().
|
||||
fn getrandom_impl(dest: &mut [u8]) -> Result<(), Error> {
|
||||
rdrand::getrandom_inner(unsafe { util::slice_as_uninit_mut(dest) })?;
|
||||
Ok(())
|
||||
}
|
||||
mod common;
|
||||
|
||||
Reference in New Issue
Block a user