use std::mem::{size_of, size_of_val};
use std::ops::{Deref, DerefMut};
use memsec::memzero;
use super::Fr;
pub(crate) const FR_SIZE: usize = size_of::<Fr>();
pub(crate) fn clear_fr(fr_ptr: *const Fr) {
unsafe { memzero(fr_ptr as *mut u8, FR_SIZE) };
}
pub(crate) struct MemRange {
pub ptr: *mut u8,
pub n_bytes: usize,
}
pub(crate) trait ContainsSecret {
fn secret_memory(&self) -> MemRange;
fn zero_secret(&self) {
let MemRange { ptr, n_bytes } = self.secret_memory();
unsafe { memzero(ptr, n_bytes) };
}
}
pub(crate) struct Safe<T: DerefMut>(T);
impl<T> Deref for Safe<T>
where
T: DerefMut,
{
type Target = T::Target;
fn deref(&self) -> &Self::Target {
&*(self.0)
}
}
impl<T> DerefMut for Safe<T>
where
T: DerefMut,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *(self.0)
}
}
impl<T> Drop for Safe<T>
where
T: DerefMut,
{
fn drop(&mut self) {
self.zero_secret();
}
}
impl<T> ContainsSecret for Safe<T>
where
T: DerefMut,
{
fn secret_memory(&self) -> MemRange {
let ptr = &*self.0 as *const T::Target as *mut u8;
let n_bytes = size_of_val(&*self.0);
MemRange { ptr, n_bytes }
}
}
impl<T> Safe<T>
where
T: DerefMut,
{
pub(crate) fn new(x: T) -> Self {
Safe(x)
}
}