Upgrade rust/crates/rand_chacha to 0.3.1 am: 2e480afc94 am: ef10ef0982 am: 746dbdab82

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/rand_chacha/+/1742521

Change-Id: I610d3a0eb224b8b476195cc8657d2ec39f573467
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 0db4f9b..e097925 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "98e220c30234370fb04ba928799ebd9727fc049a"
+    "sha1": "98a0339f99ecfe0467b2829c329bd8b7525a1c21"
   }
 }
diff --git a/Android.bp b/Android.bp
index 4fa5058..57b308b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
 // This file is generated by cargo2android.py --device --run --dependencies.
+// Do not modify this file as changes will be overridden on upgrade.
 
 package {
     default_applicable_licenses: ["external_rust_crates_rand_chacha_license"],
@@ -55,4 +56,4 @@
 
 // dependent_library ["feature_list"]
 //   ppv-lite86-0.2.10 "simd,std"
-//   rand_core-0.6.0
+//   rand_core-0.6.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a07390..a598bb7 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.3.1] - 2021-06-09
+- add getters corresponding to existing setters: `get_seed`, `get_stream` (#1124)
+- add serde support, gated by the `serde1` feature (#1124)
+- ensure expected layout via `repr(transparent)` (#1120)
+
 ## [0.3.0] - 2020-12-08
 - Bump `rand_core` version to 0.6.0
 - Bump MSRV to 1.36 (#1011)
diff --git a/Cargo.toml b/Cargo.toml
index 0f371b3..c907ae9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,11 +13,11 @@
 [package]
 edition = "2018"
 name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
 authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"]
 description = "ChaCha random number generator\n"
-homepage = "https://crates.io/crates/rand_chacha"
-documentation = "https://rust-random.github.io/rand/rand_chacha/"
+homepage = "https://rust-random.github.io/book"
+documentation = "https://docs.rs/rand_chacha"
 readme = "README.md"
 keywords = ["random", "rng", "chacha"]
 categories = ["algorithms", "no-std"]
@@ -31,7 +31,15 @@
 [dependencies.rand_core]
 version = "0.6.0"
 
+[dependencies.serde]
+version = "1.0"
+features = ["derive"]
+optional = true
+[dev-dependencies.serde_json]
+version = "1.0"
+
 [features]
 default = ["std"]
+serde1 = ["serde"]
 simd = []
 std = ["ppv-lite86/std"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 8d7dcd7..53f9f59 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,12 +1,12 @@
 [package]
 name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
 authors = ["The Rand Project Developers", "The Rust Project Developers", "The CryptoCorrosion Contributors"]
 license = "MIT OR Apache-2.0"
 readme = "README.md"
 repository = "https://github.com/rust-random/rand"
-documentation = "https://rust-random.github.io/rand/rand_chacha/"
-homepage = "https://crates.io/crates/rand_chacha"
+documentation = "https://docs.rs/rand_chacha"
+homepage = "https://rust-random.github.io/book"
 description = """
 ChaCha random number generator
 """
@@ -17,8 +17,14 @@
 [dependencies]
 rand_core = { path = "../rand_core", version = "0.6.0" }
 ppv-lite86 = { version = "0.2.8", default-features = false, features = ["simd"] }
+serde = { version = "1.0", features = ["derive"], optional = true }
+
+[dev-dependencies]
+# Only to test serde1
+serde_json = "1.0"
 
 [features]
 default = ["std"]
 std = ["ppv-lite86/std"]
 simd = [] # deprecated
+serde1 = ["serde"]
diff --git a/METADATA b/METADATA
index ba8e6ec..72cd107 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/rand_chacha/rand_chacha-0.3.0.crate"
+    value: "https://static.crates.io/crates/rand_chacha/rand_chacha-0.3.1.crate"
   }
-  version: "0.3.0"
+  version: "0.3.1"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2020
-    month: 12
-    day: 15
+    year: 2021
+    month: 6
+    day: 21
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..2441f5b
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,233 @@
+// Generated by update_crate_tests.py for tests that depend on this crate.
+{
+  "presubmit": [
+    {
+      "name": "crossbeam-epoch_device_test_src_lib"
+    },
+    {
+      "name": "crossbeam-epoch_device_test_tests_loom"
+    },
+    {
+      "name": "crossbeam-utils_device_test_src_lib"
+    },
+    {
+      "name": "crossbeam-utils_device_test_tests_atomic_cell"
+    },
+    {
+      "name": "crossbeam-utils_device_test_tests_cache_padded"
+    },
+    {
+      "name": "crossbeam-utils_device_test_tests_parker"
+    },
+    {
+      "name": "crossbeam-utils_device_test_tests_sharded_lock"
+    },
+    {
+      "name": "crossbeam-utils_device_test_tests_thread"
+    },
+    {
+      "name": "crossbeam-utils_device_test_tests_wait_group"
+    },
+    {
+      "name": "keystore2_test"
+    },
+    {
+      "name": "tokio_device_test_tests__require_full"
+    },
+    {
+      "name": "tokio_device_test_tests_buffered"
+    },
+    {
+      "name": "tokio_device_test_tests_io_async_fd"
+    },
+    {
+      "name": "tokio_device_test_tests_io_async_read"
+    },
+    {
+      "name": "tokio_device_test_tests_io_chain"
+    },
+    {
+      "name": "tokio_device_test_tests_io_copy"
+    },
+    {
+      "name": "tokio_device_test_tests_io_copy_bidirectional"
+    },
+    {
+      "name": "tokio_device_test_tests_io_driver"
+    },
+    {
+      "name": "tokio_device_test_tests_io_driver_drop"
+    },
+    {
+      "name": "tokio_device_test_tests_io_lines"
+    },
+    {
+      "name": "tokio_device_test_tests_io_mem_stream"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read_buf"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read_exact"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read_line"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read_to_end"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read_to_string"
+    },
+    {
+      "name": "tokio_device_test_tests_io_read_until"
+    },
+    {
+      "name": "tokio_device_test_tests_io_split"
+    },
+    {
+      "name": "tokio_device_test_tests_io_take"
+    },
+    {
+      "name": "tokio_device_test_tests_io_write"
+    },
+    {
+      "name": "tokio_device_test_tests_io_write_all"
+    },
+    {
+      "name": "tokio_device_test_tests_io_write_buf"
+    },
+    {
+      "name": "tokio_device_test_tests_io_write_int"
+    },
+    {
+      "name": "tokio_device_test_tests_macros_join"
+    },
+    {
+      "name": "tokio_device_test_tests_macros_pin"
+    },
+    {
+      "name": "tokio_device_test_tests_macros_select"
+    },
+    {
+      "name": "tokio_device_test_tests_macros_test"
+    },
+    {
+      "name": "tokio_device_test_tests_macros_try_join"
+    },
+    {
+      "name": "tokio_device_test_tests_net_bind_resource"
+    },
+    {
+      "name": "tokio_device_test_tests_net_lookup_host"
+    },
+    {
+      "name": "tokio_device_test_tests_no_rt"
+    },
+    {
+      "name": "tokio_device_test_tests_process_kill_on_drop"
+    },
+    {
+      "name": "tokio_device_test_tests_rt_basic"
+    },
+    {
+      "name": "tokio_device_test_tests_rt_common"
+    },
+    {
+      "name": "tokio_device_test_tests_rt_threaded"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_barrier"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_broadcast"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_errors"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_mpsc"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_mutex"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_mutex_owned"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_notify"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_oneshot"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_rwlock"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_semaphore"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_semaphore_owned"
+    },
+    {
+      "name": "tokio_device_test_tests_sync_watch"
+    },
+    {
+      "name": "tokio_device_test_tests_task_abort"
+    },
+    {
+      "name": "tokio_device_test_tests_task_blocking"
+    },
+    {
+      "name": "tokio_device_test_tests_task_local"
+    },
+    {
+      "name": "tokio_device_test_tests_task_local_set"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_accept"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_connect"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_echo"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_into_split"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_into_std"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_peek"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_shutdown"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_socket"
+    },
+    {
+      "name": "tokio_device_test_tests_tcp_split"
+    },
+    {
+      "name": "tokio_device_test_tests_time_rt"
+    },
+    {
+      "name": "tokio_device_test_tests_udp"
+    },
+    {
+      "name": "tokio_device_test_tests_uds_cred"
+    },
+    {
+      "name": "tokio_device_test_tests_uds_split"
+    },
+    {
+      "name": "vpnprofilestore_test"
+    }
+  ]
+}
diff --git a/src/chacha.rs b/src/chacha.rs
index 17bcc55..50da81b 100644
--- a/src/chacha.rs
+++ b/src/chacha.rs
@@ -16,14 +16,14 @@
 use rand_core::block::{BlockRng, BlockRngCore};
 use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
 
-const STREAM_PARAM_NONCE: u32 = 1;
-const STREAM_PARAM_BLOCK: u32 = 0;
+#[cfg(feature = "serde1")] use serde::{Serialize, Deserialize, Serializer, Deserializer};
 
 // NB. this must remain consistent with some currently hard-coded numbers in this module
 const BUF_BLOCKS: u8 = 4;
 // number of 32-bit words per ChaCha block (fixed by algorithm definition)
 const BLOCK_WORDS: u8 = 16;
 
+#[repr(transparent)]
 pub struct Array64<T>([T; 64]);
 impl<T> Default for Array64<T>
 where T: Default
@@ -68,7 +68,7 @@
 }
 
 macro_rules! chacha_impl {
-    ($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr) => {
+    ($ChaChaXCore:ident, $ChaChaXRng:ident, $rounds:expr, $doc:expr, $abst:ident) => {
         #[doc=$doc]
         #[derive(Clone, PartialEq, Eq)]
         pub struct $ChaChaXCore {
@@ -193,7 +193,7 @@
             #[inline]
             pub fn get_word_pos(&self) -> u128 {
                 let buf_start_block = {
-                    let buf_end_block = self.rng.core.state.get_stream_param(STREAM_PARAM_BLOCK);
+                    let buf_end_block = self.rng.core.state.get_block_pos();
                     u64::wrapping_sub(buf_end_block, BUF_BLOCKS.into())
                 };
                 let (buf_offset_blocks, block_offset_words) = {
@@ -218,7 +218,7 @@
                 self.rng
                     .core
                     .state
-                    .set_stream_param(STREAM_PARAM_BLOCK, block);
+                    .set_block_pos(block);
                 self.rng.generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize);
             }
 
@@ -238,12 +238,30 @@
                 self.rng
                     .core
                     .state
-                    .set_stream_param(STREAM_PARAM_NONCE, stream);
+                    .set_nonce(stream);
                 if self.rng.index() != 64 {
                     let wp = self.get_word_pos();
                     self.set_word_pos(wp);
                 }
             }
+
+            /// Get the stream number.
+            #[inline]
+            pub fn get_stream(&self) -> u64 {
+                self.rng
+                    .core
+                    .state
+                    .get_nonce()
+            }
+
+            /// Get the seed.
+            #[inline]
+            pub fn get_seed(&self) -> [u8; 32] {
+                self.rng
+                    .core
+                    .state
+                    .get_seed()
+            }
         }
 
         impl CryptoRng for $ChaChaXRng {}
@@ -258,24 +276,129 @@
 
         impl PartialEq<$ChaChaXRng> for $ChaChaXRng {
             fn eq(&self, rhs: &$ChaChaXRng) -> bool {
-                self.rng.core.state.stream64_eq(&rhs.rng.core.state)
-                    && self.get_word_pos() == rhs.get_word_pos()
+                let a: $abst::$ChaChaXRng = self.into();
+                let b: $abst::$ChaChaXRng = rhs.into();
+                a == b
             }
         }
         impl Eq for $ChaChaXRng {}
+
+        #[cfg(feature = "serde1")]
+        impl Serialize for $ChaChaXRng {
+            fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
+            where S: Serializer {
+                $abst::$ChaChaXRng::from(self).serialize(s)
+            }
+        }
+        #[cfg(feature = "serde1")]
+        impl<'de> Deserialize<'de> for $ChaChaXRng {
+            fn deserialize<D>(d: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
+                $abst::$ChaChaXRng::deserialize(d).map(|x| Self::from(&x))
+            }
+        }
+
+        mod $abst {
+            #[cfg(feature = "serde1")] use serde::{Serialize, Deserialize};
+
+            // The abstract state of a ChaCha stream, independent of implementation choices. The
+            // comparison and serialization of this object is considered a semver-covered part of
+            // the API.
+            #[derive(Debug, PartialEq, Eq)]
+            #[cfg_attr(
+                feature = "serde1",
+                derive(Serialize, Deserialize),
+            )]
+            pub(crate) struct $ChaChaXRng {
+                seed: [u8; 32],
+                stream: u64,
+                word_pos: u128,
+            }
+
+            impl From<&super::$ChaChaXRng> for $ChaChaXRng {
+                // Forget all information about the input except what is necessary to determine the
+                // outputs of any sequence of pub API calls.
+                fn from(r: &super::$ChaChaXRng) -> Self {
+                    Self {
+                        seed: r.get_seed(),
+                        stream: r.get_stream(),
+                        word_pos: r.get_word_pos(),
+                    }
+                }
+            }
+
+            impl From<&$ChaChaXRng> for super::$ChaChaXRng {
+                // Construct one of the possible concrete RNGs realizing an abstract state.
+                fn from(a: &$ChaChaXRng) -> Self {
+                    use rand_core::SeedableRng;
+                    let mut r = Self::from_seed(a.seed);
+                    r.set_stream(a.stream);
+                    r.set_word_pos(a.word_pos);
+                    r
+                }
+            }
+        }
     }
 }
 
-chacha_impl!(ChaCha20Core, ChaCha20Rng, 10, "ChaCha with 20 rounds");
-chacha_impl!(ChaCha12Core, ChaCha12Rng, 6, "ChaCha with 12 rounds");
-chacha_impl!(ChaCha8Core, ChaCha8Rng, 4, "ChaCha with 8 rounds");
+chacha_impl!(ChaCha20Core, ChaCha20Rng, 10, "ChaCha with 20 rounds", abstract20);
+chacha_impl!(ChaCha12Core, ChaCha12Rng, 6, "ChaCha with 12 rounds", abstract12);
+chacha_impl!(ChaCha8Core, ChaCha8Rng, 4, "ChaCha with 8 rounds", abstract8);
 
 #[cfg(test)]
 mod test {
     use rand_core::{RngCore, SeedableRng};
 
+    #[cfg(feature = "serde1")] use super::{ChaCha20Rng, ChaCha12Rng, ChaCha8Rng};
+
     type ChaChaRng = super::ChaCha20Rng;
 
+    #[cfg(feature = "serde1")]
+    #[test]
+    fn test_chacha_serde_roundtrip() {
+        let seed = [
+            1, 0, 52, 0, 0, 0, 0, 0, 1, 0, 10, 0, 22, 32, 0, 0, 2, 0, 55, 49, 0, 11, 0, 0, 3, 0, 0, 0, 0,
+            0, 2, 92,
+        ];
+        let mut rng1 = ChaCha20Rng::from_seed(seed);
+        let mut rng2 = ChaCha12Rng::from_seed(seed);
+        let mut rng3 = ChaCha8Rng::from_seed(seed);
+
+        let encoded1 = serde_json::to_string(&rng1).unwrap();
+        let encoded2 = serde_json::to_string(&rng2).unwrap();
+        let encoded3 = serde_json::to_string(&rng3).unwrap();
+
+        let mut decoded1: ChaCha20Rng = serde_json::from_str(&encoded1).unwrap();
+        let mut decoded2: ChaCha12Rng = serde_json::from_str(&encoded2).unwrap();
+        let mut decoded3: ChaCha8Rng = serde_json::from_str(&encoded3).unwrap();
+
+        assert_eq!(rng1, decoded1);
+        assert_eq!(rng2, decoded2);
+        assert_eq!(rng3, decoded3);
+
+        assert_eq!(rng1.next_u32(), decoded1.next_u32());
+        assert_eq!(rng2.next_u32(), decoded2.next_u32());
+        assert_eq!(rng3.next_u32(), decoded3.next_u32());
+    }
+
+    // This test validates that:
+    // 1. a hard-coded serialization demonstrating the format at time of initial release can still
+    //    be deserialized to a ChaChaRng
+    // 2. re-serializing the resultant object produces exactly the original string
+    //
+    // Condition 2 is stronger than necessary: an equivalent serialization (e.g. with field order
+    // permuted, or whitespace differences) would also be admissible, but would fail this test.
+    // However testing for equivalence of serialized data is difficult, and there shouldn't be any
+    // reason we need to violate the stronger-than-needed condition, e.g. by changing the field
+    // definition order.
+    #[cfg(feature = "serde1")]
+    #[test]
+    fn test_chacha_serde_format_stability() {
+        let j = r#"{"seed":[4,8,15,16,23,42,4,8,15,16,23,42,4,8,15,16,23,42,4,8,15,16,23,42,4,8,15,16,23,42,4,8],"stream":27182818284,"word_pos":314159265359}"#;
+        let r: ChaChaRng = serde_json::from_str(&j).unwrap();
+        let j1 = serde_json::to_string(&r).unwrap();
+        assert_eq!(j, j1);
+    }
+
     #[test]
     fn test_chacha_construction() {
         let seed = [
diff --git a/src/guts.rs b/src/guts.rs
index 27ff957..cee8cf7 100644
--- a/src/guts.rs
+++ b/src/guts.rs
@@ -21,6 +21,9 @@
 pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS;
 pub(crate) const BUFSZ: usize = BUFSZ64 as usize;
 
+const STREAM_PARAM_NONCE: u32 = 1;
+const STREAM_PARAM_BLOCK: u32 = 0;
+
 #[derive(Clone, PartialEq, Eq)]
 pub struct ChaCha {
     pub(crate) b: vec128_storage,
@@ -83,21 +86,28 @@
     }
 
     #[inline(always)]
-    pub fn set_stream_param(&mut self, param: u32, value: u64) {
-        set_stream_param(self, param, value)
+    pub fn set_block_pos(&mut self, value: u64) {
+        set_stream_param(self, STREAM_PARAM_BLOCK, value)
     }
 
     #[inline(always)]
-    pub fn get_stream_param(&self, param: u32) -> u64 {
-        get_stream_param(self, param)
+    pub fn get_block_pos(&self) -> u64 {
+        get_stream_param(self, STREAM_PARAM_BLOCK)
     }
 
-    /// Return whether rhs is equal in all parameters except current 64-bit position.
-    #[inline]
-    pub fn stream64_eq(&self, rhs: &Self) -> bool {
-        let self_d: [u32; 4] = self.d.into();
-        let rhs_d: [u32; 4] = rhs.d.into();
-        self.b == rhs.b && self.c == rhs.c && self_d[3] == rhs_d[3] && self_d[2] == rhs_d[2]
+    #[inline(always)]
+    pub fn set_nonce(&mut self, value: u64) {
+        set_stream_param(self, STREAM_PARAM_NONCE, value)
+    }
+
+    #[inline(always)]
+    pub fn get_nonce(&self) -> u64 {
+        get_stream_param(self, STREAM_PARAM_NONCE)
+    }
+
+    #[inline(always)]
+    pub fn get_seed(&self) -> [u8; 32] {
+        get_seed(self)
     }
 }
 
@@ -205,6 +215,17 @@
     }
 });
 
+dispatch_light128!(m, Mach, {
+    fn get_seed(state: &ChaCha) -> [u8; 32] {
+        let b: Mach::u32x4 = m.unpack(state.b);
+        let c: Mach::u32x4 = m.unpack(state.c);
+        let mut key = [0u8; 32];
+        b.write_le(&mut key[..16]);
+        c.write_le(&mut key[16..]);
+        key
+    }
+});
+
 fn read_u32le(xs: &[u8]) -> u32 {
     assert_eq!(xs.len(), 4);
     u32::from(xs[0]) | (u32::from(xs[1]) << 8) | (u32::from(xs[2]) << 16) | (u32::from(xs[3]) << 24)