Skip to content

Commit

Permalink
Implement ZeroizeOnDrop for containers (#703)
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Jan 6, 2022
1 parent 3f645e3 commit 3d9cd39
Showing 1 changed file with 50 additions and 2 deletions.
52 changes: 50 additions & 2 deletions zeroize/src/lib.rs
Expand Up @@ -260,8 +260,7 @@ pub trait Zeroize {
}

/// Marker trait signifying that this type will [`zeroize`](Zeroize::zeroize) itself on [`Drop`].
#[allow(drop_bounds)]
pub trait ZeroizeOnDrop: Drop {}
pub trait ZeroizeOnDrop {}

/// Marker trait for types whose `Default` is the desired zeroization result
pub trait DefaultIsZeroes: Copy + Default + Sized {}
Expand Down Expand Up @@ -324,6 +323,8 @@ where
self.iter_mut().zeroize();
}
}
/// Implement `ZeroizeOnDrop` on arrays of types that impl `ZeroizeOnDrop`
impl<Z, const N: usize> ZeroizeOnDrop for [Z; N] where Z: ZeroizeOnDrop {}

impl<'a, Z> Zeroize for IterMut<'a, Z>
where
Expand Down Expand Up @@ -376,6 +377,8 @@ where
}
}

impl<Z> ZeroizeOnDrop for Option<Z> where Z: ZeroizeOnDrop {}

/// Impl `Zeroize` on slices of MaybeUninit types
/// This impl can eventually be optimized using an memset intrinsic,
/// such as `core::intrinsics::volatile_set_memory`.
Expand Down Expand Up @@ -453,6 +456,10 @@ where
}
}

#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<Z> ZeroizeOnDrop for Vec<Z> where Z: ZeroizeOnDrop {}

#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<Z> Zeroize for Box<[Z]>
Expand All @@ -466,6 +473,10 @@ where
}
}

#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<Z> ZeroizeOnDrop for Box<[Z]> where Z: ZeroizeOnDrop {}

#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl Zeroize for String {
Expand Down Expand Up @@ -607,21 +618,29 @@ unsafe fn volatile_set<T: Copy + Sized>(dst: *mut T, src: T, count: usize) {
impl<Z> Zeroize for PhantomData<Z> {
fn zeroize(&mut self) {}
}
/// `PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation.
impl<Z> ZeroizeOnDrop for PhantomData<Z> {}
/// `PhantomPinned` is zero sized so provide a Zeroize implementation.
impl Zeroize for PhantomPinned {
fn zeroize(&mut self) {}
}
/// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation.
impl ZeroizeOnDrop for PhantomPinned {}
/// `()` is zero sized so provide a Zeroize implementation.
impl Zeroize for () {
fn zeroize(&mut self) {}
}
/// `()` is zero sized so provide a ZeroizeOnDrop implementation.
impl ZeroizeOnDrop for () {}

/// Generic implementation of Zeroize for tuples up to 10 parameters.
impl<A: Zeroize> Zeroize for (A,) {
fn zeroize(&mut self) {
self.0.zeroize();
}
}
/// Generic implementation of ZeroizeOnDrop for tuples up to 10 parameters.
impl<A: ZeroizeOnDrop> ZeroizeOnDrop for (A,) {}
macro_rules! impl_zeroize_tuple {
( $( $type_name:ident )+ ) => {
impl<$($type_name: Zeroize),+> Zeroize for ($($type_name),+) {
Expand All @@ -631,6 +650,8 @@ macro_rules! impl_zeroize_tuple {
$($type_name.zeroize());+
}
}

impl<$($type_name: ZeroizeOnDrop),+> ZeroizeOnDrop for ($($type_name),+) { }
}
}
// Generic implementations for tuples up to 10 parameters.
Expand All @@ -653,6 +674,15 @@ mod tests {
#[cfg(feature = "alloc")]
use alloc::boxed::Box;

#[derive(Clone, Debug, PartialEq)]
struct ZeroizedOnDrop(u64);

impl Drop for ZeroizedOnDrop {
fn drop(&mut self) {
self.0.zeroize();
}
}

#[test]
fn non_zero() {
macro_rules! non_zero_test {
Expand Down Expand Up @@ -688,6 +718,13 @@ mod tests {
assert_eq!(arr.as_ref(), [0u8; 137].as_ref());
}

#[test]
fn zeroize_on_drop_byte_arrays() {
let mut arr = [ZeroizedOnDrop(42); 1];
unsafe { core::ptr::drop_in_place(&mut arr) };
assert_eq!(arr.as_ref(), [ZeroizedOnDrop(0); 1].as_ref());
}

#[test]
fn zeroize_maybeuninit_byte_arrays() {
let mut arr = [MaybeUninit::new(42u64); 64];
Expand Down Expand Up @@ -716,6 +753,17 @@ mod tests {
assert_eq!(tup2, (0u8, 0u8));
}

#[test]
fn zeroize_on_drop_check_tuple() {
let mut tup1 = (ZeroizedOnDrop(42),);
unsafe { core::ptr::drop_in_place(&mut tup1) };
assert_eq!(tup1, (ZeroizedOnDrop(0),));

let mut tup2 = (ZeroizedOnDrop(42), ZeroizedOnDrop(42));
unsafe { core::ptr::drop_in_place(&mut tup2) };
assert_eq!(tup2, (ZeroizedOnDrop(0), ZeroizedOnDrop(0)));
}

#[cfg(feature = "alloc")]
#[test]
fn zeroize_vec() {
Expand Down

0 comments on commit 3d9cd39

Please sign in to comment.