#![allow(clippy::print_stdout)]
#![allow(clippy::unwrap_used)]
use hardware_enclave::{
coffer_view, pool_acquire, pool_release, LockedBuffer, MemoryEnclave, SecureBuffer,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive(tracing::Level::INFO.into()),
)
.init();
println!("=== SecureBuffer ===");
demo_secure_buffer()?;
println!("\n=== LockedBuffer ===");
demo_locked_buffer()?;
println!("\n=== MemoryEnclave ===");
demo_memory_enclave()?;
println!("\n=== Pool (pool_acquire / coffer_view) ===");
demo_pool()?;
println!("\nMemory protection example complete.");
Ok(())
}
fn demo_secure_buffer() -> Result<(), Box<dyn std::error::Error>> {
let key_material = [0xAB_u8; 32];
let mut buf = SecureBuffer::new(32)?;
println!(" Allocated SecureBuffer (32 bytes, state=Mutable).");
buf.bytes().copy_from_slice(&key_material);
println!(" Wrote secret data.");
buf.freeze()?;
println!(" Frozen (read-only).");
assert_eq!(buf.as_slice(), &key_material);
println!(" Read back: {}...", bytes_to_hex(&buf.as_slice()[..4]));
buf.melt()?;
buf.bytes().fill(0xFF);
println!(" Melted and overwrote with 0xFF.");
buf.destroy()?;
println!(" Destroyed (canaries verified, memory zeroized and unmapped).");
Ok(())
}
fn demo_locked_buffer() -> Result<(), Box<dyn std::error::Error>> {
let secret = b"locked secret value";
let buf = LockedBuffer::from_bytes(secret.as_ref())?;
println!(" Created LockedBuffer from bytes ({} bytes).", buf.size());
{
let copy = buf.bytes_zeroizing();
assert_eq!(copy.as_slice(), secret.as_ref());
println!(" bytes_zeroizing() returned correct data.");
}
let rand_buf = LockedBuffer::random(32)?;
let rand_bytes = rand_buf.bytes_zeroizing();
assert_eq!(rand_bytes.len(), 32);
println!(
" LockedBuffer::random(32) produced {} non-zero bytes.",
rand_bytes.iter().filter(|&&b| b != 0).count()
);
buf.wipe();
let wiped = buf.bytes_zeroizing();
assert!(wiped.iter().all(|&b| b == 0), "wipe() must zero the buffer");
println!(" wipe() zeroed the buffer.");
Ok(())
}
fn demo_memory_enclave() -> Result<(), Box<dyn std::error::Error>> {
let session_token = b"my session token 1234";
let sealed = MemoryEnclave::seal(session_token)?;
println!(
" Sealed {} bytes. MemoryEnclave id={}.",
session_token.len(),
sealed.id()
);
{
let slot = sealed.open()?;
assert_eq!(
&slot.as_slice()[..session_token.len()],
session_token,
"Seal/open roundtrip mismatch"
);
println!(" open() (cold path) → plaintext verified.");
}
{
let slot = sealed.open()?;
assert_eq!(&slot.as_slice()[..session_token.len()], session_token);
println!(" open() (hot cache path) → plaintext verified.");
}
let sealed2 = MemoryEnclave::seal(session_token)?;
assert_ne!(
sealed.id(),
sealed2.id(),
"Each seal must produce a distinct ID"
);
println!(
" Two seals of the same data produce distinct IDs ({} vs {}).",
sealed.id(),
sealed2.id()
);
drop(sealed);
drop(sealed2);
println!(" Dropped MemoryEnclave values — hot cache evicted.");
Ok(())
}
fn demo_pool() -> Result<(), Box<dyn std::error::Error>> {
let mut slot = pool_acquire(32)?;
println!(" pool_acquire(32) → PoolSlot ({} bytes).", slot.size());
slot.bytes().fill(0xCC);
println!(" Wrote 0xCC into slot.");
pool_release(slot);
println!(" pool_release() returned slot to pool (slot zeroed).");
{
let key_slot = coffer_view()?;
assert_eq!(key_slot.size(), 32, "Coffer key must be 32 bytes (AES-256)");
println!(" coffer_view() → 32-byte AES-256 master key slot acquired.");
}
println!(" coffer_view dropped — key slot returned to pool.");
let big_slot = pool_acquire(8192)?;
println!(
" pool_acquire(8192) → PoolSlot ({} bytes, standalone SecureBuffer).",
big_slot.size()
);
drop(big_slot);
println!(" Large slot dropped — SecureBuffer destroyed.");
Ok(())
}
fn bytes_to_hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect()
}