pub struct SipHashMAC { /* private fields */ }Expand description
SipHash-1-3 keyed MAC over the (next_idx, slot_addr) pair.
The 16-byte key is initialized once at Slab construction. On std
builds use SipHashMAC::new to seed; in no_std contexts use
SipHashMAC::with_key and supply entropy from a hardware RNG or
boot-time source.
§Threat model and limitations
MAC width — 32 bits. The MAC type is u32 (matches the on-disk
FreeLink layout in Slab’s freelist — FreeLink is private to
the slab module). 32-bit MACs give a blind-forgery probability of
2^-32 per guess. Widening to 64 bits requires changing
FreelistProtection::sign/verify to u64 and growing FreeLink
by 4 bytes per slot (4–25% size overhead depending on T). For
applications that need stronger guarantees, use PacMAC on aarch64
(hardware-backed pointer-authentication signature) once its
instruction-level implementation is complete (currently a stub).
MAC-failure behavior in Slab. Today, a MAC mismatch (or a
next_idx > capacity defense-in-depth tripwire) causes Slab to
abandon the in-band freelist (*head_ptr = 0) and fall through
to a fresh allocation from next_uncarved. The attacker-controlled
link chain is torn down — they cannot navigate the slab to a chosen
address — but the event is not propagated to the caller as an
error, and Quarantine (when composed) does not see it: the
allocate call returns Ok with a slot carved from the uncorrupted
uncarved region. Debug builds additionally panic via
debug_assert! so the regression surfaces in tests. For loud-fail-
on-corruption semantics in production, the slot the attacker
poisoned is leaked until slab drop — no slot is handed back to the
caller from the corrupted chain. MAC-failure events are counted by
the allocator and exposed via crate::Allocator::corruption_events;
operators can monitor that counter to detect silent disarms at scale.
Truncation in SipHashMAC::mac (private): we take the low 32 bits of the
SipHash-1-3 output. This is uniform random across forgeries provided
the SipHash construction is sound (it is), so collision probability
is 2^-32 per blind guess regardless of which 32 bits we keep.
Entropy source for SipHashMAC::new: std’s
HashMap::RandomState. This goes through the same OS RNG path that
hardens stdlib’s HashMap against algorithmic-complexity DoS — on
Linux/macOS/Windows it draws from getrandom/arc4random/RtlGenRandom
respectively. For deployments that mandate getrandom directly
(FIPS-flow audit trail, no-HashMap-dep environments, or pre-stdlib
init paths), supply the key via SipHashMAC::with_key and source
the bytes from your project’s existing CSPRNG. The dep is intentionally
not added to this crate to keep the no_std footprint minimal.
Implementations§
Source§impl SipHashMAC
impl SipHashMAC
Sourcepub const fn with_key(key: [u8; 16]) -> SipHashMAC
pub const fn with_key(key: [u8; 16]) -> SipHashMAC
Construct with an explicit 16-byte key. Suitable for no_std.
Sourcepub fn new() -> SipHashMAC
pub fn new() -> SipHashMAC
Seed from the OS entropy source.
Trait Implementations§
Source§impl Clone for SipHashMAC
Available on crate feature siphasher only.Manual Clone with per-byte volatile copy — the derived Clone
lowered to a memcpy that the optimizer was free to coalesce, fuse
with surrounding writes, or vectorize through registers, leaving
transient byte-aligned copies of the key in caller stack frames
outside the original key slot (which Drop then could not
zeroize). The manual loop forces each byte through a volatile
load/store pair, defeating that smear.
impl Clone for SipHashMAC
siphasher only.Manual Clone with per-byte volatile copy — the derived Clone
lowered to a memcpy that the optimizer was free to coalesce, fuse
with surrounding writes, or vectorize through registers, leaving
transient byte-aligned copies of the key in caller stack frames
outside the original key slot (which Drop then could not
zeroize). The manual loop forces each byte through a volatile
load/store pair, defeating that smear.
The compiler_fence at the end prevents the optimizer from
reordering subsequent code into the middle of the copy and from
fusing the writes with later non-volatile stores.
Source§fn clone(&self) -> SipHashMAC
fn clone(&self) -> SipHashMAC
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SipHashMAC
Available on crate feature siphasher only.
impl Debug for SipHashMAC
siphasher only.Source§impl Default for SipHashMAC
Available on crate features siphasher and std only.
impl Default for SipHashMAC
siphasher and std only.Source§fn default() -> SipHashMAC
fn default() -> SipHashMAC
Source§impl Drop for SipHashMAC
Available on crate feature siphasher only.Zeroize the key on drop so cloned instances don’t leave the secret
in deallocated stack frames after a typed slab tears down.
impl Drop for SipHashMAC
siphasher only.Zeroize the key on drop so cloned instances don’t leave the secret in deallocated stack frames after a typed slab tears down.
Note: Copy is not derived (a typed slab takes the MAC by value
at construction; explicit .clone() is required to install the same
key in two slabs — that’s the intended security posture, and it lets
us implement Drop to zeroize).
§Caveats — when Drop does not run
Drop-based zeroize protects only against keys that leave scope. It does not fire for:
static SipHashMAC/OnceCell<SipHashMAC>— process- lifetime statics never drop; the key persists until the process exits, observable via core dumps or/proc/<pid>/memreads. Construct on the stack inside the function that uses it (e.g. a per-request slab) where the natural scope-exit fires Drop.panic = "abort"builds (and theQuarantineabort-on-corruption path) — Drop is skipped on abort; if aSipHashMAC-using slab is live at the time, its key remains in freed-but-unmapped memory until the OS reclaims the address space. The OS-level free isn’t observable by other processes, but a same-process attacker who triggered the abort can still peek at the bytes if the abort handler reads memory before teardown.mem::forget(slab)orBox::leakon a slab containing the MAC — explicit destructor suppression. Don’t combine these with security-critical wrappers.
Source§impl FreelistProtection for SipHashMAC
Available on crate feature siphasher only.
impl FreelistProtection for SipHashMAC
siphasher only.Source§fn sign(&self, next_idx: u32, slot_addr: usize) -> u32
fn sign(&self, next_idx: u32, slot_addr: usize) -> u32
next_idx is the 1-based slot index being
stored, or 0 for the end-of-list sentinel (so the input range
is 0..=u32::MAX). slot_addr is the virtual address of the slot
containing the link (used as a nonce so that a copy of a freelist
link to a different slot won’t verify).