#![feature(box_syntax, unique, core_intrinsics)]
#![warn(missing_docs)]
extern crate libc;
use std::ptr::{self, Unique};
use std::{mem, intrinsics, ops, fmt, slice};
pub struct SecBox<T: ?Sized> {
inner: Unique<T>,
}
impl<T: ?Sized> SecBox<T> {
#[inline(always)]
pub fn new(inner: T) -> SecBox<T> where T: Sized {
let res = SecBox {
inner: unsafe { Unique::new(Box::into_raw(box mem::uninitialized::<T>())) },
};
res.memlock();
unsafe {
ptr::write(*res.inner, inner);
}
res
}
pub fn into_inner(self) -> T where T: Sized {
unsafe {
let res = ptr::read(*self.inner);
ptr::write_volatile(*self.inner, mem::zeroed());
self.memunlock();
res
}
}
fn memlock(&self) {
unsafe {
libc::mlock(&**self as *const T as *const libc::c_void,
mem::size_of_val(&**self) as libc::size_t);
};
}
fn memunlock(&self) {
unsafe {
libc::munlock(&**self as *const T as *const libc::c_void,
mem::size_of_val(&**self) as libc::size_t);
};
}
}
impl<T: ?Sized + Clone> Clone for SecBox<T> {
fn clone(&self) -> SecBox<T> {
unsafe {
let mut bx = SecBox::new(mem::uninitialized::<T>());
bx.clone_from(self);
bx
}
}
fn clone_from(&mut self, src: &SecBox<T>) {
(&mut **self).clone_from(src);
}
}
impl<T: ?Sized> From<Box<T>> for SecBox<T> {
fn from(from: Box<T>) -> SecBox<T> {
let res = SecBox {
inner: unsafe { Unique::new(Box::into_raw(from)) },
};
res.memlock();
res
}
}
impl<T: ?Sized> ops::Deref for SecBox<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.inner.get() }
}
}
impl<T: ?Sized> ops::DerefMut for SecBox<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { self.inner.get_mut() }
}
}
impl<T: ?Sized> fmt::Display for SecBox<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "*******")
}
}
impl<T: ?Sized> fmt::Debug for SecBox<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "*******")
}
}
impl<T: ?Sized> Drop for SecBox<T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(*self.inner);
intrinsics::volatile_set_memory(*self.inner as *mut u8, 0, mem::size_of_val(&**self));
let _buf = Box::from_raw(slice::from_raw_parts_mut(*self.inner as *mut u8, mem::size_of_val(&**self)));
self.memunlock();
}
}
}
#[cfg(test)]
mod test;