redoubt-zero 0.1.0-rc.1

Memory guards and zeroization primitives with automatic verification
Documentation

Systematic memory zeroization with compile-time and runtime guarantees.

Overview

redoubt-zero provides RAII guards and derive macros for automatic, verifiable zeroization. Zeroization happens automatically on drop with runtime verification that it actually occurred.

This is a convenience re-export crate combining [redoubt-zero-core] and [redoubt-zero-derive].

Quick Start

use redoubt_zero::{RedoubtZero, ZeroizeOnDropSentinel, AssertZeroizeOnDrop};

#[derive(RedoubtZero)]
#[fast_zeroize(drop)]
struct TempBuffer {
    data: Vec<u8>,
    capacity: usize,
    __sentinel: ZeroizeOnDropSentinel,
}

let mut buffer = TempBuffer {
    data: vec![1, 2, 3, 4],
    capacity: 1024,
    __sentinel: ZeroizeOnDropSentinel::default(),
};

// Use buffer...

// Automatically zeroized on drop
drop(buffer);

How It Works

1. The Sentinel Pattern

Every struct includes a ZeroizeOnDropSentinel field. This sentinel:

  • Flips a flag on drop
  • Can be cloned to verify the original was zeroized
  • Provides runtime proof of zeroization

2. Automatic Trait Implementation

The #[derive(RedoubtZero)] macro generates:

  • FastZeroizable: Implements fast_zeroize(&mut self) to zero all fields
  • ZeroizationProbe: Implements is_zeroized(&self) to check if data is zeroed
  • AssertZeroizeOnDrop: Test helper to verify drop behavior
  • Optional Drop impl: With #[fast_zeroize(drop)], generates Drop that calls fast_zeroize()

3. Field Skipping

Fields can be excluded from zeroization with #[fast_zeroize(skip)]:

# use redoubt_zero::{RedoubtZero, ZeroizeOnDropSentinel};
#[derive(RedoubtZero)]
struct SessionData {
    token: Vec<u8>,        // Zeroized
    #[fast_zeroize(skip)]
    id: u64,               // Not zeroized (just metadata)
    __sentinel: ZeroizeOnDropSentinel,
}

Core Types

Traits

Testing Zeroization

Use AssertZeroizeOnDrop::assert_zeroize_on_drop() in tests to verify behavior:

# use redoubt_zero::{RedoubtZero, ZeroizeOnDropSentinel, AssertZeroizeOnDrop};
#[derive(RedoubtZero)]
#[fast_zeroize(drop)]
struct Workspace {
    buffer: Vec<u8>,
    __sentinel: ZeroizeOnDropSentinel,
}

#[test]
fn test_workspace_zeroizes() {
    let ws = Workspace {
        buffer: vec![1, 2, 3, 4],
        __sentinel: ZeroizeOnDropSentinel::default(),
    };
    ws.assert_zeroize_on_drop();  // Panics if not zeroized
}

Design Rationale

The Sentinel Pattern

The sentinel enables runtime verification without unsafe code:

  • Clone the sentinel before drop
  • Drop the original
  • Check the sentinel's flag flipped

This proves Drop ran and zeroization occurred.

FastZeroizable Implementation

FastZeroizable uses compiler fences for zeroization:

  • Matches LLVM's optimization model
  • Allows vectorization and unrolling
  • Prevents dead store elimination

See redoubt-zero-core for implementation details.

Use Cases

Useful for any data that needs guaranteed cleanup:

  • Cryptographic material: Keys, nonces, IVs
  • Temporary buffers: Workspace memory, intermediate results
  • Session data: Tokens, cookies, auth state
  • Parser state: Untrusted input, partial parses
  • Any heap allocation you want cleaned up reliably

Crate Structure

This crate re-exports:

License

GPL-3.0-only