# FIPS-mode builds
This document captures what it would take to ship an enprot binary whose
crypto stack is constrained to a FIPS-validated module. Issue #48 is
long-standing; this file is the design note that closes the issue.
## Current state
enprot's `--fips` flag selects the `nist` policy and enforces it at the
Rust level: only FIPS-approved algorithm names (sha3-{256,512},
pbkdf2-{sha256,sha512}, aes-256-gcm) are accepted, with salt length,
iteration count, and IV-width checks. The crypto operations themselves
run in the linked Botan library, which is built with its full default
algorithm set.
So the existing `--fips` mode is "policy-enforced FIPS-compliant
behaviour running on a non-FIPS-validated library". That is **not** a
FIPS 140-validated binary. To produce one, the underlying library
itself must be a validated module, and only its FIPS-approved
primitives may be called.
## What a real FIPS build needs
Three things, each non-trivial:
1. **OpenSSL 3.x FIPS provider**, built from source via
`./Configure enable-fips && make && make install_sw install_ssldirs`
followed by `openssl fipsinstall`. The provider is then loadable by
any OpenSSL consumer via the default provider registry.
2. **Botan 3 built against the OpenSSL FIPS provider**. As of Botan
3.12 the build-time flag is `--enable-modules=fips` together with
`--with-openssl` (so Botan's OpenSSL bindings delegate to the FIPS
provider). The Botan docs note that this is "wrapping OpenSSL FIPS",
not a separate Botan FIPS validation. The combined module inherits
OpenSSL 3.x's FIPS 140-2 certificate (#4282) for the primitives
Botan calls.
3. **Static linking of the whole stack** into the enprot binary so the
FIPS context is self-contained. That mirrors the existing
`ci/build-static/` matrix and adds OpenSSL FIPS to the per-target
build steps.
Even with all three, the resulting binary is "FIPS-capable" — claiming
actual compliance requires platform-specific certification paperwork
outside the scope of this repo.
## Why this issue is closed without a binary
The work above is real engineering, but its value depends on a
certification effort this project isn't currently pursuing. What we can
do (and have done):
- The `nist` policy already rejects every algorithm that wouldn't be
FIPS-permitted, including in the deterministic AES-GCM variants
introduced in PR #64 (`aes-256-gcm-det`, `aes-256-gcm-siv-det`).
- `--fips` is documented as a policy-mode flag, not a compliance claim.
- This document explains the path so anyone pursuing actual
certification has a starting point.
If you want to drive the FIPS build to completion:
1. Add a `ci/build-fips.sh` modeled on `ci/build-static.sh` that builds
OpenSSL with `enable-fips`, then Botan with `--with-openssl` and the
`fips` module, then statically links enprot.
2. Add a `.github/workflows/fips.yml` that runs the script and uploads
the resulting binary.
3. Update `ci/botan-modules` to include `openssl` and `fips` when the
`FIPS=1` env var is set.
4. Document the resulting binary's FIPS claims precisely — what
certificate is inherited, what's excluded, and where the security
boundary is.
## References
- OpenSSL FIPS module 3.x: https://www.openssl.org/source/
- Botan FIPS support notes: https://botan.randombit.net/handbook/fips.html
- NIST FIPS 140-3: https://csrc.nist.gov/projects/cryptographic-module-validation-program