From 9db790ec08fe51bfe83eddf870e40ad293e9b141 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Sat, 26 Oct 2019 02:32:16 -0700 Subject: [PATCH 1/4] custom: Add support for Custom RNGs --- .travis.yml | 5 +++-- Cargo.toml | 4 +++- src/custom.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 7 ++++++- 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 src/custom.rs diff --git a/.travis.yml b/.travis.yml index 0ac4a213..716757be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -91,13 +91,14 @@ matrix: - cargo test --benches # Check that setting various features does not break the build - cargo build --features=std + - cargo build --features=custom # remove cached documentation, otherwise files from previous PRs can get included - rm -rf target/doc - - cargo doc --no-deps --features=std + - cargo doc --no-deps --features=std,custom - cargo deadlinks --dir target/doc # also test minimum dependency versions are usable - cargo generate-lockfile -Z minimal-versions - - cargo test --features=std + - cargo test --features=std,custom - <<: *nightly_and_docs name: "OSX, nightly, docs" diff --git a/Cargo.toml b/Cargo.toml index 88dd1f32..1a762121 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,10 +36,12 @@ wasm-bindgen-test = "0.2" [features] std = [] +# Feature to enable custom RNG implementations +custom = [] # Unstable feature to support being a libstd dependency rustc-dep-of-std = ["compiler_builtins", "core"] # Unstable feature for testing test-in-browser = ["wasm-bindgen"] [package.metadata.docs.rs] -features = ["std"] +features = ["std", "custom"] diff --git a/src/custom.rs b/src/custom.rs new file mode 100644 index 00000000..11abf0c4 --- /dev/null +++ b/src/custom.rs @@ -0,0 +1,45 @@ +// Copyright 2018 Developers of the Rand project. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! An implementation which calls out to an externally defined function. +use crate::Error; +use core::num::NonZeroU32; + +/// Register a function to be invoked by `getrandom` on custom targets. +/// +/// This function will only be invoked on targets not supported by `getrandom`. +/// This prevents crate dependencies from either inadvertently or maliciously +/// overriding the secure RNG implementations in `getrandom`. +/// +/// *This API requires the following crate features to be activated: `custom`* +#[macro_export] +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 slice = unsafe { ::std::slice::from_raw_parts_mut(dest, len) }; + match $path(slice) { + Ok(()) => 0, + Err(e) => e.code().get(), + } + } + }; +} + +#[allow(dead_code)] +pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { + extern "C" { + fn __getrandom_custom(dest: *mut u8, len: usize) -> u32; + } + let ret = unsafe { __getrandom_custom(dest.as_mut_ptr(), dest.len()) }; + match NonZeroU32::new(ret) { + None => Ok(()), + Some(code) => Err(Error::from(code)), + } +} diff --git a/src/lib.rs b/src/lib.rs index 1ce321ec..7612ef0b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,7 +134,10 @@ extern crate cfg_if; mod error; mod util; - +// To prevent a breaking change when targets are added, we always export the +// register_custom_getrandom macro, so old Custom RNG crates continue to build. +#[cfg(feature = "custom")] +mod custom; #[cfg(feature = "std")] mod error_impls; @@ -201,6 +204,8 @@ cfg_if! { "); } } + } else if #[cfg(feature = "custom")] { + use custom as imp; } else { compile_error!("\ target is not supported, for more information see: \ From 4057b9152a99d59ee225da77f6cbd44d6cb1165f Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Sat, 26 Oct 2019 02:37:53 -0700 Subject: [PATCH 2/4] Remove built-in support for wasm32-unknown-unknown --- Cargo.toml | 9 --------- src/lib.rs | 14 -------------- 2 files changed, 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1a762121..2f5df229 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,21 +27,12 @@ libc = { version = "0.2.64", default-features = false } [target.'cfg(target_os = "wasi")'.dependencies] wasi = "0.9" -[target.wasm32-unknown-unknown.dependencies] -wasm-bindgen = { version = "0.2.29", optional = true } -stdweb = { version = "0.4.18", optional = true } - -[target.wasm32-unknown-unknown.dev-dependencies] -wasm-bindgen-test = "0.2" - [features] std = [] # Feature to enable custom RNG implementations custom = [] # Unstable feature to support being a libstd dependency rustc-dep-of-std = ["compiler_builtins", "core"] -# Unstable feature for testing -test-in-browser = ["wasm-bindgen"] [package.metadata.docs.rs] features = ["std", "custom"] diff --git a/src/lib.rs b/src/lib.rs index 7612ef0b..cb62223b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -126,7 +126,6 @@ html_root_url = "https://rust-random.github.io/rand/" )] #![no_std] -#![cfg_attr(feature = "stdweb", recursion_limit = "128")] #![warn(rust_2018_idioms, unused_lifetimes, missing_docs)] #[macro_use] @@ -191,19 +190,6 @@ cfg_if! { target_env = "sgx", )))] { #[path = "rdrand.rs"] mod imp; - } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] { - cfg_if! { - if #[cfg(feature = "wasm-bindgen")] { - #[path = "wasm32_bindgen.rs"] mod imp; - } else if #[cfg(feature = "stdweb")] { - #[path = "wasm32_stdweb.rs"] mod imp; - } else { - compile_error!("\ - Enable crate features to use the wasm32-unknown-unknown target, see: \ - https://docs.rs/getrandom/#support-for-webassembly-and-asmjs\ - "); - } - } } else if #[cfg(feature = "custom")] { use custom as imp; } else { From 96c731bb1243bd0ff77c64f0f87f064b58b4f13e Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Sat, 26 Oct 2019 02:44:03 -0700 Subject: [PATCH 3/4] custom: Add custom RNG for stdweb --- .travis.yml | 5 ++-- Cargo.toml | 5 ++++ custom/stdweb/Cargo.toml | 26 +++++++++++++++++++ .../stdweb/src/lib.rs | 11 +++++--- tests/common.rs | 4 +++ 5 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 custom/stdweb/Cargo.toml rename src/wasm32_stdweb.rs => custom/stdweb/src/lib.rs (90%) diff --git a/.travis.yml b/.travis.yml index 716757be..b211d420 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,8 +71,9 @@ matrix: # wasi tests - cargo test --target wasm32-wasi # stdweb tests (Node, Chrome) - - cargo web test --nodejs --target=wasm32-unknown-unknown --features=stdweb - - cargo web test --target=wasm32-unknown-unknown --features=stdweb + - cd custom/stdweb + - cargo web test --nodejs --target=wasm32-unknown-unknown + - cargo web test --target=wasm32-unknown-unknown # wasm-bindgen tests (Node, Firefox, Chrome) - cargo test --target wasm32-unknown-unknown --features=wasm-bindgen - GECKODRIVER=$HOME/geckodriver cargo test --target wasm32-unknown-unknown --features=test-in-browser diff --git a/Cargo.toml b/Cargo.toml index 2f5df229..50619b57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,11 @@ exclude = ["utils/*", ".*", "appveyor.yml"] travis-ci = { repository = "rust-random/getrandom" } appveyor = { repository = "rust-random/getrandom" } +[workspace] +members = [ + "custom/stdweb", +] + [dependencies] cfg-if = "0.1.2" diff --git a/custom/stdweb/Cargo.toml b/custom/stdweb/Cargo.toml new file mode 100644 index 00000000..2b94124d --- /dev/null +++ b/custom/stdweb/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "stdweb-getrandom" +version = "0.1.0" +edition = "2018" +authors = ["The Rand Project Developers"] +license = "MIT OR Apache-2.0" +description = "Custom shim for using getrandom with stdweb" +documentation = "https://docs.rs/stdweb-getrandom" +repository = "https://github.com/rust-random/getrandom" +categories = ["wasm"] + +[dependencies] +getrandom = { path = "../..", version = "0.2", features = ["custom"] } +stdweb = "0.4.18" + +# Test-only features allowing us to reuse most of the code in common.rs +[features] +default = ["test-stdweb"] +test-stdweb = [] + +[[test]] +name = "common" +path = "../../tests/common.rs" + +[package.metadata.docs.rs] +default-target = "wasm32-unknown-unknown" \ No newline at end of file diff --git a/src/wasm32_stdweb.rs b/custom/stdweb/src/lib.rs similarity index 90% rename from src/wasm32_stdweb.rs rename to custom/stdweb/src/lib.rs index 4e28d78e..adfb3398 100644 --- a/src/wasm32_stdweb.rs +++ b/custom/stdweb/src/lib.rs @@ -6,15 +6,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementation for WASM via stdweb -extern crate std; +#![recursion_limit = "128"] +#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] +compile_error!("This crate is only for the `wasm32-unknown-unknown` target"); use core::mem; use std::sync::Once; use stdweb::js; -use crate::Error; +use getrandom::{register_custom_getrandom, Error}; #[derive(Clone, Copy, Debug)] enum RngSource { @@ -22,7 +23,9 @@ enum RngSource { Node, } -pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { +register_custom_getrandom!(getrandom_inner); + +fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { assert_eq!(mem::size_of::(), 4); static ONCE: Once = Once::new(); static mut RNG_SOURCE: Result = Ok(RngSource::Node); diff --git a/tests/common.rs b/tests/common.rs index afefa031..d629e02c 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -1,3 +1,7 @@ +// Explicitly use the Custom RNG crates to link them in. +#[cfg(feature = "test-stdweb")] +use stdweb_getrandom as _; + #[cfg(feature = "wasm-bindgen")] use wasm_bindgen_test::*; From 651ad034650ed5c56c85912efb3ee21535bb07d9 Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Sat, 26 Oct 2019 02:45:56 -0700 Subject: [PATCH 4/4] custom: Add Custom RNG for wasm-bindgen --- .travis.yml | 5 +++- Cargo.toml | 1 + custom/wasm-bindgen/Cargo.toml | 30 +++++++++++++++++++ .../wasm-bindgen/src/lib.rs | 10 ++++--- tests/common.rs | 10 ++++--- 5 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 custom/wasm-bindgen/Cargo.toml rename src/wasm32_bindgen.rs => custom/wasm-bindgen/src/lib.rs (92%) diff --git a/.travis.yml b/.travis.yml index b211d420..70bed8b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,8 @@ matrix: - cargo web test --nodejs --target=wasm32-unknown-unknown - cargo web test --target=wasm32-unknown-unknown # wasm-bindgen tests (Node, Firefox, Chrome) - - cargo test --target wasm32-unknown-unknown --features=wasm-bindgen + - cd ../wasm-bindgen + - cargo test --target wasm32-unknown-unknown - GECKODRIVER=$HOME/geckodriver cargo test --target wasm32-unknown-unknown --features=test-in-browser - CHROMEDRIVER=$HOME/chromedriver cargo test --target wasm32-unknown-unknown --features=test-in-browser @@ -84,6 +85,7 @@ matrix: rust: nightly os: linux install: + - rustup target add wasm32-unknown-unknown - cargo --list | egrep "^\s*deadlinks$" -q || cargo install cargo-deadlinks - cargo deadlinks -V script: @@ -96,6 +98,7 @@ matrix: # remove cached documentation, otherwise files from previous PRs can get included - rm -rf target/doc - cargo doc --no-deps --features=std,custom + - cargo doc --no-deps --manifest-path=custom/wasm-bindgen/Cargo.toml --target=wasm32-unknown-unknown - cargo deadlinks --dir target/doc # also test minimum dependency versions are usable - cargo generate-lockfile -Z minimal-versions diff --git a/Cargo.toml b/Cargo.toml index 50619b57..b576b840 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ appveyor = { repository = "rust-random/getrandom" } [workspace] members = [ "custom/stdweb", + "custom/wasm-bindgen", ] [dependencies] diff --git a/custom/wasm-bindgen/Cargo.toml b/custom/wasm-bindgen/Cargo.toml new file mode 100644 index 00000000..93202fa6 --- /dev/null +++ b/custom/wasm-bindgen/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "wasm-bindgen-getrandom" +version = "0.1.0" +edition = "2018" +authors = ["The Rand Project Developers"] +license = "MIT OR Apache-2.0" +description = "Custom shim for using getrandom with wasm-bindgen" +documentation = "https://docs.rs/wasm-bindgen-getrandom" +repository = "https://github.com/rust-random/getrandom" +categories = ["wasm"] + +[dependencies] +getrandom = { path = "../..", version = "0.2", features = ["custom"] } +wasm-bindgen = "0.2.29" + +[dev-dependencies] +wasm-bindgen-test = "0.2" + +# Test-only features allowing us to reuse most of the code in common.rs +[features] +default = ["test-bindgen"] +test-bindgen = [] +test-in-browser = ["test-bindgen"] + +[[test]] +name = "common" +path = "../../tests/common.rs" + +[package.metadata.docs.rs] +default-target = "wasm32-unknown-unknown" \ No newline at end of file diff --git a/src/wasm32_bindgen.rs b/custom/wasm-bindgen/src/lib.rs similarity index 92% rename from src/wasm32_bindgen.rs rename to custom/wasm-bindgen/src/lib.rs index 42d3eda9..521ff198 100644 --- a/src/wasm32_bindgen.rs +++ b/custom/wasm-bindgen/src/lib.rs @@ -6,8 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementation for WASM via wasm-bindgen -extern crate std; +#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] +compile_error!("This crate is only for the `wasm32-unknown-unknown` target"); use core::cell::RefCell; use core::mem; @@ -15,7 +15,7 @@ use std::thread_local; use wasm_bindgen::prelude::*; -use crate::Error; +use getrandom::{register_custom_getrandom, Error}; #[derive(Clone, Debug)] enum RngSource { @@ -29,7 +29,9 @@ thread_local!( static RNG_SOURCE: RefCell> = RefCell::new(None); ); -pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { +register_custom_getrandom!(getrandom_inner); + +fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { assert_eq!(mem::size_of::(), 4); RNG_SOURCE.with(|f| { diff --git a/tests/common.rs b/tests/common.rs index d629e02c..a19af2d5 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -1,8 +1,10 @@ // Explicitly use the Custom RNG crates to link them in. #[cfg(feature = "test-stdweb")] use stdweb_getrandom as _; +#[cfg(feature = "test-bindgen")] +use wasm_bindgen_getrandom as _; -#[cfg(feature = "wasm-bindgen")] +#[cfg(feature = "test-bindgen")] use wasm_bindgen_test::*; use getrandom::getrandom; @@ -10,14 +12,14 @@ use getrandom::getrandom; #[cfg(feature = "test-in-browser")] wasm_bindgen_test_configure!(run_in_browser); -#[cfg_attr(feature = "wasm-bindgen", wasm_bindgen_test)] +#[cfg_attr(feature = "test-bindgen", wasm_bindgen_test)] #[test] fn test_zero() { // Test that APIs are happy with zero-length requests getrandom(&mut [0u8; 0]).unwrap(); } -#[cfg_attr(feature = "wasm-bindgen", wasm_bindgen_test)] +#[cfg_attr(feature = "test-bindgen", wasm_bindgen_test)] #[test] fn test_diff() { let mut v1 = [0u8; 1000]; @@ -35,7 +37,7 @@ fn test_diff() { assert!(n_diff_bits >= v1.len() as u32); } -#[cfg_attr(feature = "wasm-bindgen", wasm_bindgen_test)] +#[cfg_attr(feature = "test-bindgen", wasm_bindgen_test)] #[test] fn test_huge() { let mut huge = [0u8; 100_000];