FIPS 140-3 & Classified Compliance
This is a technical assessment of the kldload OpenZFS stack against FIPS 140-3 and broader classified/high-security deployment requirements. It is not marketing. Where the stack meets requirements, that is stated clearly. Where there are gaps, those are named, explained, and mitigated. An auditor should be able to read this page and know exactly where they stand.
FIPS 140-3 is the US federal standard for cryptographic modules. If you handle government data, process healthcare records subject to HIPAA, manage financial transactions under PCI DSS, or operate in defense or intelligence environments — you need FIPS-validated cryptography. This masterclass is an honest assessment of where the kldload OpenZFS stack stands relative to those requirements.
Where we're compliant, we'll show you. Where there are gaps, we'll name them and explain what needs to change to close them. The goal is to give you enough information to make a risk-informed decision and to write an accurate System Security Plan.
1. What FIPS 140-3 Actually Requires
FIPS 140-3 (Federal Information Processing Standard Publication 140-3) is the US government standard for cryptographic module validation. It replaced FIPS 140-2 and aligns with ISO/IEC 19790. It specifies requirements for the design and implementation of a cryptographic module — the hardware, software, or firmware that performs approved cryptographic operations.
Understanding what FIPS actually requires (versus what people assume it requires) is the first step toward an honest compliance assessment.
Cryptographic Module Validation
The module itself must be tested and certified by a NIST-accredited Cryptographic and Security Testing (CST) laboratory. It is not enough to use approved algorithms — the implementation must go through the Cryptographic Module Validation Program (CMVP) process and receive a certificate.
Approved Algorithms
FIPS-approved algorithms include: AES-128/192/256, SHA-2 (SHA-256, SHA-384, SHA-512), SHA-3, RSA 2048+, ECDSA P-256/P-384/P-521, HMAC-SHA-2, and approved DRBGs. Deprecated or prohibited: MD5, SHA-1 for signatures, DES, 3DES (after 2023), RC4, RSA below 2048 bits.
Security Levels 1–4
Level 1: basic security requirements, software-only implementations. Level 2: adds tamper-evident mechanisms. Level 3: adds tamper-resistance and identity-based authentication. Level 4: complete physical protection envelope. Most software implementations target Level 1 or 2.
The CMVP Process
The vendor submits the module to a CST lab. Testing takes 12–24 months and costs $500K–$1M+. The certificate covers a specific version of the module — any significant code change requires revalidation. NIST maintains the active validated modules list (CSRC).
2. The kldload Crypto Stack — What’s Where
The kldload stack has multiple cryptographic layers. Each one needs to be evaluated independently. This section goes component by component.
Kernel Crypto (Linux Kernel Crypto API)
STATUS: FIPS-validated modules available
The Linux kernel's crypto API is the foundation everything else rests on. On RHEL 9 (and CentOS Stream 9 in FIPS mode), Red Hat maintains FIPS-validated kernel crypto modules through the CMVP. The validation covers the in-kernel implementation of AES-GCM, AES-CBC, SHA-256, SHA-512, RSA, ECDSA, and the approved DRBGs.
kldload on CentOS Stream 9 or RHEL 9 can use these validated modules. The path:
# Install crypto-policies
dnf install -y crypto-policies crypto-policies-scripts
# Enable FIPS system-wide
update-crypto-policies --set FIPS
# Enable FIPS kernel mode (requires reboot)
grubby --update-kernel=ALL --args="fips=1"
reboot
# Verify after reboot
cat /proc/sys/crypto/fips_enabled # should print 1
sysctl crypto.fips_enabled # should print crypto.fips_enabled = 1
After this, the kernel enforces FIPS-only algorithms system-wide. Non-FIPS algorithms are unavailable at the kernel level — applications cannot use them even if they try.
OpenZFS Encryption
STATUS: FIPS-approved algorithm, not a validated module
OpenZFS native encryption uses AES-256-GCM via the Linux kernel's crypto API. AES-256-GCM is a FIPS-approved algorithm. But — and this matters for auditors — OpenZFS itself is not a FIPS-validated cryptographic module. The implementation has not gone through CMVP.
What this means in practice: OpenZFS encryption uses the right algorithm via a validated backend (the kernel crypto API on RHEL), but the OpenZFS code that calls that backend has not been independently tested by a CST lab. For strict FIPS compliance where the data-at-rest encryption must be a validated module, this is a gap.
Mitigation: LUKS underneath ZFS. LUKS (Linux Unified Key Setup) on RHEL 9 is FIPS-validated. Placing LUKS on the block device and running the ZFS pool on top of LUKS gives you a compliant encryption layer. ZFS still provides all of its features — snapshots, compression, send/receive replication — but encryption happens at the block level, not per-dataset.
# FIPS-compliant LUKS + ZFS layout
# Block device: /dev/sda
cryptsetup luksFormat --cipher aes-xts-plain64 \
--key-size 512 --hash sha256 /dev/sda
cryptsetup luksOpen /dev/sda zpool-crypt
zpool create tank /dev/mapper/zpool-crypt
# ZFS sees a plain block device and provides all ZFS features.
# LUKS provides the FIPS-validated encryption layer.
# No per-dataset ZFS encryption keys in this configuration.
WireGuard
STATUS: ChaCha20-Poly1305 is NOT a FIPS-approved algorithm
This is the most significant gap for FIPS deployments. WireGuard uses ChaCha20-Poly1305 as its only encryption algorithm. ChaCha20 is considered cryptographically sound by the community — it is what Google uses for HTTPS on mobile, and it is specified in IETF RFC 8439. NIST has not approved it for FIPS use. Full stop.
Enabling FIPS mode on RHEL (fips=1) disables ChaCha20 at the kernel level. WireGuard
stops working on a FIPS-mode system because its only algorithm becomes unavailable.
Mitigation: IPsec with IKEv2. IPsec using AES-256-GCM + SHA-384 + ECDH P-384 is fully FIPS-compliant. strongSwan and Libreswan both have FIPS modes. The backplane architecture — management plane, data plane, monitoring plane, storage plane — works identically with IPsec instead of WireGuard. Only the transport layer changes.
# strongSwan FIPS-compliant IKEv2 configuration
# /etc/strongswan.d/charon.conf
charon {
# Force FIPS-approved algorithms only
proposals = aes256gcm16-sha384-ecp384
esp_proposals = aes256gcm16-sha384-ecp384
}
# /etc/ipsec.conf
conn backplane-mgmt
keyexchange=ikev2
ike=aes256gcm16-sha384-ecp384!
esp=aes256gcm16-sha384-ecp384!
left=%any
leftcert=node-a-cert.pem
right=192.0.2.1
rightcert=node-b-cert.pem
auto=start
The exclamation mark suffix in strongSwan configuration means "only this algorithm, no fallback." Without it, IKE negotiation may fall back to non-FIPS algorithms.
TLS (OpenSSL, step-ca)
STATUS: OpenSSL FIPS provider available; Go-based tools require FIPS builds
OpenSSL 3.x ships a FIPS provider that implements a CMVP-validated cryptographic module. RHEL 9 includes a FIPS-validated OpenSSL. When FIPS mode is active, OpenSSL automatically loads the FIPS provider and restricts itself to approved algorithms.
# Verify OpenSSL FIPS provider is active
openssl list -providers
# Should show: fips (active)
# Verify FIPS-only operation
openssl speed -evp md5
# Should fail: md5 not allowed in FIPS mode
openssl speed -evp aes-256-gcm
# Should succeed
step-ca (used for internal PKI) is written in Go. Go's standard crypto library is not FIPS-validated by default. For strict FIPS environments, use a FIPS-validated Go build (Red Hat ships one for RHEL) or replace step-ca with an OpenSSL-based CA such as OpenCA or Dogtag PKI, which RHEL includes.
# On RHEL, use the system Go which is FIPS-aware
dnf install golang
# The RHEL golang package links against the system OpenSSL
# which is FIPS-validated. Applications built with it
# inherit FIPS compliance when fips=1 is set.
SSH (OpenSSH)
STATUS: Auto-configured by FIPS crypto policy
OpenSSH on RHEL/CentOS in FIPS mode automatically disables non-FIPS algorithms. The
update-crypto-policies --set FIPS command configures the system-wide crypto policy,
which OpenSSH reads from /etc/crypto-policies/back-ends/openssh.config.
What FIPS mode removes from SSH:
- chacha20-poly1305 cipher (ChaCha20 not FIPS-approved)
- ED25519 host keys and user keys (not NIST-approved curves)
- Diffie-Hellman group1 and group14 (deprecated key sizes)
What remains in FIPS SSH:
- aes128-gcm, aes256-gcm, aes128-ctr, aes256-ctr ciphers
- RSA and ECDSA (P-256, P-384, P-521) host and user keys
- hmac-sha2-256, hmac-sha2-512 MACs
- ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521 key exchange
Practical implication: if you have ED25519 SSH keys for users or automation, they need to be replaced with ECDSA P-256 or RSA-3072+ keys before enabling FIPS mode.
eBPF
STATUS: No FIPS implications — eBPF is not a cryptographic component
eBPF programs do not perform cryptographic operations in the kldload stack. They handle observability (packet counts, latency histograms, syscall tracing) and security monitoring (detecting anomalous behavior). None of these operations fall under FIPS's scope, which covers cryptographic modules specifically. eBPF is FIPS-neutral.
3. Enabling FIPS Mode on kldload (CentOS/RHEL Path)
Enabling FIPS mode on CentOS Stream 9 or RHEL 9 is a supported configuration. The steps are straightforward. What is not straightforward is the application audit that needs to happen first.
Pre-flight checklist
- Identify all applications using non-FIPS algorithms: ChaCha20, ED25519, MD5, SHA-1 for signing
- Replace WireGuard with IPsec (do this first — WireGuard will stop working)
- Regenerate any ED25519 SSH keys as ECDSA P-384 or RSA-3072
- Audit Go applications (step-ca, etc.) — use FIPS-aware Go builds or replace
- Verify LUKS is in place if using ZFS encryption for FIPS compliance
Enable FIPS mode
# Step 1: Install crypto-policies
dnf install -y crypto-policies crypto-policies-scripts
# Step 2: Set FIPS crypto policy
update-crypto-policies --set FIPS
# Step 3: Enable FIPS kernel parameter
# (this also triggers kernel-level FIPS enforcement after reboot)
fips-mode-setup --enable
# Step 4: Reboot
reboot
# Step 5: Verify FIPS mode is active
fips-mode-setup --check
cat /proc/sys/crypto/fips_enabled # prints: 1
# Step 6: Verify OpenSSL FIPS provider
openssl list -providers | grep -A2 fips
# Step 7: Verify SSH is using FIPS algorithms
ssh -Q cipher | grep -v chacha # chacha20 should not appear
ssh -Q key | grep -v ed25519 # ed25519 should not appear
# Step 8: Confirm audit subsystem
systemctl status auditd
auditctl -l | head -20
What changes after enabling FIPS mode
| Component | Before FIPS | After FIPS |
|---|---|---|
| SSH ciphers | AES + ChaCha20 | AES only |
| SSH keys | RSA, ECDSA, ED25519 | RSA 3072+, ECDSA P-256/384 |
| TLS | All ciphersuites | FIPS-approved only |
| WireGuard | Working | Broken (ChaCha20 unavailable) |
| OpenSSL | Full algorithm set | FIPS provider active, non-FIPS disabled |
| kernel crypto | Full algorithm set | FIPS-only algorithms |
| Go stdlib crypto | Full algorithm set | Must use RHEL FIPS Go build |
4. FIPS-Compliant Network Fabric (IPsec Replacing WireGuard)
When FIPS mode is enabled, WireGuard stops working. The replacement is IPsec with IKEv2 using FIPS-approved algorithms. The backplane architecture — isolated encrypted planes for management, data, monitoring, and storage — is transport-agnostic. The concepts are identical; only the tunnel implementation changes.
Algorithm selection for FIPS IPsec
The FIPS-compliant IKEv2 algorithm suite:
# IKE Phase 1 (key negotiation)
ike=aes256gcm16-sha384-ecp384!
# Algorithm breakdown:
# aes256gcm16 = AES-256-GCM with 128-bit ICV (FIPS approved)
# sha384 = SHA-384 (FIPS approved)
# ecp384 = ECDH P-384 (FIPS approved)
# ! = strict (no fallback to non-FIPS)
# IKE Phase 2 (ESP, the actual data encryption)
esp=aes256gcm16-sha384-ecp384!
# Same algorithms for the data channel
strongSwan FIPS configuration
# Install strongSwan
dnf install -y strongswan strongswan-libipsec
# /etc/strongswan.conf
charon {
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
}
# Enable FIPS mode in strongSwan
crypto_test {
required = yes
on_add = yes
}
}
# /etc/ipsec.conf — management plane (equivalent to wg1)
conn mgmt-plane
keyexchange=ikev2
ike=aes256gcm16-sha384-ecp384!
esp=aes256gcm16-sha384-ecp384!
left=192.0.2.1 # this node's public IP
leftsubnet=10.201.0.0/24 # management plane subnet
leftcert=node-a.pem
leftid=node-a.mgmt.internal
right=192.0.2.2 # peer's public IP
rightsubnet=10.201.0.0/24
rightcert=node-b.pem
rightid=node-b.mgmt.internal
auto=start
# Repeat conn blocks for:
# data-plane (10.200.0.0/24, equivalent to wg0)
# monitor-plane (10.202.0.0/24, equivalent to wg2)
# storage-plane (10.203.0.0/24, equivalent to wg3)
nftables for IPsec (same zone isolation concept)
# nftables — same architectural approach as WireGuard backplane
# Physical interface: allow only IKE (UDP 500) and ESP (protocol 50)
table inet backplane {
chain input {
type filter hook input priority 0; policy drop;
# IKEv2 key exchange
iifname "eth0" udp dport 500 accept
iifname "eth0" udp dport 4500 accept # NAT traversal
# ESP (encrypted IPsec data, protocol 50)
iifname "eth0" meta l4proto esp accept
# Established IPsec traffic decrypted by kernel
# arrives on the xfrm policy, not a WireGuard interface.
# Match by source subnet instead of interface.
ip saddr 10.201.0.0/24 accept # mgmt plane
ip saddr 10.202.0.0/24 accept # monitor plane
ip saddr 10.203.0.0/24 accept # storage plane
ct state established,related accept
loopback accept
drop
}
}
Performance comparison
| Metric | WireGuard | IPsec (IKEv2 + AES-GCM) |
|---|---|---|
| Throughput (10G NIC) | ~9 Gbps | ~6–8 Gbps (AES-NI accelerated) |
| Latency overhead | ~0.1ms | ~0.3ms |
| Setup complexity | Low (one config file) | High (IKE, certificates, policies) |
| FIPS compliant | No | Yes |
| Hardware acceleration | AES-NI (via kernel) | AES-NI (via kernel, same path) |
| Certificate management | Not required | Required (X.509) |
| Rekeying | Automatic | Automatic (IKE handles it) |
5. Data at Rest — FIPS-Compliant Encryption
Three options exist for data-at-rest encryption in a FIPS-compliant kldload deployment. Choose based on your compliance posture and operational requirements.
Option 1: LUKS + ZFS (fully FIPS-compliant)
LUKS on RHEL 9 uses dm-crypt backed by the kernel's FIPS-validated crypto API. This is the compliant path. ZFS runs on top of the LUKS volume and provides all of its features: snapshots, compression, send/receive replication, checksumming. The cost is that encryption is at the block level — all datasets share one key, and per-dataset key rotation requires re-encrypting the entire LUKS volume.
# FIPS LUKS configuration
# Use AES-XTS-plain64 (FIPS-approved, designed for disk encryption)
cryptsetup luksFormat \
--cipher aes-xts-plain64 \
--key-size 512 \ # 512 bits for XTS = 256-bit effective key
--hash sha256 \ # FIPS-approved hash for PBKDF2
--pbkdf pbkdf2 \ # FIPS-approved KDF
--iter-time 5000 \
/dev/sda
cryptsetup luksOpen /dev/sda data-encrypted
# Create ZFS pool on the LUKS device
zpool create -o ashift=12 \
-O compression=zstd \
-O acltype=posixacl \
-O xattr=sa \
tank /dev/mapper/data-encrypted
# ZFS datasets inherit all ZFS features
zfs create tank/data
zfs create tank/home
zfs snapshot tank/data@daily-$(date +%Y%m%d)
Note: zstd compression is FIPS-neutral (not a cryptographic algorithm, just compression).
ZFS checksumming (SHA-256 is the default for datasets using encryption) is also FIPS-neutral in this
context — it provides integrity, not confidentiality, and runs via the kernel crypto API.
Option 2: ZFS native encryption (defense in depth, not CMVP-validated)
ZFS native encryption uses AES-256-GCM via the kernel crypto API. The algorithm is FIPS-approved. The module (OpenZFS) is not CMVP-validated. Per-dataset encryption keys are possible. Key rotation per dataset is possible. This is the right choice if you need dataset-level granularity and can document the gap in your SSP as an accepted risk or compensating control.
# ZFS native encryption (FIPS-approved algorithm, not FIPS-validated module)
zpool create -o ashift=12 tank /dev/sda
zfs create -o encryption=aes-256-gcm \
-o keylocation=prompt \
-o keyformat=passphrase \
tank/sensitive
# Per-dataset keys provide granular access control
zfs create -o encryption=aes-256-gcm \
-o keylocation=file:///etc/zfs/keys/finance.key \
-o keyformat=raw \
tank/finance
Option 3: Belt and suspenders (LUKS + ZFS encryption)
Deploy both: LUKS on the block device for the compliance checkbox, ZFS native encryption on top for per-dataset key granularity. The auditor is satisfied by LUKS. The engineer is satisfied by per-dataset ZFS keys. Two separate encryption layers, two separate keys. Breaking one requires breaking both.
# Full belt-and-suspenders setup
cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 512 \
--hash sha256 --pbkdf pbkdf2 /dev/sda
cryptsetup luksOpen /dev/sda data-encrypted
zpool create tank /dev/mapper/data-encrypted
# ZFS encryption on top (per-dataset keys)
zfs create -o encryption=aes-256-gcm \
-o keylocation=prompt -o keyformat=passphrase \
tank/classified
6. Classification Levels and What They Require
NIST 800-171 / CMMC (Controlled Unclassified Information)
NIST 800-171 governs Controlled Unclassified Information (CUI) for defense contractors. CMMC (Cybersecurity Maturity Model Certification) builds on it. Both require FIPS 140-2/3 for cryptography protecting CUI.
| 800-171 Requirement | kldload Coverage | Status |
|---|---|---|
| FIPS cryptography (3.13.10) | FIPS mode + LUKS + IPsec | Ready with config |
| Access controls (3.1.x) | RBAC, nftables, Vault policies | Ready |
| Audit & accountability (3.3.x) | Vault audit, journald, auditd | Ready |
| Data integrity (3.13.8) | ZFS end-to-end checksums | Exceeds requirement |
| Incident response (3.6.x) | Process — not a platform feature | Process required |
| Media sanitization (3.8.x) | Crypto erase (LUKS key destroy) | Ready |
Assessment: kldload can meet NIST 800-171 with FIPS mode enabled, IPsec replacing WireGuard, LUKS for data at rest, and Vault for secrets management. The WireGuard-to-IPsec migration and LUKS deployment are the two changes required. Everything else is configuration.
FedRAMP (Cloud Deployments for Federal Agencies)
FedRAMP is the federal authorization framework for cloud services. It requires FIPS 140-2/3 for all cryptographic operations, continuous monitoring with evidence, and vulnerability scanning.
kldload can achieve FedRAMP compliance with:
- FIPS mode (kernel crypto, OpenSSL FIPS provider)
- IPsec fabric for encrypted transit
- LUKS for data at rest
- Prometheus + eBPF for continuous monitoring
- OpenSCAP for automated compliance scanning and evidence generation
- Vault for secrets management with full audit log
The gap is documentation, not technology: FedRAMP requires a System Security Plan (SSP), Plan of Action and Milestones (POA&M), and Security Assessment Report (SAR). These are process deliverables, not software features.
DoD IL4/IL5 (Impact Level 4/5)
DoD Impact Levels 4 and 5 cover sensitive government information and national security systems respectively. They add stricter requirements on top of FedRAMP: DISA STIG compliance, specific approved baselines, and more rigorous access controls.
Assessment: The kldload backplane architecture with IPsec and nftables zone isolation meets the network isolation intent of IL4/IL5. The platform architecture — encrypted transits, firewalled perimeters, checksummed storage, full audit logging, identity-based access via Vault — maps cleanly to the IL4/IL5 control families.
The gap: DISA STIGs must be applied, and a STIG for OpenZFS does not exist. See Section 8 for how to handle this.
Classified (Secret / Top Secret)
Classified environments require an Authority to Operate (ATO) from the accreditation authority. The technology stack is one input. The classification requirements go well beyond algorithm selection.
Where kldload has genuine strengths for classified deployments:
- Air-gapped installation: darksites contain the complete package mirror — no internet required
- No telemetry: kldload phones home to nothing
- No external dependencies at runtime: the installed system has no cloud callbacks, no license servers, no update channels
- ZFS integrity: end-to-end checksums detect any modification to stored data
- Reproducible builds: the ISO is built from source in a container; the build process is auditable
Classified environments have requirements outside the technology scope of any installer:
- Cross-domain guards (CDS) for data moving between classification levels — not in scope
- TEMPEST shielding — hardware concern, not software
- Personnel security clearances — administrative concern
- Physical security controls — facilities concern
- Formal ATO process through the appropriate accreditation body
7. DISA STIGs and RHEL 9 Compliance
DISA STIGs (Security Technical Implementation Guides) are DoD-mandated security configuration baselines for specific products. Applying the relevant STIGs is required for IL4+ environments and strongly recommended for any regulated deployment.
Available STIGs
| Product | STIG Status | Notes |
|---|---|---|
| RHEL 9 | Exists, well-maintained | DISA STIG for RHEL 9 is comprehensive and regularly updated |
| CentOS Stream 9 | Partial | RHEL 9 STIG applies with minor differences; not officially supported by DISA |
| OpenZFS | Does not exist | No DISA STIG for OpenZFS. Must document as compensating controls in SSP. |
| WireGuard | Does not exist | Moot if replaced with IPsec (strongSwan has guidance documents) |
| strongSwan | NSA guidance exists | No formal DISA STIG, but NSA IPsec configuration guidance covers it |
| Vault | Guidance documents exist | No formal STIG; CIS benchmark for Vault covers most requirements |
Applying the RHEL 9 STIG with OpenSCAP
# Install OpenSCAP
dnf install -y openscap-scanner scap-security-guide
# List available RHEL 9 STIG profiles
oscap info /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml | grep stig
# Run a STIG compliance scan
oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_stig \
--results /tmp/stig-results.xml \
--report /tmp/stig-report.html \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# Apply STIG remediations (Ansible playbook)
oscap xccdf generate fix \
--profile xccdf_org.ssgproject.content_profile_stig \
--fix-type ansible \
--output stig-remediation.yml \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
ansible-playbook -i localhost, stig-remediation.yml
Handling the OpenZFS STIG gap
OpenZFS has no DISA STIG. The approach for auditors and SSPs is to document ZFS security properties as compensating controls:
- Data integrity: ZFS uses SHA-256 (or SHA-512 with HMAC) end-to-end checksums on all data. Corruption or tampering is detected and logged. This exceeds what POSIX filesystems provide.
- Encryption: AES-256-GCM at the dataset level (or LUKS at the block level for FIPS). See Section 5.
- Access controls: ZFS datasets support POSIX ACLs and NFS ACLs; dataset permissions can be delegated granularly (
zfs allow). - Immutability: ZFS snapshots cannot be modified after creation. This provides forensic integrity for audit data stored in ZFS datasets.
- No SUID in datasets: individual datasets can be mounted
nosuid,noexecto reduce privilege escalation risk.
8. Air-Gapped Deployment — Where kldload Excels
kldload was designed from the start for offline installation. The darksites — complete APT and RPM package mirrors baked into the ISO — mean the installer never reaches the internet during deployment. This is a significant advantage in classified and high-security environments where internet connectivity is restricted or prohibited.
What "offline" means for kldload
- All packages for all supported distros are in the ISO image
- No DNS lookups to external resolvers during install
- No certificate validation against internet CAs during install
- No telemetry, no phone-home, no license activation
- The installed system has no configured external package mirrors by default
Air-gapped update procedure
For air-gapped environments, the update workflow is:
- Build a new ISO on an internet-connected build system:
./deploy.sh build - Transfer the ISO to the air-gapped network via approved media (USB, DVD, network diode)
- Boot the target system or a staging system from the new ISO
- Run the installer (or mount the darksite and update packages manually)
- For rolling updates without reinstall: export the darksite from the ISO and configure it as a local package mirror
# Extract darksite from ISO for use as local mirror (air-gapped update)
mkdir /mnt/iso
mount -o loop kldload-1.0.2.iso /mnt/iso
# RPM darksite is at /mnt/iso/darksite/
# Copy to local mirror server
rsync -av /mnt/iso/darksite/ /srv/mirrors/kldload/
# Configure nodes to use local mirror
cat > /etc/yum.repos.d/kldload-airgap.repo <<EOF
[kldload-airgap]
name=kldload Air-Gapped Mirror
baseurl=http://mirror.internal/kldload/centos/
gpgcheck=0
enabled=1
EOF
ZFS replication for air-gapped environments
For data movement in air-gapped networks where network ZFS replication is not possible,
zfs send to portable encrypted media provides a secure transfer path:
# Send snapshot to encrypted portable media
# (media is LUKS-encrypted before use)
zfs snapshot tank/classified@transfer-$(date +%Y%m%d)
# Pipe through encryption and write to media
zfs send -R tank/classified@transfer-$(date +%Y%m%d) | \
gpg --symmetric --cipher-algo AES256 \
--compress-algo none > /media/usb/transfer.zfs.gpg
# On receiving system (after physically transporting the media)
gpg --decrypt /media/usb/transfer.zfs.gpg | \
zfs receive tank/classified
9. Compliance Gap Analysis — Honest Summary
Two genuine gaps. Everything else is configuration.
| Requirement | kldload Status | Gap | Mitigation |
|---|---|---|---|
| FIPS kernel crypto | Ready | None | Enable FIPS crypto policy on RHEL/CentOS |
| FIPS data at rest | Partial | OpenZFS not CMVP-validated | LUKS underneath ZFS (FIPS-validated on RHEL) |
| FIPS data in transit | Gap | WireGuard uses ChaCha20 (not FIPS-approved) | Replace with IPsec IKEv2 (AES-256-GCM + SHA-384 + P-384) |
| FIPS TLS | Ready | None (OpenSSL FIPS provider) | Enable FIPS crypto policy; use RHEL Go build for Go services |
| FIPS SSH | Ready | None | Auto-configured by FIPS crypto policy |
| Audit logging | Ready | None | Vault audit + auditd + journald; configure retention per policy |
| Data integrity | Exceeds requirement | None | ZFS end-to-end checksums detect any modification; document in SSP |
| Access control | Ready | None | RBAC + nftables + Vault policies; configure per environment |
| Air-gapped install | Exceeds requirement | None | Darksite ISO is self-contained; no internet required |
| Continuous monitoring | Ready | None | Prometheus + eBPF; add OpenSCAP for compliance artifacts |
| STIG compliance | Partial | RHEL STIG exists; no OpenZFS STIG | Apply RHEL STIG via OpenSCAP; document ZFS controls as compensating controls |
| Vulnerability management | Gap | No built-in vulnerability scanner | Add OpenSCAP (dnf install openscap-scanner scap-security-guide) or Nessus |
| Media sanitization | Ready | None | Crypto erase: destroy LUKS header (cryptsetup erase) renders data unrecoverable |
| Key management | Ready | None | Vault for secrets; LUKS headers for disk keys; integrate with HSM for IL5+ |
10. Roadmap — Closing the Gaps
OpenZFS FIPS validation
OpenZFS would need to go through the CMVP process to become a FIPS-validated cryptographic module. This is technically possible but organizationally expensive:
- Budget: $500K–$1M for initial validation (CST lab fees, documentation, testing)
- Timeline: 12–24 months from submission to certificate
- Maintenance: revalidation required for each significant version that touches crypto code
- Ongoing cost: $100K–$300K per revalidation cycle
This is not something an open source project does casually. Red Hat funds RHEL's FIPS validation because enterprise customers with compliance requirements pay for RHEL subscriptions. The realistic path for FIPS + OpenZFS is: use LUKS as the compliant layer, document OpenZFS's use of kernel validated crypto in the SSP, and accept the CMVP gap as a risk with LUKS as the mitigating control.
If your organization needs FIPS-validated OpenZFS: the path is defined. Sponsor the CMVP validation. The OpenZFS project would likely cooperate — the technical groundwork (AES-256-GCM via kernel crypto API) is already correct. What is needed is the organizational and financial commitment to run the process.
WireGuard FIPS
Two scenarios where WireGuard could become FIPS-usable:
- NIST approves ChaCha20: NIST has been considering ChaCha20 for inclusion in SP 800-175B and related guidance. If approved, WireGuard becomes FIPS-compliant with no changes. This is not imminent but is not impossible given ChaCha20's widespread adoption and strong security properties.
- WireGuard variant with AES-GCM: The WireGuard protocol is deliberately simple and fixed-algorithm. A variant using AES-256-GCM exists in theory but not in production-quality implementation. This would be a significant development effort and would no longer be "WireGuard" in any meaningful sense.
Planned: kldload FIPS profile
A planned future addition is a kldload FIPS install profile that auto-configures the compliant stack:
- strongSwan IPsec instead of WireGuard in the network configuration
- LUKS + ZFS layout instead of ZFS-only
- FIPS crypto policy enabled from first boot
- ECDSA P-384 host keys instead of ED25519
- OpenSCAP STIG profile applied post-install
- Vault configured with audit log from first boot
This is the "do the right thing by default for FIPS environments" profile. It does not eliminate the gaps — OpenZFS is still not CMVP-validated, and the LUKS layer is still the compliance mechanism — but it makes the compliant configuration the default for users who select this profile.
11. Practical Recommendations by Environment
Homelab / Small Business
FIPS is not required. Use the full kldload stack as-is. WireGuard backplane, ZFS native encryption, step-ca for internal PKI. The cryptography is sound even if not FIPS-validated. Compliance frameworks don't apply at this scale.
Healthcare (HIPAA)
FIPS encryption is required for PHI systems. Enable FIPS mode on PHI hosts. Use LUKS for data at rest. Use IPsec or TLS (FIPS mode) for PHI data in transit. WireGuard is acceptable for non-PHI management traffic if PHI never traverses it.
Financial (PCI DSS)
FIPS mode is strongly recommended for cardholder data systems. PCI DSS v4 requires "strong cryptography" — AES-256 and SHA-256+ qualify. Enable FIPS crypto policy. WireGuard may be acceptable with documented risk acceptance; IPsec is the conservative choice.
Government (NIST 800-171 / CUI)
FIPS required. Replace WireGuard with IPsec on all systems handling CUI. LUKS for data at rest. Vault with full audit log. Apply RHEL STIG via OpenSCAP. Document OpenZFS compensating controls in SSP.
DoD (IL4+)
All of the above plus DISA STIG application, continuous monitoring artifacts (OpenSCAP scheduled scans), formal POA&M for OpenZFS gap, and coordination with your Authorizing Official. The kldload platform covers the technology; the AO covers the authorization.
Classified (Secret / TS)
All of IL4+ plus air-gapped deployment (kldload's strength), formal ATO through the accreditation body, and the full documentation suite. kldload's offline ISO is designed for this. No internet dependency during install or operation. ZFS replication via encrypted sneakernet for inter-enclave data movement.
Related pages
- Security Hardening Masterclass — hardening the OS, nftables policies, and system-level security controls
- TLS & PKI Masterclass — step-ca, certificate lifecycle, and internal PKI
- Backplane Networks Masterclass — the WireGuard-based backplane architecture (replace with IPsec for FIPS)
- ZFS Encryption Tutorial — ZFS native encryption setup and key management
- Secure Boot & Encryption — LUKS, TPM integration, and the boot chain
- Audit & Trust — Vault audit log, journald, and auditd configuration