From bb9279e2a639bed51a64802e73ed1030241bb803 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 12 Jun 2023 22:28:14 +0300 Subject: [PATCH 1/2] Optionally implement Zeroize on ArrayVec/ArrayString --- Cargo.toml | 5 +++++ src/array_string.rs | 24 ++++++++++++++++++++++++ src/arrayvec.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index ea041136..a0a44cd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,11 @@ version = "1.0" optional = true default-features = false +[dependencies.zeroize] +version = "1.4" +optional = true +default-features = false + [dev-dependencies.serde_test] version = "1.0" diff --git a/src/array_string.rs b/src/array_string.rs index 864daeae..90cfc090 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -647,3 +647,27 @@ impl<'a, const CAP: usize> TryFrom> for ArrayString Ok(v) } } + +#[cfg(feature = "zeroize")] +/// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled. +/// +/// The length is set to 0, and the buffer is dropped and zeroized. +/// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack. +/// +/// ``` +/// use arrayvec::ArrayString; +/// use zeroize::Zeroize; +/// let mut string = ArrayString::<6>::from("foobar").unwrap(); +/// string.zeroize(); +/// assert_eq!(string.len(), 0); +/// unsafe { string.set_len(string.capacity()) }; +/// assert_eq!(&*string, "\0\0\0\0\0\0"); +/// ``` +impl zeroize::Zeroize for ArrayString { + fn zeroize(&mut self) { + // There are no elements to drop + self.clear(); + // Zeroize the backing array. + self.xs.zeroize(); + } +} diff --git a/src/arrayvec.rs b/src/arrayvec.rs index f5b89e8d..37e151a6 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -848,6 +848,32 @@ impl IntoIterator for ArrayVec { } +#[cfg(feature = "zeroize")] +/// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled. +/// +/// The length is set to 0, and the buffer is dropped and zeroized. +/// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// use zeroize::Zeroize; +/// let mut array = ArrayVec::from([1, 2, 3]); +/// array.zeroize(); +/// assert_eq!(array.len(), 0); +/// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) }; +/// assert_eq!(data, [0, 0, 0]); +/// ``` +impl zeroize::Zeroize for ArrayVec { + fn zeroize(&mut self) { + // Zeroize all the contained elements. + self.iter_mut().zeroize(); + // Drop all the elements and set the length to 0. + self.clear(); + // Zeroize the backing array. + self.xs.zeroize(); + } +} + /// By-value iterator for `ArrayVec`. pub struct IntoIter { index: usize, From 71200c01b96b01e6a3d5f634a411b3a433def98a Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Tue, 13 Jun 2023 22:02:06 +0300 Subject: [PATCH 2/2] Add Zeroize and benches to the CI matrix --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ccbf4234..56fdb0f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,12 +22,13 @@ jobs: experimental: false - rust: stable features: + bench: true experimental: false - rust: beta features: serde experimental: false - rust: nightly - features: serde + features: serde, zeroize experimental: false steps: @@ -57,4 +58,4 @@ jobs: rustup override set nightly cargo miri setup - name: Test with Miri - run: cargo miri test + run: cargo miri test --all-features