flex_alloc_secure/
protect.rs1use core::any::type_name;
2use core::fmt;
3use core::mem::MaybeUninit;
4use core::ops;
5use core::ptr;
6
7use rand_core::RngCore;
8use zeroize::{DefaultIsZeroes, Zeroize};
9
10use crate::boxed::SecureBox;
11use crate::bytes::FillBytes;
12
13pub trait ExposeProtected {
19 type Target: ?Sized;
21
22 fn expose_read<F>(&self, f: F)
24 where
25 F: FnOnce(SecureRef<&Self::Target>);
26
27 fn expose_write<F>(&mut self, f: F)
29 where
30 F: FnOnce(SecureRef<&mut Self::Target>);
31
32 fn unprotect(self) -> SecureBox<Self::Target>;
34}
35
36pub trait ProtectedInit: ExposeProtected + From<SecureBox<Self::Target>> + Sized {
38 fn init<F>(f: F) -> Self
42 where
43 F: FnOnce(SecureRef<&mut Self::Target>),
44 Self::Target: Copy + FillBytes,
45 {
46 let mut boxed = unsafe { SecureBox::<Self::Target>::new_uninit().assume_init() };
47 f(SecureRef::new_mut(boxed.as_mut()));
48 boxed.into()
49 }
50
51 fn init_default<F>(f: F) -> Self
55 where
56 F: FnOnce(SecureRef<&mut Self::Target>),
57 Self::Target: Default,
58 {
59 let mut boxed = SecureBox::<Self::Target>::default();
60 f(SecureRef::new_mut(boxed.as_mut()));
61 boxed.into()
62 }
63
64 fn init_random<F>(rng: impl RngCore, f: F) -> Self
68 where
69 F: FnOnce(SecureRef<&mut Self::Target>),
70 Self::Target: Copy + FillBytes,
71 {
72 let mut boxed = SecureBox::<Self::Target>::new_uninit();
73 boxed.fill_random(rng);
74 let mut boxed = unsafe { boxed.assume_init() };
75 f(SecureRef::new_mut(boxed.as_mut()));
76 boxed.into()
77 }
78
79 fn init_take<F>(from: &mut Self::Target, f: F) -> Self
83 where
84 F: FnOnce(SecureRef<&mut Self::Target>),
85 Self::Target: DefaultIsZeroes,
86 {
87 let boxed = SecureBox::new_uninit();
88 let mut boxed = SecureBox::write(boxed, *from);
89 from.zeroize();
90 f(SecureRef::new_mut(boxed.as_mut()));
91 boxed.into()
92 }
93
94 #[inline(always)]
97 fn init_with<F>(f: F) -> Self
98 where
99 F: FnOnce() -> Self::Target,
100 Self::Target: Sized,
101 {
102 let boxed = SecureBox::new_uninit();
103 SecureBox::write(boxed, f()).into()
104 }
105
106 #[inline(always)]
110 fn try_init_with<F, E>(f: F) -> Result<Self, E>
111 where
112 F: FnOnce() -> Result<Self::Target, E>,
113 Self::Target: Sized,
114 {
115 let boxed = SecureBox::new_uninit();
116 Ok(SecureBox::write(boxed, f()?).into())
117 }
118
119 fn random(rng: impl RngCore) -> Self
121 where
122 Self::Target: Copy + FillBytes,
123 {
124 Self::init_random(rng, |_| ())
125 }
126
127 fn take(from: &mut Self::Target) -> Self
130 where
131 Self::Target: DefaultIsZeroes,
132 {
133 Self::init_take(from, |_| ())
134 }
135}
136
137impl<T, W> ProtectedInit for W where W: From<SecureBox<T>> + ExposeProtected<Target = T> {}
138
139pub trait ProtectedInitSlice:
141 ExposeProtected<Target = [Self::Item]> + From<SecureBox<[Self::Item]>> + Sized
142{
143 type Item;
145
146 fn init_slice<F>(len: usize, f: F) -> Self
150 where
151 F: FnOnce(SecureRef<&mut [Self::Item]>),
152 Self::Item: Copy + FillBytes,
153 {
154 let mut boxed = unsafe { SecureBox::<[Self::Item]>::new_uninit_slice(len).assume_init() };
155 f(SecureRef::new_mut(boxed.as_mut()));
156 boxed.into()
157 }
158
159 fn init_default_slice<F>(len: usize, f: F) -> Self
163 where
164 F: FnOnce(SecureRef<&mut [Self::Item]>),
165 Self::Item: Default,
166 {
167 let mut boxed = SecureBox::<[Self::Item]>::new_uninit_slice(len);
168 boxed
169 .as_mut()
170 .fill_with(|| MaybeUninit::new(Default::default()));
171 let mut boxed = unsafe { boxed.assume_init() };
172 f(SecureRef::new_mut(boxed.as_mut()));
173 boxed.into()
174 }
175
176 fn init_random_slice<F>(len: usize, rng: impl RngCore, f: F) -> Self
180 where
181 F: FnOnce(SecureRef<&mut [Self::Item]>),
182 Self::Item: Copy + FillBytes,
183 {
184 let mut boxed = SecureBox::<[Self::Item]>::new_uninit_slice(len);
185 boxed.fill_random(rng);
186 let mut boxed = unsafe { boxed.assume_init() };
187 f(SecureRef::new_mut(boxed.as_mut()));
188 boxed.into()
189 }
190
191 fn init_take_slice<F>(from: &mut [Self::Item], f: F) -> Self
195 where
196 F: FnOnce(SecureRef<&mut [Self::Item]>),
197 Self::Item: DefaultIsZeroes,
198 {
199 let len = from.len();
200 let mut boxed = SecureBox::<[Self::Item]>::new_uninit_slice(len);
201 unsafe {
202 ptr::copy_nonoverlapping(
203 from.as_ptr(),
204 boxed.as_mut().as_mut_ptr() as *mut Self::Item,
205 len,
206 )
207 };
208 from.zeroize();
209 let mut boxed = unsafe { boxed.assume_init() };
210 f(SecureRef::new_mut(boxed.as_mut()));
211 boxed.into()
212 }
213
214 fn random_slice(len: usize, rng: impl RngCore) -> Self
216 where
217 Self::Item: Copy + FillBytes,
218 {
219 Self::init_random_slice(len, rng, |_| ())
220 }
221
222 fn take_slice(from: &mut [Self::Item]) -> Self
225 where
226 Self::Item: DefaultIsZeroes,
227 {
228 Self::init_take_slice(from, |_| ())
229 }
230}
231
232impl<T, W> ProtectedInitSlice for W
233where
234 W: From<SecureBox<[T]>> + ExposeProtected<Target = [T]>,
235{
236 type Item = T;
237}
238
239pub struct SecureRef<T: ?Sized>(T);
241
242impl<'a, T: ?Sized> SecureRef<&'a T> {
243 pub(crate) fn new(inner: &'a T) -> Self {
244 Self(inner)
245 }
246}
247
248impl<'a, T: ?Sized> SecureRef<&'a mut T> {
249 pub(crate) fn new_mut(inner: &'a mut T) -> Self {
250 Self(inner)
251 }
252}
253
254impl<'a, T> SecureRef<&'a mut MaybeUninit<T>> {
255 #[inline]
260 pub unsafe fn assume_init(self) -> SecureRef<&'a mut T> {
261 SecureRef(self.0.assume_init_mut())
262 }
263
264 #[inline(always)]
267 pub fn write(slf: Self, value: T) -> SecureRef<&'a mut T> {
268 slf.0.write(value);
269 SecureRef(unsafe { slf.0.assume_init_mut() })
270 }
271}
272
273impl<T: ?Sized> AsRef<T> for SecureRef<&'_ T> {
274 #[inline]
275 fn as_ref(&self) -> &T {
276 self.0
277 }
278}
279
280impl<T: ?Sized> AsRef<T> for SecureRef<&'_ mut T> {
281 #[inline]
282 fn as_ref(&self) -> &T {
283 self.0
284 }
285}
286
287impl<T: ?Sized> AsMut<T> for SecureRef<&'_ mut T> {
288 #[inline]
289 fn as_mut(&mut self) -> &mut T {
290 self.0
291 }
292}
293
294impl<T: ?Sized> fmt::Debug for SecureRef<T> {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 f.write_fmt(format_args!("ProtectedRef<{}>", type_name::<T>()))
297 }
298}
299
300impl<T: ?Sized> ops::Deref for SecureRef<&'_ T> {
301 type Target = T;
302
303 #[inline]
304 fn deref(&self) -> &T {
305 self.0
306 }
307}
308
309impl<T: ?Sized> ops::Deref for SecureRef<&'_ mut T> {
310 type Target = T;
311
312 #[inline]
313 fn deref(&self) -> &Self::Target {
314 self.0
315 }
316}
317
318impl<T: ?Sized> ops::DerefMut for SecureRef<&'_ mut T> {
319 fn deref_mut(&mut self) -> &mut Self::Target {
320 self.0
321 }
322}