Skip to content

Commit 7c07198

Browse files
author
Vishal Shenoy
committed
Implements zeroization support across all heapless data structures
Implements zeroization support across all heapless data structures to securely clear sensitive data from memory: - When the zeroize feature is enabled, the LenType sealed trait now has Zeroize as a supertrait - This simplifies the bound for deriving Zeroize for VecInner and other types - Added tests to verify VecView also implements Zeroize correctly This feature is essential for security-sensitive applications needing to prevent data leaks from memory dumps. Note: Zeroize initially worked on Vector purely via derivation, however was not complete without proper bound checks. Without these checks, the deref implementation of Zeroize was used instead, which led to incomplete zeroization of the Vector's contents.
1 parent 1a4b8c7 commit 7c07198

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

src/len_type.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ use core::{
33
ops::{Add, AddAssign, Sub, SubAssign},
44
};
55

6+
#[cfg(feature = "zeroize")]
7+
use zeroize::Zeroize;
8+
69
pub trait Sealed:
710
Send
811
+ Sync
@@ -75,6 +78,15 @@ macro_rules! impl_lentype {
7578
/// A sealed trait representing a valid type to use as a length for a container.
7679
///
7780
/// This cannot be implemented in user code, and is restricted to `u8`, `u16`, `u32`, and `usize`.
81+
///
82+
/// When the `zeroize` feature is enabled, this trait requires the `Zeroize` trait.
83+
#[cfg(feature = "zeroize")]
84+
pub trait LenType: Sealed + Zeroize {}
85+
86+
/// A sealed trait representing a valid type to use as a length for a container.
87+
///
88+
/// This cannot be implemented in user code, and is restricted to `u8`, `u16`, `u32`, and `usize`.
89+
#[cfg(not(feature = "zeroize"))]
7890
pub trait LenType: Sealed {}
7991

8092
impl_lentype!(

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,14 @@
108108
//!
109109
//! # Zeroize Support
110110
//!
111-
//! Enables secure memory wiping for the data structures via the [`zeroize`](https://crates.io/crates/zeroize)
111+
//! The `zeroize` feature enables secure memory wiping for the data structures via the [`zeroize`](https://crates.io/crates/zeroize)
112112
//! crate. Sensitive data can be properly erased from memory when no longer needed.
113113
//!
114114
//! When zeroizing a container, all underlying memory (including unused portion of the containers)
115115
//! is overwritten with zeros, length counters are reset, and the container is left in a valid but
116116
//! empty state that can be reused.
117117
//!
118+
//! Check the [documentation of the zeroize crate](https://docs.rs/zeroize/) for more information.
118119
//! # Minimum Supported Rust Version (MSRV)
119120
//!
120121
//! This crate does *not* have a Minimum Supported Rust Version (MSRV) and may make use of language

src/vec/mod.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,11 +215,7 @@ pub use drain::Drain;
215215
///
216216
/// In most cases you should use [`Vec`] or [`VecView`] directly. Only use this
217217
/// struct if you want to write code that's generic over both.
218-
#[cfg_attr(
219-
feature = "zeroize",
220-
derive(Zeroize),
221-
zeroize(bound = "S: Zeroize, LenT: Zeroize")
222-
)]
218+
#[cfg_attr(feature = "zeroize", derive(Zeroize), zeroize(bound = "S: Zeroize"))]
223219
pub struct VecInner<T, LenT: LenType, S: VecStorage<T> + ?Sized> {
224220
phantom: PhantomData<T>,
225221
len: LenT,
@@ -2293,6 +2289,35 @@ mod tests {
22932289
}
22942290
}
22952291

2292+
#[test]
2293+
#[cfg(feature = "zeroize")]
2294+
fn test_vecview_zeroize() {
2295+
use zeroize::Zeroize;
2296+
2297+
let mut v: Vec<u8, 8> = Vec::new();
2298+
for i in 0..8 {
2299+
v.push(i).unwrap();
2300+
}
2301+
2302+
let view = v.as_mut_view();
2303+
2304+
for i in 0..8 {
2305+
assert_eq!(view[i], i as u8);
2306+
}
2307+
2308+
view.zeroize();
2309+
2310+
assert_eq!(view.len(), 0);
2311+
2312+
unsafe {
2313+
view.set_len(8);
2314+
}
2315+
2316+
for i in 0..8 {
2317+
assert_eq!(view[i], 0);
2318+
}
2319+
}
2320+
22962321
fn _test_variance<'a: 'b, 'b>(x: Vec<&'a (), 42>) -> Vec<&'b (), 42> {
22972322
x
22982323
}

0 commit comments

Comments
 (0)