Craton HSM

Enabling FIPS mode

Enabling FIPS mode

Craton HSM supports a FIPS-approved mode of operation when it is built against the AWS-LC backend and configured to reject non-approved mechanisms. This guide walks through the end-to-end enablement: pick the backend, rebuild, update the config, compute the integrity sidecar, and verify. For the policy reference — which mechanisms are approved, how the algorithm indicator works, what the self-tests cover — see FIPS mode and Self-tests.

Prerequisites

The FIPS build has a few extra native dependencies beyond the pure-Rust default:

ToolWhy
CMake 3.xAWS-LC uses CMake as its top-level build system.
Clang / LLVMAWS-LC's Rust bindings require libclang for bindgen.
GoAWS-LC's generator scripts are written in Go.

On Windows, set the following before building:

LIBCLANG_PATH=C:\path\to\llvm\bin
AWS_LC_SYS_NO_ASM=1

1. Select the AWS-LC backend

FIPS deployments must use the awslc-backend feature. This swaps the pure-Rust RustCrypto implementations for AWS-LC, which holds a FIPS 140-3 certificate. The default rustcrypto-backend is not FIPS validated and will not produce an approved mode of operation.

See Enterprise / AWS-LC backend for licensing, support, and platform coverage notes before committing to this backend in production.

2. Rebuild with the FIPS features

cargo build --release --features awslc-backend --no-default-features

The resulting target/release/libcraton_hsm.so (or craton_hsm.dll on Windows) embeds the AWS-LC FIPS module. Do not copy a non-FIPS build into a FIPS deployment even if the filename is the same — the integrity check in step 4 will not catch a backend mismatch, only a post-build modification.

If you are distributing the library to other hosts, build once and ship the resulting binary plus its .hmac sidecar (step 4). Do not rebuild per host.

3. Configure for FIPS-approved only

Open craton_hsm.toml (or the path in CRATON_HSM_CONFIG) and apply the FIPS-approved-only policy:

[algorithms]
# Use the FIPS-certified backend.
crypto_backend = "awslc"

# Reject every non-FIPS mechanism at C_*Init time.
fips_approved_only = true

# PQC is not yet FIPS-approved (as of CMVP's current module list).
# Disable it in FIPS deployments.
enable_pqc = false

# Already default; listed for operator awareness.
# allow_weak_rsa = false     # RSA < 2048 rejected.
# allow_sha1_signing = false  # SHA-1 is digest-only, never signing.

With fips_approved_only = true the module registers only approved mechanisms. The table below summarises the cut:

CategoryAllowedBlocked
SymmetricAES-128/192/256 GCM, CBC, CTR, Key Wrap
RSARSA-2048 / 3072 / 4096 with PKCS#1 v1.5, PSS, OAEPRSA < 2048
ECDSAP-256, P-384Any other curve
ECDHP-256, P-384Any other curve
DigestSHA-256 / 384 / 512, SHA3-256 / 384 / 512SHA-1 (digest available, signing blocked)
MACHMAC-SHA256 / 384 / 512
EdDSAEd25519 (not FIPS-approved)
PQCML-KEM, ML-DSA, SLH-DSA, hybrids

Key size minimums: RSA ≥ 2048, AES ≥ 128. Any C_GenerateKey / C_GenerateKeyPair below these is rejected.

4. Compute the integrity HMAC sidecar

Every C_Initialize verifies an HMAC-SHA256 of the shared library against a .hmac sidecar file. The sidecar is part of the POST — without it, the check is skipped and the module logs a warning (development mode). With it in place, a tampered binary is caught before any key material is touched.

Linux or macOS:

./tools/compute-integrity-hmac.sh target/release/libcraton_hsm.so

Windows:

.\tools\compute-integrity-hmac.ps1 -LibPath target\release\craton_hsm.dll

The script writes libcraton_hsm.hmac (or craton_hsm.hmac) next to the library. Recompute it after every rebuild; a stale sidecar triggers CKR_GENERAL_ERROR at C_Initialize and the module enters an error state that requires a process restart.

5. Verify the FIPS configuration

Start a session and confirm the module is behaving as expected.

C_Initialize passes POST

Enable info-level logs and launch any consumer. Look for the POST summary:

POST: integrity=OK
POST: KATs 16/16 passed (SHA-2, SHA-3, HMAC, AES-GCM, AES-CBC, AES-CTR, RSA, ECDSA, ML-DSA, ML-KEM, RNG, DRBG)

The counts include one software integrity test plus 16 algorithm KATs, for a total of 17 self-tests. See Self-tests for the complete list and what each test exercises.

Mechanism list matches the approved set

pkcs11-tool --module ./libcraton_hsm.so --list-mechanisms

Nothing outside the approved table above should appear. If CKM_EDDSA, CKM_ML_DSA_*, CKM_ML_KEM_*, or any non-approved mechanism shows up, fips_approved_only is not set or the build did not actually use the AWS-LC backend.

A sign / verify round trip shows fips_approved = true

Initialise a token, generate an RSA-2048 key, sign, verify:

pkcs11-tool --module ./libcraton_hsm.so --login --pin <USER_PIN> \
    --keypairgen --key-type RSA:2048 --label fips-test --id 01

pkcs11-tool --module ./libcraton_hsm.so --login --pin <USER_PIN> \
    --sign --mechanism SHA256-RSA-PKCS --label fips-test \
    --input-file /etc/hostname --output-file sig.bin

pkcs11-tool --module ./libcraton_hsm.so \
    --verify --mechanism SHA256-RSA-PKCS --label fips-test \
    --input-file /etc/hostname --signature-file sig.bin

Inspect the audit log entry for that Sign call; the JSON record carries "fips_approved": true:

{
  "operation": {
    "Sign": {
      "mechanism": 7,
      "fips_approved": true
    }
  },
  "result": "Success"
}

The same flag is exposed per session as last_operation_fips_approved (queryable through the craton-admin tooling) and is reserved on objects as the vendor attribute CKA_VENDOR_FIPS_APPROVED = 0x80000001.

craton-admin status

Where available, run the administrative CLI to confirm module state:

craton-admin status

The status output includes the active backend (awslc), the fips_approved_only flag, POST state, and whether the integrity sidecar was matched at C_Initialize. If your deployment does not ship craton-admin, the same information is available in the structured logs; see Self-tests for log field names.

What changes operationally

Switching to FIPS-approved mode is not purely cosmetic — a number of call sites that work in the default mode will start returning errors. Audit ahead of cutover.

ChangeSymptomFix
SHA-1 signing is rejected.CKR_MECHANISM_INVALID for CKM_SHA1_RSA_PKCS, CKM_ECDSA_SHA1, etc.Switch the caller to SHA-256 or stronger. SHA-1 remains available as a digest for non-signing purposes.
RSA below 2048 bits is rejected.CKR_KEY_SIZE_RANGE at C_GenerateKeyPair or C_*Init.Re-issue keys at 2048 or larger.
Ed25519 is blocked.CKR_MECHANISM_INVALID for CKM_EDDSA.Use ECDSA P-256 or P-384 in FIPS deployments.
PQC mechanisms are blocked.CKR_MECHANISM_INVALID for CKM_ML_* / CKM_SLH_*.Wait for CMVP approval, or run a parallel non-FIPS module for PQC-only workloads. See Post-quantum migration.
Failed POST locks the module.Every subsequent call returns CKR_GENERAL_ERROR.Restart the process; a failed self-test is not recoverable in place by design.
Pairwise consistency runs on every C_GenerateKeyPair.Slightly slower keygen than the default build.No fix required — this is the conditional self-test mandated by IG 10.3.A.
Continuous RNG health tests run on every C_GenerateRandom.Extra work per random draw.No fix required.

Deployment checklist

  • Built with --features awslc-backend --no-default-features.
  • crypto_backend = "awslc" in craton_hsm.toml.
  • fips_approved_only = true.
  • enable_pqc = false (unless you have an explicit non-FIPS side channel for PQC).
  • .hmac sidecar computed against the exact binary being deployed.
  • C_Initialize returns CKR_OK and the log records all 17 self-tests passing.
  • pkcs11-tool --list-mechanisms shows only approved mechanisms.
  • Token initialised with strong SO PIN and user PIN.
  • A representative sign / verify path logs fips_approved = true.
  • cargo test --features awslc-backend --no-default-features -- --test-threads=1 passes on the build host.
  • Audit log review procedure documented for the operator on-call rotation.