1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 Cédric Mesnil <cslashm@pm.me>
//! # quantica — post-quantum cryptography for the `krypteia` workspace
//!
//! Pure-Rust implementations of the three NIST post-quantum standards,
//! sharing the same side-channel countermeasure toolkit
//! ([`silentops`](https://docs.rs/silentops)) used by the classical
//! side of the workspace ([`arcana`](https://docs.rs/arcana)).
//!
//! | Module | Standard | Algorithm | Validation |
//! |--------------|----------|----------------------------------------|------------------------------------------------|
//! | [`ml_kem`] | FIPS 203 | ML-KEM (key encapsulation) | ACVP + Wycheproof |
//! | [`ml_dsa`] | FIPS 204 | ML-DSA (digital signature) | ACVP + Wycheproof |
//! | [`slh_dsa`] | FIPS 205 | SLH-DSA (hash-based digital signature) | ACVP (Wycheproof has no SLH-DSA corpus yet) |
//!
//! # Cargo features
//!
//! | Feature | Default | Effect |
//! |---------|:-------:|--------|
//! | `std` | **on** | Pulls in the standard library. Enables [`OsRng`](ml_kem::OsRng) and `std::error::Error` impls. |
//! | `ml-kem` | **on** | Compiles the FIPS 203 module ([`ml_kem`]). |
//! | `ml-dsa` | **on** | Compiles the FIPS 204 module ([`ml_dsa`]). |
//! | `slh-dsa` | **on** | Compiles the FIPS 205 module ([`slh_dsa`]). |
//! | `sca-protected` | **on** | Activates the masking + shuffled-NTT defences inside ML-KEM **and** ML-DSA (see below). |
//! | `hazmat` | off | Exposes the expert building-block tier (see *API tiers* below). |
//!
//! Disable `std` for `no_std` builds: pass `--no-default-features`
//! then re-enable the algorithms you need. The crate still requires
//! `alloc` (keys, ciphertexts and signatures are `Vec<u8>`-backed).
//!
//! # API tiers
//!
//! The public surface is deliberately split in three tiers:
//!
//! 1. **Facade (guaranteed API)** — the typed entry points
//! [`MlKem`](ml_kem::MlKem), [`MlDsa`](ml_dsa::MlDsa),
//! [`SlhDsa`](slh_dsa::SlhDsa), their key/signature/ciphertext wrappers,
//! the `params` and `rng` modules, [`prehash`] and [`secret`]. Semver
//! applies here; this is what applications should use.
//! 2. **`hazmat` (expert bricks, feature-gated, NO promise)** — the
//! FIPS-level building blocks (byte encodings, samplers, Decompose/hints,
//! the SLH-DSA address/tweakable-hash surface, the raw-slice algorithm
//! facades and the deterministic `*_internal` CAVP entries). Offered for
//! KAT/test-vector tooling and research. **No stability,
//! misuse-resistance, or side-channel guarantee** — this tier may change
//! in *any* release, and misusing some bricks (e.g. the unauthenticated
//! component schemes) breaks the scheme's security.
//! 3. **Internal** — everything else (`ntt`, `kpke`, WOTS+/XMSS/FORS, the
//! masking/shuffling countermeasures, …) is `pub(crate)`: not reachable,
//! not a compatibility surface.
//!
//! # Quick start
//!
//! ```no_run
//! use quantica::ml_kem::*;
//!
//! let mut rng = OsRng;
//! let (ek, dk) = MlKem::<MlKem768>::keygen(&mut rng).unwrap();
//! let (ss_a, ct) = MlKem::<MlKem768>::encaps(&ek, &mut rng).unwrap();
//! let ss_b = MlKem::<MlKem768>::decaps(&dk, &ct, &mut rng).unwrap();
//! assert_eq!(ss_a, ss_b);
//! // Both shared secrets auto-zeroize when they drop.
//! ```
//!
//! # Typed key wrappers (Zeroize-on-Drop)
//!
//! The public API never returns raw `Vec<u8>` for secret material.
//! Each algorithm exposes parameter-set-tagged wrapper types backed
//! by the shared [`secret`] module:
//!
//! | Module | Public (not zeroized) | Secret (Drop-zeroizes) |
//! |------------|---------------------------------------------|----------------------------------------------|
//! | [`ml_kem`] | [`EncapsulationKey<P>`](ml_kem::EncapsulationKey), [`Ciphertext<P>`](ml_kem::Ciphertext) | [`DecapsulationKey<P>`](ml_kem::DecapsulationKey), [`SharedSecret`](ml_kem::SharedSecret) |
//! | [`ml_dsa`] | [`VerifyingKey<P>`](ml_dsa::VerifyingKey), [`Signature<P>`](ml_dsa::Signature) | [`SigningKey<P>`](ml_dsa::SigningKey) |
//! | [`slh_dsa`]| [`VerifyingKey<P>`](slh_dsa::VerifyingKey), [`Signature<P>`](slh_dsa::Signature) | [`SigningKey<P>`](slh_dsa::SigningKey) |
//!
//! All wrappers implement `from_bytes(&[u8])` (length-validated),
//! `as_bytes()`, `Deref<Target=[u8]>`, `AsRef<[u8]>` and `Clone`.
//! Secret variants have a **redacted `Debug`** impl
//! (`<redacted; len=N>`) so stray logging cannot leak key material.
//!
//! The raw byte-slice paths (`ml_kem::kem::*`, `ml_dsa::dsa::*`,
//! `slh_dsa::slh::*`) are exposed **only** under the `hazmat` Cargo
//! feature — `pub(crate)` otherwise — for ACVP/CAVP tooling and the
//! C FFI. See the `hazmat` tier in *API tiers* above.
//!
//! # Side-channel countermeasures
//!
//! ## Always-on (every build)
//!
//! | Defence | Algorithms | Threat addressed |
//! |-----------------------|---------------------|---------------------------------|
//! | Constant-time arith | all three | Timing / cache / basic SPA |
//! | Zeroize-on-Drop | all three | Cold boot, memory dumps, UAF |
//! | Volatile zeroization | all three | Same, on intermediates |
//! | Double Decaps | ML-KEM | DFA on FO comparison |
//! | dk integrity check | ML-KEM | DFA on stored key material |
//! | Hedged signing | ML-DSA, SLH-DSA | Fault-induced nonce reuse |
//!
//! ## `sca-protected` (on by default)
//!
//! | Defence | Algorithms | Module |
//! |-------------------------------|-----------------|---------------------------------------|
//! | First-order additive masking | ML-KEM, ML-DSA | `ml_kem::masked`, `ml_dsa::masked` (internal) |
//! | Shuffled NTT (Fisher-Yates) | ML-KEM, ML-DSA | `ml_kem::shuffle`, `ml_dsa::shuffle` (internal) |
//! | Mask refresh between rounds | ML-DSA | `MaskedPoly::refresh()` per rejection iteration |
//!
//! The masking layer is mathematically transparent: `unmask(op(mask(s), public)) ≡ op(s, public)`.
//! All NIST ACVP vectors pass unchanged with `sca-protected` enabled — the masked path produces
//! **bit-identical** signatures and shared secrets.
//!
//! SLH-DSA is purely hash-based and has no algebraic structure to
//! mask; the always-on defences are the relevant layer there.
//!
//! # `no_std`
//!
//! `quantica` is `std`-by-default, but the standard library is gated
//! behind the `std` feature. Building with
//! `--no-default-features --features ml-kem,ml-dsa,slh-dsa,sca-protected`
//! produces a `no_std` crate that still depends on `alloc` (because
//! the algorithms allocate heap buffers for keys, ciphertexts and
//! signatures). In `no_std` mode:
//!
//! * The OS-backed `OsRng` is not available — callers must provide
//! their own [`CryptoRng`](ml_kem::CryptoRng) implementation
//! (typically wrapping a hardware RNG on embedded targets).
//! * The error enums no longer implement [`std::error::Error`].
//!
//! Cross-compile validated on `thumbv7em-none-eabihf` (Cortex-M4),
//! `thumbv6m-none-eabi` (Cortex-M0), and `riscv32imc-unknown-none-elf`
//! (ESP32-C3) with all three algorithms + `sca-protected` enabled.
//!
//! # Examples
//!
//! ```bash
//! cargo run --release -p quantica --example ml_kem_roundtrip
//! cargo run --release -p quantica --example ml_dsa_sign_verify
//! cargo run --release -p quantica --example slh_dsa_sign_verify
//! ```
extern crate alloc;
// Bring `Vec` into scope for all submodules without forcing a per-file
// `use alloc::vec::Vec;`. The `vec!` macro is brought in via the
// `#[macro_use] extern crate alloc;` above.
pub use Vec;
// Shared Keccak-f[1600] core used by every algorithm. Crate-private:
// each algorithm exposes its own thin `sha3` wrapper module on top.
/// Pre-hash selector ([`prehash::PreHash`]) and `M′` message encoding
/// shared by the ML-DSA and SLH-DSA external signature APIs
/// (FIPS 204 §5.4 / FIPS 205 §10.2).
/// Zeroize-on-Drop wrappers for secret key material
/// ([`SecretBytes`](secret::SecretBytes), [`SecretArray`](secret::SecretArray)).
// Shared dependency-free JSON/`.rsp` helpers for the in-crate `acvp_internal`
// KAT modules (which drive the `pub(crate)` `*_internal` functions).