Craton HSM
Windows CNG Backend
Windows CNG Backend
The craton-hsm-cng crate implements the CryptoBackend trait on top of
the native Windows Cryptography API: Next Generation (CNG, the BCrypt*
family). In FIPS mode, algorithm providers are opened with
BCRYPT_PROV_DISPATCH, restricting operations to Windows-validated
FIPS-approved algorithms.
- Crate:
craton-hsm-cng - Backend type:
CngBackend - License: BSL 1.1
- MSRV: Rust 1.75
- Platform: Windows only (Windows 10 / Windows Server 2016 or newer)
- Status: production-ready
Platform and Cross-Compilation
The full implementation is gated behind #[cfg(windows)]. On non-Windows
targets the crate compiles to a minimal stub whose new_fips() returns
HsmError::FunctionNotSupported, so portable applications can select
backends by target without sprinkling #[cfg] blocks through call sites.
When cross-compiling a workspace build from a non-Windows host, exclude the crate:
cargo build --workspace \
--exclude craton-hsm-cng \
--target aarch64-unknown-linux-gnu
This crate exposes no Cargo features. The Windows-specific
windows-sys dependency activates automatically via target triple.
Build Requirements
- Windows 10 / Windows Server 2016 or later.
- Rust 1.75+.
- Visual Studio 2022 with the "Desktop development with C++" workload, or an equivalent MSVC toolchain.
Algorithms
- AES in GCM, CBC, CTR, and key-wrap modes (128 / 192 / 256-bit).
- RSA PKCS#1 v1.5, PSS, and OAEP on 2048-, 3072-, and 4096-bit moduli.
- ECDSA and ECDH on P-256 and P-384.
- Ed25519 via RustCrypto's
ed25519-dalek. CNG does not expose Ed25519 directly, so this one operation is outside the CNG FIPS boundary and is rejected in FIPS mode. - SHA-2 via
BCryptCreateHash. - Hardware RNG via
BCryptGenRandom.
Usage
# #[cfg(windows)]
# {
use craton_hsm_cng::CngBackend;
use craton_hsm::crypto::backend::CryptoBackend;
// Non-FIPS: any Windows CNG-supported algorithm.
let backend = CngBackend::new(false);
// FIPS mode: providers opened with BCRYPT_PROV_DISPATCH so only
// FIPS-approved algorithms succeed.
let backend = CngBackend::new_fips()?;
let key = backend.generate_aes_key(32, true)?;
let ct = backend.aes_256_gcm_encrypt(key.as_ref(), b"plaintext")?;
# }
# Ok::<(), craton_hsm::error::HsmError>(())
FIPS via CNG
CngBackend::new_fips() opens providers with BCRYPT_PROV_DISPATCH.
That flag restricts which algorithms succeed, but it does not change
the OS FIPS policy. For the deployment to be genuinely FIPS-compliant,
the Windows FIPS-mode Group Policy must also be enabled:
Computer Configuration → Windows Settings → Security Settings → Local Policies → Security Options → "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing", or- equivalently, the registry value
HKLM\System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy\Enabled = 1.
Without that policy set, calling new_fips() restricts the algorithm
menu but the CNG module is not running inside its validated FIPS
configuration. Full FIPS 140-3 compliance with this backend is a
Windows property, not a crate property.
For a self-contained FIPS boundary that does not depend on OS policy,
use craton-hsm-awslc with the fips feature.
Safety (FFI / unsafe)
Every CNG / BCrypt call is unsafe extern FFI. The crate sets
#![forbid(unsafe_op_in_unsafe_fn)], so every FFI call site sits in an
explicit unsafe block with a SAFETY: comment naming the invariant
being upheld.
Three RAII wrappers — AlgHandle, KeyHandle, HashHandle — guarantee
that BCryptCloseAlgorithmProvider, BCryptDestroyKey, and
BCryptDestroyHash run on drop, so handle leaks on error paths are not
possible. Private-key material is wrapped in Zeroizing buffers.
NTSTATUS values returned by CNG are mapped to HsmError through a
typed mapping that covers 13+ documented codes (INVALID_HANDLE,
INSUFFICIENT_RESOURCES, NOT_FOUND, ACCESS_DENIED, INVALID_KEY,
BUFFER_TOO_SMALL, DEVICE_BUSY, and others) — no error-text string
matching.
Limitations
- Ed25519 is not FIPS under this backend. It runs in
ed25519-dalekbecause CNG does not expose it, so FIPS mode rejects it. - Prehashed signing uses RustCrypto and is outside the CNG FIPS
boundary, matching the
craton-hsm-awslccontract. - Non-Windows compilation produces a stub. Every constructor on a
non-Windows target either returns
FunctionNotSupporteddirectly or a backend that rejects every operation. Portable builds must pick a different backend on those targets. - AES-GCM AAD is not threaded through the
CryptoBackendtrait.
Related Documents
- AWS-LC backend — cross-platform FIPS boundary.
- Compatibility matrix — tested Windows versions.