use std::fmt;
use std::ptr::copy;
use std::mem::size_of;
use memsec::{
malloc, free,
Prot, unprotected_mprotect
};
pub struct SecKey<T: Sized>(*mut T);
impl<T> SecKey<T> where T: Sized {
pub fn new(t: &T) -> Option<SecKey<T>> {
let memptr = match unsafe { malloc(size_of::<T>()) } {
Some(memptr) => memptr,
None => return None
};
unsafe {
copy(t, memptr, 1);
unprotected_mprotect(memptr, Prot::NoAccess);
}
Some(SecKey(memptr))
}
pub fn read_map<U, F: FnOnce(&T) -> U>(&self, f: F) -> U {
unsafe { unprotected_mprotect(self.0, Prot::ReadOnly) };
let output = f(unsafe { &*self.0 });
unsafe { unprotected_mprotect(self.0, Prot::NoAccess) };
output
}
pub fn write_map<U, F: FnOnce(&mut T) -> U>(&mut self, f: F) -> U {
unsafe { unprotected_mprotect(self.0, Prot::ReadWrite) };
let output = f(unsafe { &mut *self.0 });
unsafe { unprotected_mprotect(self.0, Prot::NoAccess) };
output
}
}
impl<T> From<T> for SecKey<T> {
fn from(t: T) -> SecKey<T> {
SecKey::new(&t).unwrap()
}
}
impl<T> fmt::Debug for SecKey<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", "** sec key **")
}
}
impl<T> Drop for SecKey<T> {
fn drop(&mut self) {
unsafe { free(self.0) }
}
}