diff --git a/zeroize/CHANGELOG.md b/zeroize/CHANGELOG.md index 5b60a039..13f4cba1 100644 --- a/zeroize/CHANGELOG.md +++ b/zeroize/CHANGELOG.md @@ -5,10 +5,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## 1.9.0 (unreleased) +### Added +- `optimization_barrier` function ([#1261]) + ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) [#1149]: https://github.com/RustCrypto/utils/pull/1149 +[#1261]: https://github.com/RustCrypto/utils/pull/1261 ## 1.8.2 (2025-09-29) ### Changed diff --git a/zeroize/src/barrier.rs b/zeroize/src/barrier.rs index abc8e600..ae297e3b 100644 --- a/zeroize/src/barrier.rs +++ b/zeroize/src/barrier.rs @@ -11,12 +11,18 @@ /// implemented using `#[inline(never)]` and `read_volatile`. /// /// # Examples -/// ```ignore +/// ``` /// use core::num::NonZeroU32; /// use zeroize::{ZeroizeOnDrop, zeroize_flat_type}; /// +/// # type ThirdPartyType = u32; +/// /// struct DataToZeroize { /// buf: [u8; 32], +/// // `ThirdPartyType` can be a type with private fields +/// // defined in a third-party crate and which does not implement +/// // `Zeroize` or zeroization on drop. +/// data: ThirdPartyType, /// pos: NonZeroU32, /// } /// @@ -25,6 +31,7 @@ /// impl Drop for DataToZeroize { /// fn drop(&mut self) { /// self.buf = [0u8; 32]; +/// self.data = ThirdPartyType::default(); /// self.pos = NonZeroU32::new(32).unwrap(); /// zeroize::optimization_barrier(self); /// } @@ -34,12 +41,16 @@ /// /// let mut data = DataToZeroize { /// buf: [3u8; 32], +/// data: ThirdPartyType::default(), /// pos: NonZeroU32::new(32).unwrap(), /// }; /// /// // data gets zeroized when dropped /// ``` -pub(crate) fn optimization_barrier(val: &T) { +/// +/// Note that erasure of `ThirdPartyType` demonstrated above can be fragile if it contains +/// `MaybeUninit` or `union` data. It also does not perform erasure of types like `Box` or `Vec`. +pub fn optimization_barrier(val: &T) { #[cfg(all( not(miri), any( diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 4b571abe..e2662c2e 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -251,7 +251,7 @@ mod aarch64; mod x86; mod barrier; -use barrier::optimization_barrier; +pub use barrier::optimization_barrier; use core::{ marker::{PhantomData, PhantomPinned}, diff --git a/zeroize/tests/alloc.rs b/zeroize/tests/alloc.rs index 677a914a..99df9518 100644 --- a/zeroize/tests/alloc.rs +++ b/zeroize/tests/alloc.rs @@ -42,9 +42,32 @@ impl Drop for SecretBox { } #[test] -fn proxy_alloc_test() { +fn secret_box_alloc_test() { let b1 = SecretBox::new([u128::MAX; 10]); core::hint::black_box(&b1); let b2 = SecretBox::new([u8::MAX; 160]); core::hint::black_box(&b2); } + +struct ObserveSecretBox(Box); + +impl ObserveSecretBox { + fn new(val: S) -> Self { + Self(Box::new(val)) + } +} + +impl Drop for ObserveSecretBox { + fn drop(&mut self) { + *self.0 = Default::default(); + zeroize::optimization_barrier(&self); + } +} + +#[test] +fn observe_secret_box_alloc_test() { + let b1 = ObserveSecretBox::new([u128::MAX; 10]); + core::hint::black_box(&b1); + let b2 = SecretBox::new([u8::MAX; 160]); + core::hint::black_box(&b2); +}