redoubt_zero_core/
collections.rs1use alloc::string::String;
7use alloc::vec::Vec;
8
9use core::sync::atomic::{Ordering, compiler_fence};
10
11use super::traits::{FastZeroizable, ZeroizationProbe, ZeroizeMetadata};
12
13#[inline(always)]
18pub fn to_fast_zeroizable_dyn_mut<'a, T: FastZeroizable>(
19 x: &'a mut T,
20) -> &'a mut (dyn FastZeroizable + 'a) {
21 x
22}
23
24#[inline(always)]
29pub fn to_zeroization_probe_dyn_ref<'a, T: ZeroizationProbe>(
30 x: &'a T,
31) -> &'a (dyn ZeroizationProbe + 'a) {
32 x
33}
34
35pub fn zeroize_collection(collection_iter: &mut dyn Iterator<Item = &mut dyn FastZeroizable>) {
39 for z in collection_iter {
40 z.fast_zeroize();
41 compiler_fence(Ordering::SeqCst);
42 }
43}
44
45pub fn collection_zeroed(collection_iter: &mut dyn Iterator<Item = &dyn ZeroizationProbe>) -> bool {
49 for z in collection_iter {
50 if !z.is_zeroized() {
51 return false;
52 }
53 }
54
55 true
56}
57
58#[inline(always)]
68pub(crate) fn slice_fast_zeroize<T: FastZeroizable + ZeroizeMetadata>(slice: &mut [T], fast: bool) {
69 if fast {
70 redoubt_util::fast_zeroize_slice(slice);
72 compiler_fence(Ordering::SeqCst);
73 } else {
74 for elem in slice.iter_mut() {
76 elem.fast_zeroize();
77 compiler_fence(Ordering::SeqCst);
78 }
79 }
80}
81
82impl<T> ZeroizeMetadata for [T]
83where
84 T: FastZeroizable + ZeroizeMetadata,
85{
86 const CAN_BE_BULK_ZEROIZED: bool = T::CAN_BE_BULK_ZEROIZED;
87}
88
89impl<T> FastZeroizable for [T]
90where
91 T: FastZeroizable + ZeroizeMetadata,
92{
93 fn fast_zeroize(&mut self) {
94 slice_fast_zeroize(self, T::CAN_BE_BULK_ZEROIZED);
95 }
96}
97
98impl<T> ZeroizationProbe for [T]
99where
100 T: ZeroizeMetadata + FastZeroizable + ZeroizationProbe,
101{
102 fn is_zeroized(&self) -> bool {
103 collection_zeroed(&mut self.iter().map(to_zeroization_probe_dyn_ref))
104 }
105}
106
107impl<T: ZeroizeMetadata, const N: usize> ZeroizeMetadata for [T; N] {
118 const CAN_BE_BULK_ZEROIZED: bool = T::CAN_BE_BULK_ZEROIZED;
120}
121
122impl<T: ZeroizeMetadata + FastZeroizable, const N: usize> FastZeroizable for [T; N] {
123 #[inline(always)]
124 fn fast_zeroize(&mut self) {
125 slice_fast_zeroize(self, T::CAN_BE_BULK_ZEROIZED);
126 }
127}
128
129impl<T, const N: usize> ZeroizationProbe for [T; N]
130where
131 T: ZeroizationProbe,
132{
133 fn is_zeroized(&self) -> bool {
134 collection_zeroed(&mut self.iter().map(to_zeroization_probe_dyn_ref))
135 }
136}
137
138#[inline(always)]
149pub(crate) fn vec_fast_zeroize<T: FastZeroizable + ZeroizeMetadata>(vec: &mut Vec<T>, fast: bool) {
150 if fast {
151 redoubt_util::fast_zeroize_vec(vec);
153 compiler_fence(Ordering::SeqCst);
154 } else {
155 for elem in vec.iter_mut() {
157 elem.fast_zeroize();
158 compiler_fence(Ordering::SeqCst);
159 }
160 redoubt_util::zeroize_spare_capacity(vec);
161 compiler_fence(Ordering::SeqCst);
162 }
163}
164
165impl<T: ZeroizeMetadata> ZeroizeMetadata for Vec<T> {
166 const CAN_BE_BULK_ZEROIZED: bool = false;
168}
169
170impl<T: ZeroizeMetadata + FastZeroizable> FastZeroizable for Vec<T> {
171 #[inline(always)]
172 fn fast_zeroize(&mut self) {
173 vec_fast_zeroize(self, T::CAN_BE_BULK_ZEROIZED);
174 }
175}
176
177impl<T> ZeroizationProbe for Vec<T>
178where
179 T: ZeroizationProbe,
180{
181 fn is_zeroized(&self) -> bool {
189 collection_zeroed(&mut self.iter().map(to_zeroization_probe_dyn_ref))
191 && redoubt_util::is_spare_capacity_zeroized(self)
192 }
193}
194
195impl ZeroizeMetadata for String {
199 const CAN_BE_BULK_ZEROIZED: bool = false;
201}
202
203impl FastZeroizable for String {
204 #[inline(always)]
205 fn fast_zeroize(&mut self) {
206 unsafe {
209 let vec_bytes = self.as_mut_vec();
210 redoubt_util::fast_zeroize_vec(vec_bytes);
211 }
212 }
213}
214
215impl ZeroizationProbe for String {
216 fn is_zeroized(&self) -> bool {
217 redoubt_util::is_slice_zeroized(self.as_bytes())
218 }
219}
220
221impl<T: ZeroizeMetadata + FastZeroizable> ZeroizeMetadata for alloc::boxed::Box<T> {
223 const CAN_BE_BULK_ZEROIZED: bool = T::CAN_BE_BULK_ZEROIZED;
224}
225
226impl<T: FastZeroizable> FastZeroizable for alloc::boxed::Box<T> {
227 #[inline(always)]
228 fn fast_zeroize(&mut self) {
229 (**self).fast_zeroize();
230 }
231}
232
233impl<T: ZeroizationProbe> ZeroizationProbe for alloc::boxed::Box<T> {
234 fn is_zeroized(&self) -> bool {
235 (**self).is_zeroized()
236 }
237}
238
239impl<T: ZeroizeMetadata + FastZeroizable> ZeroizeMetadata for Option<T> {
242 const CAN_BE_BULK_ZEROIZED: bool = false;
243}
244
245impl<T: FastZeroizable> FastZeroizable for Option<T> {
246 #[inline(always)]
247 fn fast_zeroize(&mut self) {
248 if let Some(val) = self {
249 val.fast_zeroize();
250 }
251 *self = None;
253 }
254}
255
256impl<T: ZeroizationProbe> ZeroizationProbe for Option<T> {
257 fn is_zeroized(&self) -> bool {
258 match self {
259 Some(val) => val.is_zeroized(),
260 None => true, }
262 }
263}