Skip to content

Commit cdd0dd6

Browse files
committed
Implement ZeroizeOnDrop for the output of buffer_ct_variable
This is a breaking change in that the generated `struct` now implements `Drop` and cannot be destructured, hence the addition of `.clone()` calls inside `decompose`, but callers of this macro could also directly perform this destructuring prior. The fields aren't `pub`, so only the immediate caller's scope could, so this may be so slight/internal it's a non-issue? It depends on if the layout of the generated struct, whose internals are intended to be accessed through the `CoreProxy` trait, is considered to be part of the public API or not. This allows `blake2::Blake2b: ZeroizeOnDrop`.
1 parent 1c96506 commit cdd0dd6

File tree

1 file changed

+68
-3
lines changed

1 file changed

+68
-3
lines changed

digest/src/buffer_macros/variable.rs

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/// Creates a buffered wrapper around block-level "core" type which implements variable output size traits
22
/// with output size selected at compile time.
3+
#[doc(hidden)]
34
#[macro_export]
4-
macro_rules! buffer_ct_variable {
5+
macro_rules! buffer_ct_variable_internal {
56
(
67
$(#[$attr:meta])*
78
$vis:vis struct $name:ident<$out_size:ident>($core_ty:ty);
@@ -116,8 +117,7 @@ macro_rules! buffer_ct_variable {
116117
Self { core, buffer }
117118
}
118119
fn decompose(self) -> (Self::Core, $crate::block_api::Buffer<Self::Core>) {
119-
let Self { core, buffer } = self;
120-
(core, buffer)
120+
(self.core.clone(), self.buffer.clone())
121121
}
122122
}
123123

@@ -209,3 +209,68 @@ macro_rules! buffer_ct_variable {
209209
}
210210
};
211211
}
212+
213+
#[doc(hidden)]
214+
#[cfg(not(feature = "zeroize"))]
215+
#[macro_export]
216+
macro_rules! buffer_ct_variable_zeroize_on_drop {
217+
($name:ident, $out_size:ident, $max_size:ty) => {
218+
impl<$out_size> Drop for $name<$out_size>
219+
where
220+
$out_size: $crate::array::ArraySize
221+
+ $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
222+
{
223+
fn drop(&mut self) {}
224+
}
225+
};
226+
}
227+
228+
#[doc(hidden)]
229+
#[cfg(feature = "zeroize")]
230+
#[macro_export]
231+
macro_rules! buffer_ct_variable_zeroize_on_drop {
232+
($name:ident, $out_size:ident, $max_size:ty) => {
233+
impl<$out_size> Drop for $name<$out_size>
234+
where
235+
$out_size: $crate::array::ArraySize
236+
+ $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>,
237+
{
238+
fn drop(&mut self) {
239+
let Self { core, buffer } = self;
240+
// Ensure these types implement `ZeroizeOnDrop` and therefore we have no work to do
241+
fn implements_zeroize_on_drop(_value: &mut impl $crate::zeroize::ZeroizeOnDrop) {}
242+
implements_zeroize_on_drop(core);
243+
implements_zeroize_on_drop(buffer);
244+
}
245+
}
246+
impl<$out_size> $crate::zeroize::ZeroizeOnDrop for $name<$out_size> where
247+
$out_size: $crate::array::ArraySize
248+
+ $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>
249+
{
250+
}
251+
};
252+
}
253+
254+
/// Creates a buffered wrapper around block-level "core" type which implements variable output size traits
255+
/// with output size selected at compile time.
256+
#[macro_export]
257+
macro_rules! buffer_ct_variable {
258+
(
259+
$(#[$attr:meta])*
260+
$vis:vis struct $name:ident<$out_size:ident>($core_ty:ty);
261+
exclude: SerializableState;
262+
// Ideally, we would use `$core_ty::OutputSize`, but unfortunately the compiler
263+
// does not accept such code. The likely reason is this issue:
264+
// https://github.com/rust-lang/rust/issues/79629
265+
max_size: $max_size:ty;
266+
) => {
267+
$crate::buffer_ct_variable_internal!(
268+
$(#[$attr])*
269+
$vis struct $name<$out_size>($core_ty);
270+
exclude: SerializableState;
271+
max_size: $max_size;
272+
);
273+
274+
$crate::buffer_ct_variable_zeroize_on_drop!($name, $out_size, $max_size);
275+
}
276+
}

0 commit comments

Comments
 (0)