diff --git a/rust/pv_core/src/confidential.rs b/rust/pv_core/src/confidential.rs index 0e8e6f96..1c5aa8e0 100644 --- a/rust/pv_core/src/confidential.rs +++ b/rust/pv_core/src/confidential.rs @@ -13,28 +13,35 @@ pub trait Zeroize { } // Automatically impl Zeroize for u8 arrays -impl Zeroize for [u8; COUNT] { +impl Zeroize for [T; COUNT] { /// Reliably overwrites the given buffer with zeros, /// by performing a volatile write followed by a memory barrier fn zeroize(&mut self) { - // SAFETY: given buffer(self) has the correct (compile time) size - unsafe { std::ptr::write_volatile(self, [0u8; COUNT]) }; + let mut dst = self.as_mut_ptr(); + for _ in 0..self.len() { + // SAFETY: + // * Array allocated len elements continuously + // * dst points always to a valid location + unsafe { + std::ptr::write_volatile(dst, T::default()); + dst = dst.add(1); + } + } std::sync::atomic::compiler_fence(std::sync::atomic::Ordering::SeqCst); } } -impl Zeroize for Vec { +impl Zeroize for Vec { /// Reliably overwrites the given buffer with zeros, /// by overwriting the whole vector's capacity with zeros. fn zeroize(&mut self) { - // TODO use `volatile_set_memory` when stabilized let mut dst = self.as_mut_ptr(); for _ in 0..self.capacity() { // SAFETY: // * Vec allocated at least capacity elements continuously // * dst points always to a valid location unsafe { - std::ptr::write_volatile(dst, 0); + std::ptr::write_volatile(dst, T::default()); dst = dst.add(1); } } @@ -116,3 +123,49 @@ impl Drop for Confidential { self.0.zeroize(); } } + +#[cfg(test)] +mod test { + use super::*; + + #[derive(Debug, Default, PartialEq, Eq)] + struct DummyStruct([u32; 8]); + + #[test] + fn array() { + let mut conf = Confidential::new([17; 42]); + assert_eq!(&[17; 42], conf.value()); + conf.zeroize(); + assert_eq!(&[0; 42], conf.value()); + + let mut conf2 = Confidential::new([DummyStruct([0x12u32; 8]), DummyStruct([0x24u32; 8])]); + assert_eq!( + &[DummyStruct([0x12u32; 8]), DummyStruct([0x24u32; 8])], + conf2.value() + ); + conf2.zeroize(); + assert_eq!( + &[DummyStruct([0x0u32; 8]), DummyStruct([0x0u32; 8])], + conf2.value() + ); + } + + #[test] + fn vec() { + let mut conf = Confidential::new(vec![17; 42]); + conf.zeroize(); + assert_eq!(&[0; 42], conf.value().as_slice()); + + let mut conf2 = + Confidential::new(vec![DummyStruct([0x12u32; 8]), DummyStruct([0x24u32; 8])]); + assert_eq!( + &[DummyStruct([0x12u32; 8]), DummyStruct([0x24u32; 8])], + conf2.value().as_slice() + ); + conf2.zeroize(); + assert_eq!( + &[DummyStruct([0x0u32; 8]), DummyStruct([0x0u32; 8])], + conf2.value().as_slice() + ); + } +}