diff --git a/rust/pv_core/src/confidential.rs b/rust/pv_core/src/confidential.rs index 1c5aa8e0..ce74adc4 100644 --- a/rust/pv_core/src/confidential.rs +++ b/rust/pv_core/src/confidential.rs @@ -49,6 +49,13 @@ impl Zeroize for Vec { } } +impl Zeroize for String { + fn zeroize(&mut self) { + // SAFETY: The Vec zerorize function overwrites memory with the zero byte -> still valid UTF-8 + unsafe { self.as_mut_vec().zeroize() }; + } +} + /// Thin wrapper around an type implementing Zeroize. /// /// A `Confidential` represents a confidential value that must be securely overwritten during drop. @@ -93,6 +100,16 @@ impl Confidential { } } +impl Confidential { + /// Consume the [`Confidential`] into its contained type as a clone. + /// + /// This disables any cleanups for the result. + pub fn into_inner(self) -> C { + // The clone is required because drop is implemented (E0509) + self.0.clone() + } +} + impl Debug for Confidential { #[allow(unreachable_code)] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -168,4 +185,11 @@ mod test { conf2.value().as_slice() ); } + + #[test] + fn string() { + let mut conf = Confidential::new("test".to_string()); + conf.zeroize(); + assert_eq!(&[0; 4], conf.value().as_bytes()); + } }