Snap for 10453938 from 1df27553ccea135ec8c64649af6e018b0b277e98 to mainline-odp-release
Change-Id: I8533e18b89d8537f6318d0fe827af4fbaec0fab3
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 7f98fc0..4787b56 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "8792268dfe57e49bb4518190bf4fe66176759a44"
- }
-}
+ "sha1": "89a1336b934c68ddce548127c6f8afd910b35a18"
+ },
+ "path_in_vcs": "rand_core"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 6d2506f..841b4e1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,7 +43,7 @@
host_supported: true,
crate_name: "rand_core",
cargo_env_compat: true,
- cargo_pkg_version: "0.6.3",
+ cargo_pkg_version: "0.6.4",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -58,6 +58,8 @@
"//apex_available:platform",
"com.android.virt",
],
+ product_available: true,
+ vendor_available: true,
}
rust_test {
@@ -65,7 +67,7 @@
host_supported: true,
crate_name: "rand_core",
cargo_env_compat: true,
- cargo_pkg_version: "0.6.3",
+ cargo_pkg_version: "0.6.4",
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 82c8300..75fcbc6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@
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.6.4] - 2022-09-15
+- Fix unsoundness in `<BlockRng64 as RngCore>::next_u32` (#1160)
+- Reduce use of `unsafe` and improve gen_bytes performance (#1180)
+- Add `CryptoRngCore` trait (#1187, #1230)
+
## [0.6.3] - 2021-06-15
### Changed
- Improved bound for `serde` impls on `BlockRng` (#1130)
diff --git a/Cargo.toml b/Cargo.toml
index 06ba1e8..fd8c96d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,32 +3,47 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "rand_core"
-version = "0.6.3"
-authors = ["The Rand Project Developers", "The Rust Project Developers"]
-description = "Core random number generator traits and tools for implementation.\n"
+version = "0.6.4"
+authors = [
+ "The Rand Project Developers",
+ "The Rust Project Developers",
+]
+description = """
+Core random number generator traits and tools for implementation.
+"""
homepage = "https://rust-random.github.io/book"
documentation = "https://docs.rs/rand_core"
readme = "README.md"
-keywords = ["random", "rng"]
-categories = ["algorithms", "no-std"]
+keywords = [
+ "random",
+ "rng",
+]
+categories = [
+ "algorithms",
+ "no-std",
+]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-random/rand"
+
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "doc_cfg"]
+rustdoc-args = [
+ "--cfg",
+ "doc_cfg",
+]
[package.metadata.playground]
all-features = true
+
[dependencies.getrandom]
version = "0.2"
optional = true
@@ -41,4 +56,8 @@
[features]
alloc = []
serde1 = ["serde"]
-std = ["alloc", "getrandom", "getrandom/std"]
+std = [
+ "alloc",
+ "getrandom",
+ "getrandom/std",
+]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 6604bc5..bfaa029 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
@@ -14,15 +14,6 @@
categories = ["algorithms", "no-std"]
edition = "2018"
-[features]
-std = ["alloc", "getrandom", "getrandom/std"] # use std library; should be default but for above bug
-alloc = [] # enables Vec and Box support without std
-serde1 = ["serde"] # enables serde for BlockRng wrapper
-
-[dependencies]
-serde = { version = "1", features = ["derive"], optional = true }
-getrandom = { version = "0.2", optional = true }
-
[package.metadata.docs.rs]
# To build locally:
# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --all-features --no-deps --open
@@ -31,3 +22,12 @@
[package.metadata.playground]
all-features = true
+
+[features]
+std = ["alloc", "getrandom", "getrandom/std"] # use std library; should be default but for above bug
+alloc = [] # enables Vec and Box support without std
+serde1 = ["serde"] # enables serde for BlockRng wrapper
+
+[dependencies]
+serde = { version = "1", features = ["derive"], optional = true }
+getrandom = { version = "0.2", optional = true }
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
index 17d7468..455787c 100644
--- a/LICENSE-APACHE
+++ b/LICENSE-APACHE
@@ -185,17 +185,3 @@
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/METADATA b/METADATA
index 6c047cf..88a399e 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/rand_core
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
name: "rand_core"
description: "Core random number generator traits and tools for implementation."
third_party {
@@ -7,13 +11,13 @@
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/rand_core/rand_core-0.6.3.crate"
+ value: "https://static.crates.io/crates/rand_core/rand_core-0.6.4.crate"
}
- version: "0.6.3"
+ version: "0.6.4"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 6
- day: 21
+ year: 2022
+ month: 12
+ day: 13
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cd4547e..05d9335 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -23,6 +23,12 @@
"path": "external/rust/crates/crossbeam-utils"
},
{
+ "path": "external/rust/crates/flate2"
+ },
+ {
+ "path": "external/rust/crates/hashbrown"
+ },
+ {
"path": "external/rust/crates/mio"
},
{
@@ -42,64 +48,52 @@
},
{
"path": "external/rust/crates/tokio"
+ },
+ {
+ "path": "external/rust/crates/zerocopy"
+ },
+ {
+ "path": "external/uwb/src"
+ },
+ {
+ "path": "packages/modules/Virtualization/apkdmverity"
+ },
+ {
+ "path": "packages/modules/Virtualization/authfs"
+ },
+ {
+ "path": "packages/modules/Virtualization/avmd"
+ },
+ {
+ "path": "packages/modules/Virtualization/libs/devicemapper"
+ },
+ {
+ "path": "packages/modules/Virtualization/microdroid_manager"
+ },
+ {
+ "path": "packages/modules/Virtualization/virtualizationmanager"
+ },
+ {
+ "path": "packages/modules/Virtualization/vm"
+ },
+ {
+ "path": "packages/modules/Virtualization/zipfuse"
+ },
+ {
+ "path": "system/security/keystore2"
+ },
+ {
+ "path": "system/security/keystore2/legacykeystore"
}
],
"presubmit": [
{
- "name": "ZipFuseTest"
- },
- {
- "name": "apkdmverity.test"
- },
- {
- "name": "authfs_device_test_src_lib"
- },
- {
- "name": "keystore2_test"
- },
- {
- "name": "keystore2_test_utils_test"
- },
- {
- "name": "legacykeystore_test"
- },
- {
- "name": "microdroid_manager_test"
- },
- {
"name": "rand_core_test_src_lib"
- },
- {
- "name": "virtualizationservice_device_test"
}
],
"presubmit-rust": [
{
- "name": "ZipFuseTest"
- },
- {
- "name": "apkdmverity.test"
- },
- {
- "name": "authfs_device_test_src_lib"
- },
- {
- "name": "keystore2_test"
- },
- {
- "name": "keystore2_test_utils_test"
- },
- {
- "name": "legacykeystore_test"
- },
- {
- "name": "microdroid_manager_test"
- },
- {
"name": "rand_core_test_src_lib"
- },
- {
- "name": "virtualizationservice_device_test"
}
]
}
diff --git a/cargo2android.json b/cargo2android.json
index b73c7b4..8945bb0 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -7,5 +7,6 @@
"device": true,
"features": "std",
"run": true,
- "tests": true
-}
\ No newline at end of file
+ "tests": true,
+ "vendor-available": true
+}
diff --git a/src/block.rs b/src/block.rs
index a54cadf..d311b68 100644
--- a/src/block.rs
+++ b/src/block.rs
@@ -95,7 +95,7 @@
/// [`fill_bytes`] / [`try_fill_bytes`] is called on a large array. These methods
/// also handle the bookkeeping of when to generate a new batch of values.
///
-/// No whole generated `u32` values are thown away and all values are consumed
+/// No whole generated `u32` values are thrown away and all values are consumed
/// in-order. [`next_u32`] simply takes the next available `u32` value.
/// [`next_u64`] is implemented by combining two `u32` values, least
/// significant first. [`fill_bytes`] and [`try_fill_bytes`] consume a whole
@@ -352,27 +352,21 @@
{
#[inline]
fn next_u32(&mut self) -> u32 {
- let mut index = self.index * 2 - self.half_used as usize;
- if index >= self.results.as_ref().len() * 2 {
+ let mut index = self.index - self.half_used as usize;
+ if index >= self.results.as_ref().len() {
self.core.generate(&mut self.results);
self.index = 0;
+ index = 0;
// `self.half_used` is by definition `false`
self.half_used = false;
- index = 0;
}
+ let shift = 32 * (self.half_used as usize);
+
self.half_used = !self.half_used;
self.index += self.half_used as usize;
- // Index as if this is a u32 slice.
- unsafe {
- let results = &*(self.results.as_ref() as *const [u64] as *const [u32]);
- if cfg!(target_endian = "little") {
- *results.get_unchecked(index)
- } else {
- *results.get_unchecked(index ^ 1)
- }
- }
+ (self.results.as_ref()[index] >> shift) as u32
}
#[inline]
@@ -435,3 +429,111 @@
}
impl<R: BlockRngCore + CryptoRng> CryptoRng for BlockRng<R> {}
+
+#[cfg(test)]
+mod test {
+ use crate::{SeedableRng, RngCore};
+ use crate::block::{BlockRng, BlockRng64, BlockRngCore};
+
+ #[derive(Debug, Clone)]
+ struct DummyRng {
+ counter: u32,
+ }
+
+ impl BlockRngCore for DummyRng {
+ type Item = u32;
+
+ type Results = [u32; 16];
+
+ fn generate(&mut self, results: &mut Self::Results) {
+ for r in results {
+ *r = self.counter;
+ self.counter = self.counter.wrapping_add(3511615421);
+ }
+ }
+ }
+
+ impl SeedableRng for DummyRng {
+ type Seed = [u8; 4];
+
+ fn from_seed(seed: Self::Seed) -> Self {
+ DummyRng { counter: u32::from_le_bytes(seed) }
+ }
+ }
+
+ #[test]
+ fn blockrng_next_u32_vs_next_u64() {
+ let mut rng1 = BlockRng::<DummyRng>::from_seed([1, 2, 3, 4]);
+ let mut rng2 = rng1.clone();
+ let mut rng3 = rng1.clone();
+
+ let mut a = [0; 16];
+ (&mut a[..4]).copy_from_slice(&rng1.next_u32().to_le_bytes());
+ (&mut a[4..12]).copy_from_slice(&rng1.next_u64().to_le_bytes());
+ (&mut a[12..]).copy_from_slice(&rng1.next_u32().to_le_bytes());
+
+ let mut b = [0; 16];
+ (&mut b[..4]).copy_from_slice(&rng2.next_u32().to_le_bytes());
+ (&mut b[4..8]).copy_from_slice(&rng2.next_u32().to_le_bytes());
+ (&mut b[8..]).copy_from_slice(&rng2.next_u64().to_le_bytes());
+ assert_eq!(a, b);
+
+ let mut c = [0; 16];
+ (&mut c[..8]).copy_from_slice(&rng3.next_u64().to_le_bytes());
+ (&mut c[8..12]).copy_from_slice(&rng3.next_u32().to_le_bytes());
+ (&mut c[12..]).copy_from_slice(&rng3.next_u32().to_le_bytes());
+ assert_eq!(a, c);
+ }
+
+ #[derive(Debug, Clone)]
+ struct DummyRng64 {
+ counter: u64,
+ }
+
+ impl BlockRngCore for DummyRng64 {
+ type Item = u64;
+
+ type Results = [u64; 8];
+
+ fn generate(&mut self, results: &mut Self::Results) {
+ for r in results {
+ *r = self.counter;
+ self.counter = self.counter.wrapping_add(2781463553396133981);
+ }
+ }
+ }
+
+ impl SeedableRng for DummyRng64 {
+ type Seed = [u8; 8];
+
+ fn from_seed(seed: Self::Seed) -> Self {
+ DummyRng64 { counter: u64::from_le_bytes(seed) }
+ }
+ }
+
+ #[test]
+ fn blockrng64_next_u32_vs_next_u64() {
+ let mut rng1 = BlockRng64::<DummyRng64>::from_seed([1, 2, 3, 4, 5, 6, 7, 8]);
+ let mut rng2 = rng1.clone();
+ let mut rng3 = rng1.clone();
+
+ let mut a = [0; 16];
+ (&mut a[..4]).copy_from_slice(&rng1.next_u32().to_le_bytes());
+ (&mut a[4..12]).copy_from_slice(&rng1.next_u64().to_le_bytes());
+ (&mut a[12..]).copy_from_slice(&rng1.next_u32().to_le_bytes());
+
+ let mut b = [0; 16];
+ (&mut b[..4]).copy_from_slice(&rng2.next_u32().to_le_bytes());
+ (&mut b[4..8]).copy_from_slice(&rng2.next_u32().to_le_bytes());
+ (&mut b[8..]).copy_from_slice(&rng2.next_u64().to_le_bytes());
+ assert_ne!(a, b);
+ assert_eq!(&a[..4], &b[..4]);
+ assert_eq!(&a[4..12], &b[8..]);
+
+ let mut c = [0; 16];
+ (&mut c[..8]).copy_from_slice(&rng3.next_u64().to_le_bytes());
+ (&mut c[8..12]).copy_from_slice(&rng3.next_u32().to_le_bytes());
+ (&mut c[12..]).copy_from_slice(&rng3.next_u32().to_le_bytes());
+ assert_eq!(b, c);
+ }
+}
diff --git a/src/error.rs b/src/error.rs
index a64c430..411896f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -82,7 +82,7 @@
///
/// This method is identical to `std::io::Error::raw_os_error()`, except
/// that it works in `no_std` contexts. If this method returns `None`, the
- /// error value can still be formatted via the `Diplay` implementation.
+ /// error value can still be formatted via the `Display` implementation.
#[inline]
pub fn raw_os_error(&self) -> Option<i32> {
#[cfg(feature = "std")]
diff --git a/src/impls.rs b/src/impls.rs
index 2588a72..4b7688c 100644
--- a/src/impls.rs
+++ b/src/impls.rs
@@ -52,36 +52,59 @@
}
}
-macro_rules! fill_via_chunks {
- ($src:expr, $dst:expr, $ty:ty) => {{
- const SIZE: usize = core::mem::size_of::<$ty>();
- let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
- let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;
+trait Observable: Copy {
+ type Bytes: AsRef<[u8]>;
+ fn to_le_bytes(self) -> Self::Bytes;
- // The following can be replaced with safe code, but unfortunately it's
- // ca. 8% slower.
- if cfg!(target_endian = "little") {
- unsafe {
- core::ptr::copy_nonoverlapping(
- $src.as_ptr() as *const u8,
- $dst.as_mut_ptr(),
- chunk_size_u8);
- }
- } else {
- for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) {
- let tmp = n.to_le();
- let src_ptr = &tmp as *const $ty as *const u8;
- unsafe {
- core::ptr::copy_nonoverlapping(
- src_ptr,
- chunk.as_mut_ptr(),
- chunk.len());
- }
- }
+ // Contract: observing self is memory-safe (implies no uninitialised padding)
+ fn as_byte_slice(x: &[Self]) -> &[u8];
+}
+impl Observable for u32 {
+ type Bytes = [u8; 4];
+ fn to_le_bytes(self) -> Self::Bytes {
+ self.to_le_bytes()
+ }
+ fn as_byte_slice(x: &[Self]) -> &[u8] {
+ let ptr = x.as_ptr() as *const u8;
+ let len = x.len() * core::mem::size_of::<Self>();
+ unsafe { core::slice::from_raw_parts(ptr, len) }
+ }
+}
+impl Observable for u64 {
+ type Bytes = [u8; 8];
+ fn to_le_bytes(self) -> Self::Bytes {
+ self.to_le_bytes()
+ }
+ fn as_byte_slice(x: &[Self]) -> &[u8] {
+ let ptr = x.as_ptr() as *const u8;
+ let len = x.len() * core::mem::size_of::<Self>();
+ unsafe { core::slice::from_raw_parts(ptr, len) }
+ }
+}
+
+fn fill_via_chunks<T: Observable>(src: &[T], dest: &mut [u8]) -> (usize, usize) {
+ let size = core::mem::size_of::<T>();
+ let byte_len = min(src.len() * size, dest.len());
+ let num_chunks = (byte_len + size - 1) / size;
+
+ if cfg!(target_endian = "little") {
+ // On LE we can do a simple copy, which is 25-50% faster:
+ dest[..byte_len].copy_from_slice(&T::as_byte_slice(&src[..num_chunks])[..byte_len]);
+ } else {
+ // This code is valid on all arches, but slower than the above:
+ let mut i = 0;
+ let mut iter = dest[..byte_len].chunks_exact_mut(size);
+ for chunk in &mut iter {
+ chunk.copy_from_slice(src[i].to_le_bytes().as_ref());
+ i += 1;
}
+ let chunk = iter.into_remainder();
+ if !chunk.is_empty() {
+ chunk.copy_from_slice(&src[i].to_le_bytes().as_ref()[..chunk.len()]);
+ }
+ }
- (chunk_size, chunk_size_u8)
- }};
+ (num_chunks, byte_len)
}
/// Implement `fill_bytes` by reading chunks from the output buffer of a block
@@ -115,7 +138,7 @@
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
- fill_via_chunks!(src, dest, u32)
+ fill_via_chunks(src, dest)
}
/// Implement `fill_bytes` by reading chunks from the output buffer of a block
@@ -129,7 +152,7 @@
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
- fill_via_chunks!(src, dest, u64)
+ fill_via_chunks(src, dest)
}
/// Implement `next_u32` via `fill_bytes`, little-endian order.
diff --git a/src/lib.rs b/src/lib.rs
index bc24270..1234a56 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -196,7 +196,7 @@
/// Some generators may satisfy an additional property, however this is not
/// required by this trait: if the CSPRNG's state is revealed, it should not be
/// computationally-feasible to reconstruct output prior to this. Some other
-/// generators allow backwards-computation and are consided *reversible*.
+/// generators allow backwards-computation and are considered *reversible*.
///
/// Note that this trait is provided for guidance only and cannot guarantee
/// suitability for cryptographic applications. In general it should only be
@@ -208,6 +208,35 @@
/// [`BlockRngCore`]: block::BlockRngCore
pub trait CryptoRng {}
+/// An extension trait that is automatically implemented for any type
+/// implementing [`RngCore`] and [`CryptoRng`].
+///
+/// It may be used as a trait object, and supports upcasting to [`RngCore`] via
+/// the [`CryptoRngCore::as_rngcore`] method.
+///
+/// # Example
+///
+/// ```
+/// use rand_core::CryptoRngCore;
+///
+/// #[allow(unused)]
+/// fn make_token(rng: &mut dyn CryptoRngCore) -> [u8; 32] {
+/// let mut buf = [0u8; 32];
+/// rng.fill_bytes(&mut buf);
+/// buf
+/// }
+/// ```
+pub trait CryptoRngCore: CryptoRng + RngCore {
+ /// Upcast to an [`RngCore`] trait object.
+ fn as_rngcore(&mut self) -> &mut dyn RngCore;
+}
+
+impl<T: CryptoRng + RngCore> CryptoRngCore for T {
+ fn as_rngcore(&mut self) -> &mut dyn RngCore {
+ self
+ }
+}
+
/// A random number generator that can be explicitly seeded.
///
/// This trait encapsulates the low-level functionality common to all
@@ -215,7 +244,7 @@
///
/// [`rand`]: https://docs.rs/rand
pub trait SeedableRng: Sized {
- /// Seed type, which is restricted to types mutably-dereferencable as `u8`
+ /// Seed type, which is restricted to types mutably-dereferenceable as `u8`
/// arrays (we recommend `[u8; N]` for some `N`).
///
/// It is recommended to seed PRNGs with a seed of at least circa 100 bits,
@@ -448,10 +477,10 @@
}
}
-// Implement `CryptoRng` for references to an `CryptoRng`.
+// Implement `CryptoRng` for references to a `CryptoRng`.
impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {}
-// Implement `CryptoRng` for boxed references to an `CryptoRng`.
+// Implement `CryptoRng` for boxed references to a `CryptoRng`.
#[cfg(feature = "alloc")]
impl<R: CryptoRng + ?Sized> CryptoRng for Box<R> {}