rust/pv_core: Implement Zeroroize for String

String is more or less a Vec<u8> with some extra invariants (i.e. only
UFF-8 chars). Zeroroize is implemented by calling the Vec<u8>
implementation. The zero byte is a valid UTF-8 symbol. The String
invariant is uphold by the clearing code.

Also, implement a into_inner function for clone-able inner types.
This allows converting confidential types into no-confidential types.
As Drop is implemented this requires a clone (see E0509).

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
Steffen Eiden
2024-06-26 14:56:16 +02:00
parent 0495947604
commit 5e97205530

View File

@@ -49,6 +49,13 @@ impl<T: Default> Zeroize for Vec<T> {
}
}
impl Zeroize for String {
fn zeroize(&mut self) {
// SAFETY: The Vec<u8> 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<C: Zeroize> Confidential<C> {
}
}
impl<C: Zeroize + Clone> Confidential<C> {
/// 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<C: Zeroize + Debug> Debug for Confidential<C> {
#[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());
}
}