Skip to content

[FEATURE] Add helper to detect FIPS mode OS/host; add crypto policy option #1846

@oberstet

Description

@oberstet

Feature Description

Some Linux distros like RHEL / Rocky Linux and Ubuntu can run in FIPS mode which will ensure that the system OpenSSL only provides/enables NIST approved algorithms.

On Linux, /proc/sys/crypto/fips_enabled is the standard Linux kernel interface to check, the behavior is:

  • In FIPS mode, the value in the file /proc/sys/crypto/fips_enabled will be set to 1.
  • If the kernel parameter was fips=0 then still the file would be created but with value 0.
  • If no kernel parameter was given, the "file doesn't exist" = "not in FIPS mode"

NIST/FIPS algorithm approval vs module validation

These are genuinely different things:

  • Algorithm approval (FIPS 186-5, SP 800-56A, etc.): "This cryptographic primitive is sound and approved for use."
  • Module validation (FIPS 140-3 CMVP): "This specific compiled binary, on these specific platforms, has passed our audit for correct implementation, self-tests, key zeroization, entropy handling, etc."

Cybersecurity and Compliance posture

Definition: An organization's overall security standing and regulatory adherence, encompassing the policies, controls, technologies, and practices that collectively determine its ability to protect assets, detect threats, respond to incidents, and demonstrate compliance with applicable standards and regulations.

A strong posture answers these questions clearly:

  • What cryptographic algorithms does our software use, and which are NIST-approved?
  • What happens when a user configures a non-compliant feature?
  • Can we demonstrate compliance to an auditor with documentation and logs?
  • How do we detect and respond to a compromise?

A user might have a compliance posture which requires to only use NIST/FIPS approved ciphers and cryptographic primitives.

WAMP cryptographic primitives

Autobahn|Python and Crossbar.io support all advanced cryptographic features of WAMP.

The NIST/FIPS approval status of the cryptographic primitives ("algorithms") used for these features is as follows:

Category Algorithm Usage in WAMP NIST/FIPS Compatible
Elliptic Curves
secp256r1 (P-256) Transport Encryption ✅ Yes (SP 800-186)
curve25519 Session Authentication (WAMP-Cryptosign) ✅ Yes (SP 800-186)
secp256k1 Data Signatures (Certificates, E2E) No
Hash Functions
SHA-256 Session Authentication (WAMP-Cryptosign) ✅ Yes (FIPS 180-4)
Keccak-256 Data Signatures (Certificates, E2E) No (differs from SHA3-256)
Signature Schemes
Ed25519 Session Authentication (WAMP-Cryptosign) ✅ Yes (FIPS 186-5)
ECDSA Data Signatures (Ethereum, Certificates, E2E) ⚠️ Depends on curve

Notes on ECDSA:

  • ECDSA + secp256r1 (P-256): ✅ FIPS compatible
  • ECDSA + secp256k1: ❌ Not FIPS compatible (Ethereum uses this)

For background references and intro reading, here are some good ones:

Run-time detection

To detect NIST/FIPS mode on Linux, here is a Python code draft:

import os
from pathlib import Path
from typing import NamedTuple


class FIPSStatus(NamedTuple):
    """System FIPS mode status."""
    enabled: bool
    kernel_fips: bool | None  # None if file doesn't exist
    openssl_fips: bool | None  # None if we can't determine


def get_kernel_fips_mode() -> bool | None:
    """
    Check Linux kernel FIPS mode via /proc/sys/crypto/fips_enabled.
    
    Returns:
        True:  FIPS mode enabled (file contains "1")
        False: FIPS mode disabled (file contains "0")
        None:  Cannot determine (file doesn't exist, not Linux, etc.)
    """
    fips_path = Path("/proc/sys/crypto/fips_enabled")
    
    try:
        content = fips_path.read_text().strip()
        return content == "1"
    except FileNotFoundError:
        # Kernel not booted with fips= parameter
        return None
    except (OSError, PermissionError):
        # Some other issue reading the file
        return None


def get_openssl_fips_mode() -> bool | None:
    """
    Check if OpenSSL is operating in FIPS mode.
    
    Returns:
        True:  OpenSSL FIPS provider is active
        False: OpenSSL not in FIPS mode
        None:  Cannot determine (OpenSSL not available, etc.)
    """
    try:
        # Python 3.9+ with OpenSSL 3.x
        import ssl
        # This is a bit of a hack - check if MD5 is available
        # In FIPS mode, MD5 should fail
        import hashlib
        try:
            # usedforsecurity=True is the default and will fail in FIPS mode
            hashlib.md5(b"test", usedforsecurity=True)
            return False  # MD5 worked, not in FIPS mode
        except ValueError:
            return True   # MD5 rejected, likely FIPS mode
    except Exception:
        return None


def get_fips_status() -> FIPSStatus:
    """
    Get comprehensive FIPS mode status.
    
    Returns a FIPSStatus with:
        - enabled: True if system appears to be in FIPS mode
        - kernel_fips: Kernel FIPS flag status
        - openssl_fips: OpenSSL FIPS mode status
    """
    kernel = get_kernel_fips_mode()
    openssl = get_openssl_fips_mode()
    
    # Consider FIPS enabled if kernel says so
    # (OpenSSL check is supplementary)
    enabled = kernel is True
    
    return FIPSStatus(
        enabled=enabled,
        kernel_fips=kernel,
        openssl_fips=openssl,
    )


def os_fips_enabled() -> bool:
    """Simple check: is the OS in FIPS mode?"""
    return get_fips_status().enabled

Run-time enforcement

We should add an environment variable to Autobahn:

# defaults to unrestricted
AUTOBAHN_CRYPTO_POLICY=nist-algorithms | unrestricted

and a CLI option to Crossbar.io:

--crypto-policy=nist-algorithms
--crypto-policy=unrestricted   # default

which makes it actively fail rather than just log or even silently run and thus break the user's compliance posture.

=> Fail-fast is better than fail-audit!

What it should do

At startup, when this flag is set:

  1. Reject configurations that enable: secp256k1 and keccak-256 (Ethereum integration)
  2. Log clearly:
[WARN] NIST-algorithms crypto policy active. The following features are disabled:
     - Ethereum integration (requires secp256k1, keccak-256)
     - [any others non-NIST algorithms for cryptographic use]
  1. Fail hard if a config file specifies disabled features:
[ERROR] Configuration error: Ethereum integration requires secp256k1 which is 
   not permitted under AUTOBAHN_CRYPTO_POLICY=nist-algorithms / --crypto-policy=nist-algorithms. Remove this flag or remove the Ethereum integration configuration.

WAMP Application Error URIs

We will also need to define a WAMP application error URI - as a WAMP client with Ethereum integration enabled might try to talk to a WAMP router without Ethereum integration enabled due to --crypto-policy=nist-algorithms!

Documentation framing

Be precise in our docs:

NIST-Algorithms Mode (AUTOBAHN_CRYPTO_POLICY=nist-algorithms / --crypto-policy=nist-algorithms)

When enabled, Autobahn|Python / Crossbar.io restricts cryptographic operations to algorithms
approved by NIST (FIPS 186-5, SP 800-56A, etc.).

This is a necessary but not sufficient condition for FIPS 140-3 compliance—full compliance also
requires using a FIPS-validated cryptographic module at the OS level.

This mode disables Ethereum integration, see https://wamp-proto.org/spec.html: Data Signatures (Ethereum, WAMP-Cryptosign Certificates, WAMP-E2E encryption).

Crypto Policy Summary

Summary for crypto policy:

Feature NIST-algorithms Mode
TLS transport (secp256r1) ✅ Allowed
WAMP-Cryptosign auth (Ed25519/curve25519/SHA-256) ✅ Allowed
WAMP-Cryptosign certificates with secp256k1 ❌ Blocked
WAMP E2E encryption (secp256k1/keccak256) ❌ Blocked
Ethereum integration ❌ Blocked

So core WAMP-Cryptosign authentication is actually NIST-algorithms compatible.

It's specifically the Ethereum-interop features (certificates with secp256k1 signatures, E2E using keccak256) that break compliance.

In Crossbar.io during startup, here is some draft code:

def check_fips_compatibility(config: Config) -> None:
    """Check FIPS mode compatibility at startup."""
    fips = get_fips_status()
    uses_non_nist = config.has_ethereum_bridge() or config.has_bitcoin_integration()
    
    if fips.enabled and uses_non_nist and not config.nist_only:
        log.warn(
            "System is in FIPS mode (kernel={kernel}, openssl={openssl}) "
            "but configuration uses non-NIST algorithms (Ethereum/secp256k1). "
            "Cryptographic operations may fail at runtime. "
            "Consider using --nist-only to catch this at startup.",
            kernel=fips.kernel_fips,
            openssl=fips.openssl_fips,
        )
    
    if config.nist_only and uses_non_nist:
        raise ConfigurationError(
            "Configuration error: Ethereum integration requires secp256k1 "
            "which is not permitted under --nist-only mode. "
            "Remove --nist-only or disable Ethereum features."
        )

Checklist

  • I have searched existing issues to avoid duplicates
  • I have described the problem clearly
  • I have provided use cases
  • I have considered alternatives
  • I have assessed impact and breaking changes

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions