Craton HSM

AWS-LC Backend (FIPS)

AWS-LC Backend (FIPS)

The craton-hsm-awslc crate implements the CryptoBackend trait on top of aws-lc-rs, the Rust binding to AWS-LC. When built with the fips feature, every classical cryptographic operation runs inside the FIPS 140-3-validated AWS-LC module. This is the intended software FIPS boundary for Craton HSM.

  • Crate: craton-hsm-awslc
  • Backend type: AwsLcBackend
  • License: BSL 1.1
  • MSRV: Rust 1.75
  • Status: production-ready

Build

FIPS-validated primitives require the fips feature, which in turn builds the AWS-LC FIPS module from source. The AWS-LC build script shells out to Go, so a Go 1.21+ toolchain must be on PATH at build time. Go is not a runtime dependency.

cargo build -p craton-hsm-awslc --features fips

Non-FIPS builds omit the feature:

cargo build -p craton-hsm-awslc

The produced binary has no Go runtime dependency. aws-lc-rs is pinned at =1.16.2 in the workspace lockfile.

Feature Flags

FlagDefaultEffect
fipsoffBuild the FIPS-validated AWS-LC module. Requires Go 1.21+ on PATH.

Algorithms

All of the following run inside the FIPS boundary when fips is enabled:

  • AES in GCM, CBC, CTR, and key-wrap modes (128 / 192 / 256-bit keys).
  • RSA PKCS#1 v1.5, RSA-PSS, and RSA-OAEP with a 2048-bit minimum modulus enforced on both sign and verify.
  • ECDSA on P-256 and P-384.
  • Ed25519 sign and verify.
  • ECDH on P-256 and P-384.
  • SHA-2 (SHA-256, SHA-384, SHA-512).
  • HKDF key derivation.
  • AES key wrap / unwrap (AES-KW).

FIPS Mode Interaction

Two constructors select the operating mode:

use craton_hsm_awslc::AwsLcBackend;
use craton_hsm::crypto::backend::CryptoBackend;

// FIPS mode: reject any operation outside the FIPS boundary.
let backend = AwsLcBackend::new_fips();

// Non-FIPS mode: use all primitives, including prehashed signing.
let backend = AwsLcBackend::new();

let key = backend.generate_aes_key(32, true)?;
let ct  = backend.aes_256_gcm_encrypt(key.as_ref(), b"plaintext")?;

In FIPS mode, the backend is fail-closed: every operation that cannot be served by an AWS-LC FIPS primitive returns HsmError::MechanismInvalid rather than falling back to software.

Unsupported Mechanisms

Two classes of operation are not available when fips_mode = true:

  1. SHA-1. Rejected everywhere. AES-128 key generation remains permitted because AES-128 / 192 / 256 are all FIPS-approved, but AES-256 is recommended for new keys.
  2. Prehashed signing. aws-lc-rs does not expose prehashed signature APIs, so the eight *_sign_prehashed and *_verify_prehashed methods fall back to RustCrypto (rsa, p256, p384) for the signature math. That path is not FIPS-validated. In FIPS mode it is rejected with MechanismInvalid; in non-FIPS mode it works.

AES-GCM Nonce Budget

The backend enforces the NIST SP 800-38D per-key 2^32 encryption limit. A per-key counter fingerprinted with SHA-256(key) tracks encryption operations; a key that exhausts its budget is permanently poisoned for the remainder of the process and cannot be re-armed.

The in-memory counter is sufficient for ephemeral keys. For long-lived keys that outlive the process, use the file-backed journal:

use craton_hsm_awslc::AwsLcBackend;

let backend = AwsLcBackend::new_fips_with_persistent_gcm_counter(
    "/var/lib/craton-hsm/gcm-counter.journal",
)?;
# Ok::<(), craton_hsm::error::HsmError>(())

Journal behaviour:

  • Loaded on startup and verified with an HMAC-SHA256 integrity footer.
  • Counters are flushed to disk with fsync after every 1024-count advance, on first-sight of a key, and on poison. Worst-case lost count on SIGKILL is bounded by the 1024-count batch.
  • An integrity-footer mismatch fails closed: every previously recorded fingerprint is treated as poisoned for this process.
  • A missing footer (e.g. a crash during write) triggers a warning; recorded values are honoured and the next flush writes a fresh footer.
  • The journal HMAC key is derived from the file path. This catches accidental truncation or cross-path swaps; it is not an attacker defence — an attacker with filesystem write access already has the keys.

Only the first new_*_with_persistent_gcm_counter call in a process installs the counter. To switch paths, restart the process.

Error Reporting

Failures surface through craton_hsm::error::HsmError. MechanismInvalid specifically indicates that the mechanism is intentionally unavailable in the current mode (FIPS mode + prehashed signing, FIPS mode + SHA-1, RSA under the 2048-bit minimum, etc.).

Safety

The crate contains no direct unsafe blocks. All FFI is contained in aws-lc-rs upstream. Private-key material is wrapped in Zeroizing buffers and wiped on drop.