Skip to content

fips: define and implement a FIPS-compliant deployment story (no strategy exists today) #296

Description

@allamiro

No issue covered this; searched fips|crypto|aws-lc|boring across all open and closed issues and found nothing. Filing to define the strategy before it is promised to anyone.

Where we actually stand

# Cargo.toml
rustls      = { version = "0.23", default-features = false, features = ["ring", "std"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] }

ring is not FIPS 140-validated and there is no path to making it so. It has never been submitted, and its maintainer has said it is not a goal. So today VTOP cannot be deployed into a FIPS-constrained environment at all, regardless of how the OS is configured — the TLS in this process does not use the OS crypto library.

That last point is the one most likely to be misunderstood: running on a FIPS-enabled RHEL host does not make VTOP's TLS FIPS-compliant, because rustls+ring is statically linked and never calls OpenSSL. A deployment could pass an OS-level check and still be non-compliant in the transport that matters.

What a real FIPS story requires

1. Crypto provider. The viable route is aws-lc-rs with its fips feature, which builds AWS-LC-FIPS — a module with a FIPS 140-3 certificate. rustls supports it as a first-class provider, so this is a provider swap rather than a rewrite. Consequences to accept up front:

  • The FIPS build needs a C toolchain and CMake at build time (the builder stage already has both for librdkafka, so this is cheaper for us than for most projects).
  • Provider selection becomes explicit — CryptoProvider::install_default — rather than the implicit default. That is a change every TLS construction site inherits, and there are 37 of them.
  • aws-lc-rs in FIPS mode restricts the cipher suite and curve set. Any suite we pin must be checked against it.

2. What else does crypto that is not rustls. This is where FIPS claims usually fall apart, and it needs an inventory before any promise is made:

  • BLAKE3 — used for manifest MACs, the chunk tree, segment content roots, and the derived producer id. BLAKE3 is not a FIPS-approved algorithm. This is the hard part: it is not a transport detail that can be swapped, it is the integrity substrate of the segment format, the commit statements, and vtopctl segment verify. A FIPS deployment would need an approved digest (SHA-256/SHA-384) for anything that counts as a security function, which means a format decision, not a dependency bump.
  • librdkafka / OpenSSL for the Kafka adapter, which does use the system provider and so has a different (easier) FIPS story.
  • AWS SDK for S3, and whatever sqlx/libpq use for PostgreSQL TLS.

Deciding which of these are "security functions" under FIPS and which are non-security integrity checks is the substantive question. A checksum for corruption detection is defensible as non-security; a keyed MAC that authenticates a commit statement is not.

3. Container and base OS. A FIPS image usually means a certified base (UBI with the FIPS-enabled OpenSSL, or a distro whose module has a certificate) and, on Linux, fips=1 in kernel boot parameters. Ours is debian:bookworm-slim, which has no FIPS certification. So this is a second image lineage, not a flag.

4. Build and release. A separate fips feature and a separate published image, because a FIPS build is not a superset — it is a different, more restricted binary, and shipping one image that claims both is how a false compliance claim gets made.

5. Validation. A FIPS claim is only worth what tests back it: assert the negotiated suite comes from the approved set, assert the provider in use at runtime, and gate the FIPS image in CI. Without this the claim is a README sentence.

Proposed staging

  • Inventory every cryptographic primitive, where it is used, and whether it is a security function under FIPS. Deliverable: a table in docs/SECURITY_MODEL.md. This is the prerequisite — everything else depends on the BLAKE3 answer.
  • Provider abstraction: install the rustls provider explicitly at startup and report it in the observability surface, so "which crypto is this process using" is answerable in the field. Useful on its own, independent of FIPS.
  • fips cargo feature building aws-lc-rs in FIPS mode; CI compiles it.
  • Decide the BLAKE3 question, with the format-compatibility consequences written down. Likely a v2-format variant with a pluggable digest, and likely the largest single piece of work here.
  • FIPS image lineage on a certified base, with the approved-suite assertions gated in CI.
  • Document the boundary honestly — what is FIPS-validated, what is merely FIPS-compatible, and what is out of scope. A partial claim stated precisely is far more useful than a broad one that does not survive an audit.

Milestone v0.5.0. Scoped after the durability arc deliberately: a FIPS build of a format whose integrity primitive is still being decided would have to be redone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions