rust/pv_core: Generalize Confidential

Generalize the `Confidential` impl over Vec<T> and [COUNT; T] instead of
specializing T to u8.

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-10-25 10:04:30 +02:00
parent 516bd8c2cf
commit 0495947604

View File

@@ -13,28 +13,35 @@ pub trait Zeroize {
}
// Automatically impl Zeroize for u8 arrays
impl<const COUNT: usize> Zeroize for [u8; COUNT] {
impl<T: Default, const COUNT: usize> 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<u8> {
impl<T: Default> Zeroize for Vec<T> {
/// 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<C: Zeroize> Drop for Confidential<C> {
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()
);
}
}