Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hardened In-RAM Secret Storage for Rust (with Inline Assembly)

SecureCell is a small educational demo that shows how to store sensitive data in RAM in a way that’s encrypted-at-rest and only readable during short critical sections. It uses:

  • Rust for memory safety and ergonomics

  • Linux page protections (mmap, mlock, mprotect, MADV_DONTDUMP, PR_SET_DUMPABLE)

  • x86-64 Protection Keys (PKU) via inline assembly (wrpkru/rdpkru) to open/close access without TLB invalidations (when supported)

  • A minimal stream-XOR for encryption (for the demo). In real projects, replace it with a vetted cipher (AES-GCM or ChaCha20-Poly1305).

What problem does it address?

  • Prevent casual memory scraping (e.g., other processes reading /proc/$pid/mem, core dumps, simple RCE payloads) from easily obtaining secrets.

  • Minimize the time windows in which plaintext exists in accessible memory.

  • Make “read/modify” by other processes significantly harder without elevated privileges.

Not a silver bullet: Kernel-level attackers, root with ptrace, physical DMA, or hypervisor access can still defeat user-space defenses.

How It Works

1. Memory allocation & hardening

  • mmap(PROT_NONE) a page-aligned region

  • mlock to prevent swapping

  • MADV_DONTDUMP and PR_SET_DUMPABLE=0 to keep secrets out of core dumps

2. Encryption-at-rest

  • A per-process random key is generated from OsRng

  • Data written with SecureCell::set() is immediately XOR-encrypted and stored

  • On get(), ciphertext is read, decrypted on the stack, returned to the caller, and then zeroized

3. Access windows with PKU (if supported)

  • The mapping is associated with a protection key (pkey_mprotect)

  • Outside critical sections, access is denied by setting the corresponding PKRU bits (inline asm wrpkru)

  • For a read/write, we briefly allow access (clear PKRU AD/WD bits), perform the operation, then deny again

  • If PKU isn’t available, we fallback to toggling mprotect (weaker, but portable)

4. Zeroization & teardown

  • On Drop, the region is temporarily made writable; the bytes are overwritten via write_volatile

  • The key material is zeroized

  • The mapping is unmapped

Requirements

  • OS: Linux recommended

  • Arch: x86-64 (PKU path). Other arches will build, but only the mprotect fallback is used.

  • Rust: 1.70+ (tested on modern stable)

  • Tooling: gcc/clang/libc headers for pkey functions (typical on Linux)

Some older distros or kernels may not expose pkey_* syscalls or may not actually enable PKU. The code gracefully falls back to mprotect.

Build & Run

cd securecell
cargo run --release

Example output:

SecureCell demo: protected, encrypted-at-rest memory.
Secret stored (encrypted at rest). Memory is PROT_NONE with PKU denial between accesses.
Decrypted read: Attack at dawn. Bring coffee. 🍺

Threat Model & Limitations

  • Out of scope to fully prevent: root attackers, kernel exploits, DMA/PCIe sniffers, memory forensics with full privileges, or hypervisor inspection.

  • On Windows/macOS: This exact PKU approach won’t work; you’d use platform-specific features (e.g., VM protection APIs, enclaves/SGX/SEV/TEE if available).

  • Crypto: The demo uses XOR for simplicity. Replace xor_keystream with a vetted AEAD (e.g., ring, aes-gcm, chacha20poly1305 crates) and include nonces + authentication tags.

Hardening Ideas (beyond this demo)

  • AEAD encryption with per-record nonces and authentication tags

  • Per-thread WRPKRU guard using RAII to minimize enabled window durations

  • Guard pages around the region to catch over/underflows

  • Seccomp to restrict syscalls after setup

  • Key wrapping with KMS/TPM and only deriving the in-RAM key just-in-time

  • Enclaves/TEEs if your deployment platform supports them

API Sketch

  • SecureCell::new(len) -> SecureCell

  • SecureCell::set(&mut self, plaintext) — encrypts and stores

  • SecureCell::get(&self, out_buf) -> len — decrypts into user buffer

  • Automatic zeroization and unmap on Drop

Why Inline Assembly?

We use inline asm to call wrpkru/rdpkru which are not regular instructions exposed by portable intrinsics. This shows how Rust and assembly can cooperate: Rust manages safety and lifecycle; assembly toggles hardware protection without flushing the TLB (unlike mprotect), keeping the “open access” window as short and cheap as possible.

About

SecureCell is a small educational demo that shows how to store sensitive data in RAM in a way that’s encrypted-at-rest and only readable during short “critical sections.”

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages