Unsafe review: secretmangle::MangledBoxArbitrary
โ Rust ๐ 2025-09-22 ๐ค surdeus ๐๏ธ 9The crate part I'm presenting is secretmangle/src/arbitrary.rs at master ยท ProgramCrafter/secretmangle ยท GitHub.
/// Utility for masking a structure in program's heap with a random key,
/// supporting an arbitrary content type.
///
/// This version is written using assembly (not even common Unsafe Rust).
/// If your data is [`bytemuck::NoUninit`] (that is, Copy and has no padding), you can
/// also use [`crate::MangledBox`].
///
/// It is recommended to use [`std::clone::CloneToUninit`] to initialize
/// the contents of the box rather than constructing it on stack, since the
/// latter option might leave some trace of value being masked.
pub struct MangledBoxArbitrary<T> {
/// Heap allocation with bytes mangled by XORing with `key`.
data: Box<MaybeUninit<T>>,
/// T-sized buffer containing a cryptographically secure random key.
key: MaybeUninit<T>,
}
impl<T> MangledBoxArbitrary<T> {
// ...
/// Unmangles the contents and invokes the provided closure on it.
/// Whether the closure panics or returns normally, the contents
/// are remangled.
pub fn with_unmangled<F, R>(&mut self, f: F) -> R
where
F: FnOnce(NonNull<T>) -> R,
{
let data_ptr = Box::as_mut_ptr(&mut self.data).cast::<u8>();
let key_ptr = self.key.as_ptr().cast::<u8>();
let data_nn: NonNull<u8> = NonNull::new(data_ptr).unwrap();
// # Safety
// 1. Both pointers point to some `MaybeUninit<T>`, so aligned
// 2. [`data_ptr`] and [`key_ptr`] point to an allocation of at least
// `size_of::<T>()` bytes because they are obtained from references
// to `MaybeUninit<T>`.
// 3. [`data_ptr`] points to heap allocation and [`key_ptr`] to
// stack, therefore they do not overlap.
unsafe {
xor_chunks::<T>(data_ptr, key_ptr);
}
// ... another safety comment here ...
let _guard = RemangleGuard::<T> {
data: data_ptr,
key: key_ptr,
token: PhantomData,
};
f(data_nn.cast())
}
}
xor_chunks::<T> is then calling xor_intrinsic::xor_chunks_intrinsic_baseline::<T>(data, key) which is written in assembly code and mangles the T-sized buffer behind first pointer using the key behind second one.
(To be continued)
3 posts - 1 participant
๐ท๏ธ Rust_feed