insectbox 0.1.0

OpenSSH inspired in-memory key security.
Documentation
use std::alloc::Layout;
use std::ptr::NonNull;

use super::*;

#[cfg(windows)]
use windows_sys::Win32;

#[cfg(unix)]
#[inline]
unsafe fn __alloc(n: usize) -> Option<NonNull<u8>> {
    let layout = Layout::from_size_align_unchecked(n, *PAGE_SIZE);
    NonNull::new(std::alloc::alloc(layout))
}

#[cfg(windows)]
#[inline]
unsafe fn __alloc(n: usize) -> Option<NonNull<u8>> {
    let ptr = Win32::System::Memory::VirtualAlloc(
        ptr::null(),
        *PAGE_SIZE,
        Memory::MEM_COMMIT | Memory::MEM_RESERVE,
        Memory::PAGE_READWRITE,
    ) as *mut u8;
    NonNull::new(ptr)
}

/// Allocate page aligned memory
///
/// In particular `n` bytes starting at some page boundary will be allocated.
/// This function ensures that `n <= isize::MAX` and will return `None` if the
/// condition is not met.
#[must_use]
pub fn alloc(n: usize) -> Option<NonNull<u8>> {
    if n <= isize::MAX as usize {
        unsafe { __alloc(n) }
    } else {
        None
    }
}

#[cfg(unix)]
#[inline]
unsafe fn __free(ptr: *mut u8, n: usize) {
    let layout = Layout::from_size_align_unchecked(n, *PAGE_SIZE);
    std::alloc::dealloc(ptr, layout);
}

#[cfg(windows)]
#[inline]
unsafe fn __free(ptr: *mut u8, _n: usize) {
    Win32::System::Memory::VirtualFree(ptr.cast(), 0, Memory::MEM_RELEASE);
}

/// Free previously allocated memory
///
/// # Safety
/// * `ptr` MUST be aligned to a page boundary
/// * `ptr` MUST come from an allocation made by [`alloc()`]
pub unsafe fn free(ptr: *mut u8, n: usize) {
    __free(ptr, n)
}