sec-mem 0.1.1

High-assurance, attack-resistant cryptographic memory allocator and hardware-enforced secret container
Documentation

SecMem - Secretes Memory Protection

Crates.io Documentation License: MIT/Apache

SecMem is a high-assurance, attack-resistant cryptographic memory allocator for Rust. It provides two secure container types designed to aggressively protect sensitive data (cryptographic keys, passwords, PII) in memory from OS-level exploits, memory dumping, buffer overflows, and side-channel attacks.

Feature Flags

Feature Description Default
sec_mem Enables SecMem, the OS-level memory hardening container. Requires libc and Linux. Yes
encryption Enables ChaCha20/XOR-blinded encrypt-at-rest for SecMem. Stores the master key in memfd_secret. Yes
key_shielding Enables OpenSSH-style 16 KiB pre-key blake3 derivation to heavily defend against side-channels. No

(Note: SecretBox is always available and fully no_std compatible, regardless of features).

Core Protections

1. SecMem<S> (Hardware-Accelerated OS Hardening)

The primary secure container leveraging deep OS integration and hardware capabilities for maximum security.

  • XOR-Blinded Encrypt-at-Rest: Secrets are transparently ChaCha20 encrypted at rest in RAM using a 2-of-2 secret sharing scheme. The master key is stored in a pointerless kernel blind spot (memfd_secret), making the ciphertext in RAM mathematically useless to an attacker even if they dump the process memory or read /proc/self/mem.
  • Key Shielding (Optional): If the key_shielding feature is enabled, it implements OpenSSH-style Key Shielding by splitting a massive 16 KiB pre-key buffer into two XOR parts. During access, it dynamically reconstructs the 16 KiB buffer and derives the final key via blake3 hashing. This mathematical complexity actively crushes side-channel read attacks (Spectre/Meltdown) and Rowhammer bit-flips, at the cost of performance (~10x slower over normal setup).
  • Intel MPK (Memory Protection Keys): Hardware-accelerated memory isolation. It utilizes pkey_mprotect and WRPKRU thread-local register gating to grant zero-syscall hardware access, triggering a hardware SIGSEGV if any unauthorized thread attempts access.
  • Linux Memory Sealing (mseal): Embedding mseal to permanently lock guard pages and permissions. SecMem uses raw MAP_ANONYMOUS | MAP_PRIVATE syscalls to create discrete VMAs, strictly avoiding the global heap to guarantee it never permanently locks malloc memory or causes leaks.
  • Process Anti-Tracing & Anti-Forking: Implements PR_SET_DUMPABLE(0) to block ptrace debuggers, and MADV_DONTFORK | MADV_DONTDUMP to ensure secrets are strictly wiped in child processes and omitted from core dumps.
  • Memory Locks (mlock): Actively prevents secrets from ever being swapped to unencrypted disk swap space.
  • Zero-Window Fail-Closed RAII: Cryptographic operations are locked behind strict closure boundaries (.access()). Panics correctly trigger stack unwinding that engages the hardware WRPKRU lock as the absolute first instruction in the drop phase, entirely eliminating the time-of-check to time-of-use unwind window before memory is zeroized, re-encrypted, and dropped.

2. SecretBox<S> (Software-Enforced Memory Hardening)

A highly portable, software-only wrapper that requires zero OS syscalls. Perfect for zero-allocator no_std or heavily constrained embedded environments.

  • Strict Exclusive Access: Enforces &mut self for all access. This mathematically eliminates multi-threaded race conditions and ensures zero concurrent references can exist at the compiler level.
  • Dynamic Volatile Canaries: Implements a #[repr(C)] layout enveloping the inner stack data with dynamically generated randomized canaries (via libc::getrandom or RDRAND at startup). Validation is strictly enforced using read_volatile to mathematically prevent LLVM from dead-code-eliminating the memory corruption checks.
  • Closure-Restricted Lifetimes: Completely removes expose_secret(). Secrets are strictly injected into closures (.with_secret()), forcing the reference to automatically die the microsecond the closure finishes.
  • Pure Stack Native: Stores data purely inline, completely eliminating the need for alloc::Box or heap allocation.
  • Anti-Duplication: Actively disables the Clone trait to prevent cryptographic key scattering across dynamic RAM.

Usage

use sec_mem::{SecMem, SecretBox};
use zeroize::Zeroize;

// 1. High-Assurance OS-Protected Memory (SecMem)
let master_key = [0xAAu8; 32];
let mut secure_key = SecMem::new(master_key);

// Secret is unlocked, unblinded, and Hardware MPK-accessed only inside this closure
secure_key.access_mut(|key| {
   key[0] = 0xBB;
}); // Memory is instantly hardware-locked and re-blinded here!

// 2. Portable Software-Hardened Box (SecretBox)
let mut portable_box = SecretBox::new(42u32);

portable_box.with_secret(|val| {
   assert_eq!(*val, 42);
}); // Stack canaries verified via volatile reads on access!

Advanced Security Testing

We hammer the library with 24 aggressive security tests designed to simulate raw exploit vectors, including:

  • attack_proc_self_mem_read: Proves kernel bypass reading mprotected pages via /proc/self/mem only yields encrypted ciphertext.
  • attack_stack_corruption: Uses unsafe pointer arithmetic to artificially overflow the SecretBox stack, proving the canaries catch the exploit and panic.
  • attack_mseal_guard_page_bypass: Attempts to forcefully unprotect guard pages, proving mseal successfully blocks it.
  • attack_panic_during_access: Panics inside an unlocked closure to verify the Drop handler successfully executes during unwind to prevent memory leakage.

Performance Considerations

SecMem heavily trades performance for maximum security. Hardware-accelerated memory protection and encryption-at-rest requires expensive context switches, syscalls, cache flushes, and memory barriers.

It is NOT designed for raw-performance hot paths (e.g. encrypting a 10Gbps packet stream). However, it is perfectly suited for web servers, password managers, key management systems (KMS), or security-focused applications where long-term key protection is prioritized over nanosecond-level latency.

Operation Standard Memory / Box SecretBox (Stack) SecMem (Hardware)
Allocation ~50 ns ~2 ns ~15,600 ns (15.6 µs)
Read Access ~40 ns < 1 ns ~3,170 ns (3.17 µs)
Write Access ~142 ns < 1 ns ~3,330 ns (3.33 µs)
Deallocation ~40 ns ~2 ns ~5,000 ns (5.0 µs)

Benchmarks are approximations representing the heavy toll of raw mmap, pkey_mprotect, mlock, cache flushing, and ChaCha20 encryption loops compared to standard heap allocations.