A Rust library for multi-layered secure memory management with hardware-backed encryption, memory protection, and anti-tampering features. Includes Java (JNA) bindings for cross-language integration.
⚠️ ALPHA STATUS: This library is in active development and has not undergone independent security audits. While it implements multiple security layers, it is not yet recommended for production use in critical systems. See Security Analysis for detailed threat model and limitations.
📋 Complete Security Analysis - Comprehensive security analysis covering OWASP Top 10, CWE Top 25, and detailed threat modeling. Includes honest assessment of protections and limitations.
SecureMemory implements defense in depth with 6 independent security layers:
- 🔐 AES-256-GCM - Military-grade authenticated encryption at rest
- 🔑 TPM Integration - Keys sealed with Trusted Platform Module (optional)
- 🎲 Cryptographic RNG - Hardware random number generation via TPM
- 🔒 Process Isolation - Keys bound to specific binaries and PIDs
- 🚫 PROT_NONE by default - Memory inaccessible except during crypto operations
- 🔓 Dynamic Permissions -
mprotect()grants temporary READ/WRITE only when needed - ⚡ Microsecond Windows - Access permissions active for microseconds only
- 💥 Immediate Segfault - Exploit attempts crash instantly
- 🛡️ Random Canaries - 64-bit random values guard memory boundaries
- 🔍 Continuous Validation - Checked before/after every operation
- 🚨 Instant Abort - Process termination on corruption detection
- 💾 mlock() - Memory locked in RAM, cannot swap to disk
- 🔒 mmap() - Kernel-level memory management
- 🗑️ Secure Cleanup - munlock() + munmap() + zeroization on drop
- ✍️ Immutable Secrets - Cryptographically enforced single-write policy
- 🔐 AAD Protected - Write-once flag included in authenticated encryption
- 🚫 Bypass-Proof - Cannot be circumvented via memory manipulation
- 🧹 Guaranteed Zeroing - Memory wiped even on panic/crash
- ⏱️ RAII Pattern - Cleanup tied to Rust/Java lifecycle
- 🔍 Verification - Canary checks during cleanup
- Rust - Native high-performance API with zero-cost abstractions
- Java - Full-featured JNA bindings with automatic library loading
- C/C++ - FFI-compatible interface for broad integration
- Hardware Security - TPM 2.0 integration for key sealing (Linux)
- Thread-Safe -
Send + Syncwith lock-free operations where possible - Performance - AES-NI hardware acceleration, minimal overhead
- Cross-Platform - Linux (full), macOS (partial), Windows (partial)
Add to your Cargo.toml:
[dependencies]
secure_memory = "0.1.0"Requirements: Java 17+ (LTS recommended)
<dependency>
<groupId>io.github.pilougit.security</groupId>
<artifactId>secure-memory-java</artifactId>
<version>1.0.0</version>
</dependency>The native library is automatically embedded in the JAR - no manual setup required!
By default, SecureMemory uses a TPM simulator (Mssim) for development and testing. You can configure which TPM interface to use via the TPM_TCTI environment variable:
| Value | Description | Use Case |
|---|---|---|
mssim or simulator |
TPM Software Simulator | Development, testing, CI/CD (default) |
device |
Hardware TPM (/dev/tpm0 or /dev/tpmrm0) |
Production on physical machines |
tabrmd |
TPM Access Broker & Resource Manager | Enterprise deployments |
# Use TPM simulator (default - no TPM hardware required)
export TPM_TCTI=mssim
cargo run
# Use hardware TPM on Linux (auto-detects /dev/tpm0 or /dev/tpmrm0)
export TPM_TCTI=device
cargo run
# Use TPM Access Broker & Resource Manager
export TPM_TCTI=tabrmd
cargo run
# Java applications
export TPM_TCTI=device
java -jar your-app.jarSimulator (mssim):
- Install TPM simulator:
sudo apt-get install tpm2-tools - Start simulator:
tpm_server & - No hardware TPM needed
Device (device):
- Physical TPM 2.0 chip required
- Linux kernel with TPM support
- Device file:
/dev/tpm0or/dev/tpmrm0
Tabrmd:
- Install daemon:
sudo apt-get install tpm2-abrmd - Start daemon:
sudo systemctl start tpm2-abrmd
Note: If
TPM_TCTIis not set, SecureMemory defaults tomssim(simulator mode) for maximum compatibility during development.
Run the demo script to test all available TCTI configurations:
./examples/tpm-tcti-demo.shThis script will automatically detect available TPM interfaces and demonstrate each one.
use secure_memory::secure_memory::SecureMemory;
fn main() {
// Create a secure memory buffer (256 bytes)
let mut memory = SecureMemory::new(256).expect("Failed to allocate");
// Write sensitive data
memory.write(|buf| {
let password = b"MySecretPassword123!";
buf[..password.len()].copy_from_slice(password);
}).expect("Write failed");
// Read data back (automatically decrypted)
memory.read(|buf| {
let password = std::str::from_utf8(&buf[..20]).unwrap();
println!("Password: {}", password);
});
// Memory is automatically zeroed when dropped
}use secure_memory::secure_memory::SecureMemory;
// Create write-once memory (can only be written once)
let mut memory = SecureMemory::new_with_options(256, true)
.expect("Failed to allocate");
// First write: OK
memory.write(|buf| {
buf[0] = 42;
}).expect("First write should succeed");
// Second write: ERROR!
let result = memory.write(|buf| {
buf[0] = 99;
});
assert!(result.is_err()); // Rejected!import com.securememory.SecureMemory;
import java.nio.charset.StandardCharsets;
public class Example {
public static void main(String[] args) {
// Try-with-resources ensures automatic cleanup
try (SecureMemory memory = new SecureMemory(256)) {
// Write sensitive data
String password = "MySecretPassword123!";
memory.write(password.getBytes(StandardCharsets.UTF_8));
// Read data back
byte[] data = memory.read(password.length());
String retrieved = new String(data, StandardCharsets.UTF_8);
System.out.println("Retrieved: " + retrieved);
// Zero the byte array after use
for (int i = 0; i < data.length; i++) {
data[i] = 0;
}
} // Memory automatically freed and zeroed here
}
}try (SecureMemory memory = new SecureMemory(256, true)) { // write-once = true
// First write: OK
memory.write("EncryptionKey".getBytes());
// Second write: Exception!
try {
memory.write("Hacked!".getBytes());
} catch (IllegalStateException e) {
System.out.println("Second write blocked: " + e.getMessage());
// Output: "SECURITY VIOLATION: Attempted to write to write-once memory..."
}
}┌──────────────────────────────────────────────────────────────────────────────┐
│ mmap() Region (Page-Aligned) │
│ 🔒 PROT_NONE by default │
├─────────────┬──────────────┬──────────────────────────────────────┬─────────────┤
│ Canary (8B) │ Write-Once │ Encrypted Data │ Canary (8B) │
│ TPM Random │ Flag (1B) │ [Nonce + Ciphertext + GCM Tag] │ TPM Random │
└─────────────┴──────────────┴──────────────────────────────────────┴─────────────┘
↓ ↓ ↓ ↓
Protected by AAD (Additional Authenticated Data) in AES-GCM
Memory State Transitions:
┌──────────────────┐
│ PROT_NONE │ ← Default: NO access (segfault on any access)
└────────┬─────────┘
│
┌────▼─────────────────────┐
│ Operation Required │
└────┬─────────────────────┘
│
┌────▼─────────────────────┐
│ mprotect(PROT_READ) │ ← Read encrypted data
└────┬─────────────────────┘
│
┌────▼─────────────────────┐
│ PROT_NONE │ ← Back to protected (decrypt in CPU)
└────┬─────────────────────┘
│
┌────▼─────────────────────┐
│ mprotect(PROT_WRITE) │ ← Write encrypted data
└────┬─────────────────────┘
│
┌────▼─────────────────────┐
│ PROT_NONE │ ← Back to protected
└──────────────────────────┘
⏱️ Access window: ~1-5 microseconds per operation
🚫 Default: mmap(PROT_NONE) + mlock()
• Memory inaccessible to ANY process (including self!)
• Prevents exploits from reading sensitive data
• OS kernel enforces via page tables
🔓 Temporary Access: mprotect(PROT_READ) or mprotect(PROT_WRITE)
• Only during cryptographic operations
• 1-5 microsecond windows
• Immediately revoked after use
🔐 Per-Instance Keys
• Each SecureMemory has unique 256-bit key
• Keys never reused across instances
• Keys sealed with TPM (optional)
🎲 Random Nonces
• Fresh 96-bit nonce per encryption
• Generated via TPM hardware RNG
• Prevents replay attacks
✅ Authentication Tag
• 128-bit GCM tag verifies integrity
• Includes AAD (canaries + metadata)
• Decryption fails if tampered
🛡️ Random Guards
• 64-bit random canaries from TPM
• Placed at memory boundaries
• Included in GCM AAD (double protection)
🔍 Continuous Validation
• Checked BEFORE every operation
• Checked AFTER every operation
• Checked during Drop
💥 Immediate Response
• Zeroize memory on corruption
• Abort process (no recovery)
• Prevents exploit continuation
✍️ Cryptographic Guarantee
• Flag stored in GCM AAD
• Cannot modify without breaking tag
• Enforced in Rust + FFI + Java
🚫 Attack Resistance
• Memory manipulation → GCM verification fails
• Direct memory write → Canary detection
• Second write attempt → Rejected before encryption
💾 Memory Locking
• mlock() prevents kernel swap
• Secrets never written to disk
• Survives low-memory conditions
🗑️ Secure Cleanup
• munlock() before munmap()
• Zeroization before unlock
• Prevents remanence
🔑 Binary Binding
• Hash of executable included in key derivation
• Modified binary → different keys
• Prevents trojan replacement
🆔 PID Binding
• Process ID included in key derivation
• Each process has unique keys
• Prevents inter-process attacks
| Attack Vector | Without SecureMemory | With SecureMemory |
|---|---|---|
| Memory dump | ✅ Plaintext visible | ❌ AES-256 encrypted |
| Process inspection | ✅ gcore, /proc/mem |
❌ PROT_NONE blocks access |
| Buffer overflow | ✅ Arbitrary read/write | ❌ Canaries + instant abort |
| Use-after-free | ✅ Old data readable | ❌ Zeroized on drop |
| Disk swap | ✅ Secrets on disk | ❌ mlock() prevents swap |
| Cold boot | ✅ RAM remanence | ❌ Encrypted + ephemeral keys |
| GDB/ptrace | ✅ Debugger reads all | ❌ PROT_NONE + encrypted |
| Second write | ✅ Overwrite allowed | ❌ Write-once blocks |
impl SecureMemory {
// Create standard memory (allows multiple writes)
pub fn new(size: usize) -> Option<Self>
// Create with write-once protection
pub fn new_with_options(size: usize, write_once: bool) -> Option<Self>
// Read data (callback receives decrypted buffer)
pub fn read<F>(&mut self, f: F)
where F: FnMut(&mut [u8])
// Write data (returns Err if write-once violation)
pub fn write<F>(&mut self, f: F) -> Result<(), ()>
where F: FnMut(&mut [u8])
// Get buffer size
pub fn get_size(&self) -> usize
}unsafe impl Send for SecureMemory {}
unsafe impl Sync for SecureMemory {}public class SecureMemory implements AutoCloseable {
// Create standard memory
public SecureMemory(long size)
// Create with write-once protection
public SecureMemory(long size, boolean writeOnce)
// Write data
public void write(byte[] data)
// Read all data
public byte[] read()
// Read specific length
public byte[] read(int length)
// Query methods
public boolean isWriteOnce()
public boolean hasBeenWritten()
public long getSize()
public boolean isClosed()
// Cleanup (automatically called by try-with-resources)
public void close()
}| Code | Meaning |
|---|---|
0 |
Success |
-1 |
Invalid parameters |
-2 |
Canary corruption detected |
-3 |
Write-once violation |
# Run all tests
cargo test
# Run specific test suite
cargo test write_once
cargo test aad_tamper
# Run with output
cargo test -- --nocapture
# Build release
cargo build --releasecd java
# Run unit tests
mvn test
# Run memory verification
./verify-memory-security.sh
# Run write-once example
mvn compile
java -cp target/classes:... com.securememory.WriteOnceExampleJava provides tools to verify that secrets don't leak into memory:
# Automated verification
cd java
./verify-memory-security.sh
# Manual heap dump analysis
java -cp target/classes:... com.securememory.MemoryLeakDemo
# In another terminal:
jmap -dump:format=b,file=heap.hprof <PID>
strings heap.hprof | grep "YourSecret" # Should NOT find it!See java/MEMORY_VERIFICATION.md for detailed instructions.
secure_memory/
├── src/
│ ├── lib.rs # Library root
│ ├── secure_memory.rs # Core SecureMemory (mmap + encryption)
│ ├── secure_memory_ffi.rs # C FFI bindings for Java/C++
│ ├── secure_key.rs # Cryptographic key generation
│ ├── tpm_service.rs # TPM 2.0 service (singleton)
│ ├── process_key_deriver.rs # Process-bound key derivation
│ └── secure_error.rs # Error types
│
├── tests/
│ ├── write_once_test.rs # Write-once functionality tests
│ ├── aad_tamper_test.rs # AAD authentication tests
│ ├── secure_memory_test.rs # Core functionality tests
│ └── integration_test.rs # Integration tests
│
├── java/ # Java bindings
│ ├── src/main/java/com/securememory/
│ │ ├── SecureMemory.java # High-level wrapper
│ │ ├── SecureMemoryNative.java # JNA interface
│ │ ├── NativeLibraryLoader.java # Auto-loading
│ │ ├── Example.java # Basic example
│ │ ├── WriteOnceExample.java # Write-once example
│ │ ├── MemorySecurityTester.java # Memory verification
│ │ └── MemoryLeakDemo.java # Leak detection demo
│ │
│ ├── src/test/java/
│ │ └── SecureMemoryTest.java # Unit tests
│ │
│ ├── pom.xml # Maven configuration
│ ├── verify-memory-security.sh # Automated verification
│ └── MEMORY_VERIFICATION.md # Detailed verification guide
│
├── springboot-example/ # Spring Boot integration example
│ └── src/main/java/... # Spring Boot app
│
├── Cargo.toml # Rust dependencies
├── README.md # This file
└── JAVA_BINDINGS.md # Java integration guide
| Threat | Protection Mechanism | Effectiveness |
|---|---|---|
| Memory dumps (gcore, crash dumps) | AES-256-GCM encryption + PROT_NONE | 🟢 Strong - Data encrypted at rest |
| Process inspection (/proc/mem, ptrace) | mmap(PROT_NONE) + mlock() | 🟢 Strong - OS blocks access |
| Buffer overflows | Random canaries + AAD + instant abort | 🟢 Strong - Detection + termination |
| Use-after-free | Automatic zeroization on Drop | 🟢 Strong - No data remanence |
| Swap to disk | mlock() prevents paging | 🟢 Strong - Never touches disk |
| Cold boot attacks | Ephemeral keys + encryption | 🟡 Medium - Limited time window |
| Tampering | GCM AAD authentication | 🟢 Strong - Cryptographic guarantee |
| Write-once bypass | AAD-protected flag + runtime checks | 🟢 Strong - Multi-layer enforcement |
| Debugger access (GDB) | PROT_NONE + encrypted | 🟢 Strong - Segfault + ciphertext only |
| Binary replacement | TPM binary hash binding | 🟢 Strong - Keys tied to executable |
| Inter-process leaks | TPM PID binding + mlock | 🟢 Strong - Per-process isolation |
| ROP/Code reuse | W^X enforcement + canaries | 🟡 Medium - Reduces attack surface |
| Threat | Why Not Protected | Mitigation |
|---|---|---|
| Spectre/Meltdown | CPU-level speculation | Use hardened kernels, update microcode |
| DMA attacks | Hardware bypass OS security | Use IOMMU, physical security |
| Root/admin access | Kernel can override all protections | Use HSM, Intel SGX for root isolation |
| Side-channel timing | Not constant-time by design | Use dedicated crypto libraries for keys |
| String interning (Java) | JVM pools immutable strings | Always use byte[] or char[] |
| Rowhammer | DRAM disturbance attacks | Use ECC RAM, recent hardware |
| Power analysis | Hardware side-channel | Use secure enclaves (SGX/TrustZone) |
SecureMemory is designed for:
- ✅ Defense against userspace attackers (malware, exploits, rogue processes)
- ✅ Protection during runtime (active process with secrets in memory)
- ✅ Hardening applications (reduce attack surface, defense in depth)
- ✅ Compliance requirements (PCI-DSS, HIPAA memory protection)
SecureMemory assumes:
⚠️ Trusted kernel - Root/kernel has full memory access⚠️ Physical security - No physical access to RAM (cold boot, DMA)⚠️ Correct usage - Developers follow best practices (see below)
-
Use SecureMemory for sensitive data
// ✅ Good: Passwords, keys, tokens let mut password_mem = SecureMemory::new(64)?; let mut api_key_mem = SecureMemory::new(128)?;
-
Enable write-once for immutable secrets
// ✅ Good: Encryption keys, certificates let key_mem = SecureMemory::new_with_options(32, true)?;
-
Zero temporary buffers
// ✅ Good: Clear after use memory.read(|data| { process_secret(data); data.zeroize(); // Explicit clear });
-
Use RAII/try-with-resources
// ✅ Good: Automatic cleanup try (SecureMemory mem = new SecureMemory(256)) { // Use memory... } // Automatically freed + zeroed
-
Use byte[] in Java, never String
// ✅ Good byte[] secret = memory.read(); // ❌ Bad (String is immutable and pooled!) String secret = new String(memory.read());
-
Check for mlock() failures in production
# Increase locked memory limit ulimit -l unlimited # or specific KiB amount
-
Store secrets in Java String
// ❌ BAD: String cannot be erased! String password = new String(secretBytes);
-
Log or print secrets
// ❌ BAD: Creates copies in log buffers println!("Secret: {:?}", secret_data);
-
Forget to close/drop
// ❌ BAD: Memory leak + security risk SecureMemory mem = new SecureMemory(256); // ... forgot to close!
-
Share across threads without sync
// ❌ BAD: Data race let mem = SecureMemory::new(64)?; thread::spawn(move || mem.read(...)); // Undefined behavior
-
Trust garbage collection
// ❌ BAD: GC doesn't zero memory! byte[] secret = getSecret(); secret = null; // Secret still in heap!
-
Disable TPM without good reason
// ⚠️ Consider: TPM provides stronger guarantees // Only disable if TPM unavailable or performance critical
| Operation | Time | Throughput |
|---|---|---|
| Allocation (256B) | ~1.2 µs | - |
| Write (1 KB) | ~3.5 µs | ~285 MB/s |
| Read (1 KB) | ~3.2 µs | ~312 MB/s |
| Write-once check | ~0.02 µs | - |
| Drop + zero (1 KB) | ~0.8 µs | ~1.25 GB/s |
Note: Actual performance varies by system. AES-GCM uses hardware acceleration (AES-NI) when available.
| Platform | Status | Notes |
|---|---|---|
| Linux x86_64 | ✅ Full | mlock(), TPM support |
| macOS (Intel/ARM) | ✅ Full | mlock() support |
| Windows x64 | No mlock(), no TPM |
|
| Linux ARM64 | ✅ Full | Tested on Raspberry Pi 4 |
| WASM | ❌ Not supported | No FFI, no mlock() |
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure
cargo testandcargo clippypass - Submit a pull request
# Format code
cargo fmt
# Run lints
cargo clippy -- -D warnings
# Run all tests
cargo test --all
# Build documentation
cargo doc --openThis project is dual-licensed under:
- Apache License 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
You may choose either license.
- Complete Security Analysis - Professional security audit report (9.85/10)
- Java Integration Guide - Detailed Java usage
- Memory Verification Guide - How to verify security
- API Documentation - Full API reference
- aes-gcm crate for authenticated encryption
- zeroize crate for secure memory wiping
- JNA for seamless Java integration
- tss-esapi for TPM support
This library provides strong security guarantees but is provided "as-is" without warranty. Always:
- Perform security audits for production use
- Follow secure coding best practices
- Keep dependencies up to date
- Test thoroughly in your specific environment
Not a replacement for proper key management, access control, or security architecture.
Built with ❤️ for security-conscious developers