pub struct SecretPool<const N: usize, const SLOTS: usize> { /* private fields */ }Expand description
Fixed-slot arena for many same-size secrets inside one locked mapping.
SecretPool<N, SLOTS> amortizes platform memory-locking overhead when
an application needs many fixed-size secrets at once. Instead of using
one locked page-backed mapping per secret, the pool creates one private
locked mapping large enough for SLOTS slots of N bytes and hands out
lifetime-bound SecretPoolSlot handles.
Slots borrow the pool, so Rust prevents the pool from being dropped while a slot is still live. Dropping a slot volatile-clears exactly that slot and returns it to the pool. Dropping the pool volatile-clears the full mapping before unlocking and releasing it.
use sanitization::SecretPool;
let pool = SecretPool::<32, 4>::new().unwrap();
let slot = pool.try_allocate().unwrap().unwrap();
drop(pool); // rejected: `slot` still borrows the pool
drop(slot);Implementations§
Source§impl<const N: usize, const SLOTS: usize> SecretPool<N, SLOTS>
impl<const N: usize, const SLOTS: usize> SecretPool<N, SLOTS>
Sourcepub fn new() -> Result<Self, MemoryLockError>
pub fn new() -> Result<Self, MemoryLockError>
Create a locked pool with SLOTS fixed-size slots of N bytes.
This performs one platform mapping and one platform lock operation for the whole arena. The requested mapping length is rounded to the platform page granule, so the pool also clears padding bytes on drop.
Sourcepub fn new_hardened_native() -> Result<Self, ProtectionError>
pub fn new_hardened_native() -> Result<Self, ProtectionError>
Create a locked pool with the profile-hardened-native policy.
Preferred dump and fork exclusion outcomes remain visible through
SecretPool::protection_report.
Sourcepub fn new_hardened_linux() -> Result<Self, ProtectionError>
pub fn new_hardened_linux() -> Result<Self, ProtectionError>
Create a locked pool with the profile-hardened-linux policy.
Sourcepub fn new_with_protection(
request: ProtectionRequest,
) -> Result<Self, ProtectionError>
pub fn new_with_protection( request: ProtectionRequest, ) -> Result<Self, ProtectionError>
Create a pool under an explicit runtime protection policy.
Sourcepub const fn capacity_slots(&self) -> usize
pub const fn capacity_slots(&self) -> usize
Number of slots in the pool.
Sourcepub const fn locked_len(&self) -> usize
pub const fn locked_len(&self) -> usize
Rounded platform mapping length locked by this pool.
Sourcepub const fn protection_report(&self) -> &ProtectionReport
pub const fn protection_report(&self) -> &ProtectionReport
Actual runtime protections established for the pool mapping.
Sourcepub const fn protection_request(&self) -> ProtectionRequest
pub const fn protection_request(&self) -> ProtectionRequest
Runtime protection policy requested for the pool mapping.
Sourcepub const fn is_memory_locked(&self) -> bool
pub const fn is_memory_locked(&self) -> bool
Returns true when the pool mapping is locked against ordinary paging.
Sourcepub fn available_slots(&self) -> usize
pub fn available_slots(&self) -> usize
Count slots that are currently available.
This is a point-in-time observation. Other threads may allocate or release slots immediately after this method returns.
Sourcepub fn quarantined_slots(&self) -> usize
pub fn quarantined_slots(&self) -> usize
Count slots permanently withheld after an integrity failure.
This is public operational metadata. It does not expose mapping addresses, canary values, or secret bytes.
Sourcepub fn arena_report(&self) -> SecretPoolReport
pub fn arena_report(&self) -> SecretPoolReport
Capture fixed-arena capacity, utilization, and lock-overhead metadata.
live_slots is a point-in-time observation. Other threads may allocate
or release slots immediately after this method returns.
Sourcepub fn try_allocate(
&self,
) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, MemoryLockError>
pub fn try_allocate( &self, ) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, MemoryLockError>
Allocate one unused slot from the pool and report random-canary setup errors explicitly.
Ok(None) means only that every non-quarantined slot is in use.
Random-canary setup failures are returned as MemoryLockError.
Sourcepub fn try_allocate_from_slice(
&self,
source: &[u8],
) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, PoolInitError>
pub fn try_allocate_from_slice( &self, source: &[u8], ) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, PoolInitError>
Allocate a slot and copy bytes from a same-length slice.
Returns Ok(None) when the pool is full. A length mismatch returns
an error without allocating a slot.
Sourcepub fn try_allocate_from_array(
&self,
bytes: [u8; N],
) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, PoolInitError>
pub fn try_allocate_from_array( &self, bytes: [u8; N], ) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, PoolInitError>
Allocate a slot, copy an owned array into it, then clear this function’s owned array parameter. Other caller-retained copies are unaffected.
Ok(None) means only that the pool is exhausted. Platform setup and
integrity failures remain distinct errors.
Sourcepub fn try_allocate_from_fn<E>(
&self,
make_byte: impl FnMut(usize) -> Result<u8, E>,
) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, SecretPoolGenerateError<E>>
pub fn try_allocate_from_fn<E>( &self, make_byte: impl FnMut(usize) -> Result<u8, E>, ) -> Result<Option<SecretPoolSlot<'_, N, SLOTS>>, SecretPoolGenerateError<E>>
Allocate a slot and fallibly generate each byte directly inside it.
If generation fails, the partially initialized slot is volatile-cleared and returned to the pool before the error is returned.
Sourcepub fn secure_clear(&mut self)
pub fn secure_clear(&mut self)
Clear the full locked mapping and mark every slot available.
This requires &mut self, so Rust prevents it while any live slot
handle still borrows the pool.