oxicrypt-module 0.22.0

FIPS 140-3 Level 1 module boundary: state machine, self-test runner, approved-mode indicator
Documentation

FIPS 140-3 Level 1 module boundary.

This crate defines the cryptographic module boundary per FIPS 140-3 Section 7.2 and the service-gating plumbing every other crate in the workspace depends on. No algorithm is permitted to produce output until the power-up self-tests have run and the module has entered the Operational state; on any self-test failure the module latches into a terminal Error state and rejects every subsequent call for the remainder of the process lifetime.

State machine (FIPS 140-3 §7.2)

   ┌──────────┐  initialize() ┌───────────┐  all KATs pass  ┌──────────────┐
   │ PowerOff │──────────────▶│ SelfTest  │────────────────▶│ Operational  │
   └──────────┘               └───────────┘                 └──────────────┘
                                    │                              │
                                KAT failure                conditional self-test
                                    │                            failure
                                    ▼                              │
                               ┌─────────┐◀───────────────────────┘
                               │  Error  │
                               └─────────┘

What this crate ships

  • [State] and the transition machine (PowerOff → SelfTest → Operational | Error).
  • [initialize_with_tests] — the canonical one-shot entry point that the top-level caller uses to run every approved algorithm's power-up KAT before opening the service interface. [initialize] is a thin wrapper for the empty registry case (used only by this crate's own unit tests).
  • [require_operational] — the gate that every approved service in every other crate calls on entry. Returns [Error::NotOperational] (with the observed state) on any pre-Operational or post-Error call.
  • [enter_error_state] — irreversible transition into the terminal error state, called by conditional self-tests (pairwise consistency, DRBG health) when they detect a failure.
  • [KatEntry] and the [SelfTest] trait — the registry shape that algorithm crates use to expose their power-up KATs.
  • [AlgorithmProfile] — runtime selection of an algorithm restriction policy (Unrestricted, CNSA 2.0, CNSA 1.0). Set once at initialization via [initialize_with_profile].
  • [Service] — per-algorithm-and-parameter enumeration of every approved service in the module. Used with [require_allowed] to enforce profile restrictions.

The test registry is not assembled by linker-section tricks: callers pass an explicit &[KatEntry] slice. That means the full set of power-up tests is visible in source at every call site, which makes it straightforward to audit the module's power-up inventory against the Security Policy.

Algorithm profiles

A single validated binary serves general FIPS 140-3 consumers and CNSA-restricted deployments via a runtime [AlgorithmProfile] selection. The operator passes the desired profile to [initialize_with_profile]; subsequent calls to [require_allowed] enforce it. Services not permitted by the active profile return [Error::AlgorithmRestricted].

Three profiles are defined:

  • Unrestricted — all FIPS-approved algorithms are available. This is the default, matching the behavior of [initialize_with_tests].
  • CNSA 2.0 (CNSSP 15) — only quantum-resistant algorithms: AES-256, SHA-384/512, ML-KEM-1024, ML-DSA-87, LMS, XMSS, plus SHA3-384/512 and 256-bit SP 800-185 variants.
  • CNSA 1.0 — classical algorithms for the transition period: AES-256, SHA-384, ECDSA/ECDH P-384, RSA >= 3072, DH >= 3072.

Profiles nest: CNSA 2.0 is the most restrictive, CNSA 1.0 is intermediate, Unrestricted allows everything. KATs still run all algorithms regardless of profile — the profile only restricts post-initialization service access.

Sensitive security parameters (SSPs)

This crate holds no SSPs of its own. It only gates access to other crates that do. Secret material lives in the algorithm crates that own it (e.g. oxicrypt-rsa's RsaPrivateKey2048, oxicrypt-drbg's DRBG states). The error latch here does not perform SSP zeroization on its own — each owning crate is responsible for ensuring its SSPs are dropped when the process restarts following a transition into the Error state.

FIPS 140-3 / SP 800-140B mapping

SP 800-140B / IG clause Implementation
§7.10 power-up self-tests [initialize_with_tests] runs every registered [KatEntry] sequentially; the first failure latches [State::Error].
§7.10 conditional self-tests Algorithm crates call [enter_error_state] on detecting a pairwise-consistency or DRBG-health failure.
IG 9.5.A approved-mode indicator [is_operational] / [state] — queryable at runtime.
IG 10.3.A software integrity Delegated to oxicrypt-integrity (separate crate), wired in as the first KAT by the top-level caller.

Thread safety

State is stored in a single AtomicU8 and is safe to read from any thread. [initialize_with_tests] uses a compare-and-swap to guarantee the self-test phase runs exactly once per process lifetime even under concurrent first-calls; racing losers spin on the SelfTest state byte so they do not observe the transient phase and then receive [Error::AlreadyInitialized].