# Configuration Reference
Craton HSM is configured via a TOML file. By default, it looks for `craton_hsm.toml` in the current working directory. Override the path with the `CRATON_HSM_CONFIG` environment variable.
If the config file is not found, secure defaults are used. If the config file exists but cannot be parsed or fails validation, `C_Initialize` returns `CKR_GENERAL_ERROR` (the module refuses to start with potentially misconfigured security parameters).
In FIPS mode (`CRATON_HSM_FIPS=1` or `--features fips`), config files are ignored and hardcoded secure defaults are used.
### Configuration Validation (v0.9.1)
The following validation rules are enforced on load:
- `storage_path` and `log_path`: must be relative, no `..` traversal, no UNC paths (`\\server\share`), no null bytes
- `pin_min_length` ≥ 4; `pin_max_length` ≥ `pin_min_length`
- `pbkdf2_iterations` ≥ 100,000
- `max_failed_logins`: 3–100 (prevents accidental lockout or brute-force)
- `serial_number`: 1–16 ASCII printable characters
- `slot_count` ≥ 1
- `crypto_backend`: must be `"rustcrypto"` or `"awslc"`
- `log_level`: must be `"all"`, `"crypto"`, `"auth"`, `"admin"`, or `"none"`
## Environment Variables
| `CRATON_HSM_CONFIG` | `craton_hsm.toml` | Path to the configuration file |
| `RUST_LOG_FORMAT` | `text` | `craton-hsm-daemon` log formatter: `text` (human-readable, default), `json` (structured — consume directly in Loki / ELK / Datadog), or `compact` (slightly smaller per-record than `text`). Unknown values fall back to `text` and emit a `warn!` after init. |
## `[token]` — Token & Slot Settings
| `label` | string | `"Craton HSM Token 0"` | Token display name (returned by `C_GetTokenInfo`) |
| `storage_path` | string | platform default (see below) | Path to the redb persistent storage database. May be absolute or CWD-relative. Rejected: `..` traversal, UNC paths, null bytes, and any component that is a symlink. Default: `/var/lib/craton-hsm/store` on Unix and `%PROGRAMDATA%\craton-hsm\store` on Windows when the parent system directory exists, otherwise falls back to the legacy relative `craton_hsm_store` (with a startup warning). |
| `max_sessions` | integer | `100` | Maximum concurrent PKCS#11 sessions |
| `max_rw_sessions` | integer | `10` | Maximum read-write sessions |
| `persist_objects` | bool | `false` | Persist token objects to disk (AES-256-GCM encrypted) |
| `slot_count` | integer | `1` | Number of virtual slots to expose (must be ≥ 1) |
| `serial_number` | string | `"0000000000000001"` | Token serial number (max 16 chars, ASCII printable) |
## `[security]` — PIN & Authentication
| `pin_min_length` | integer | `8` | Minimum PIN length in bytes (must be ≥ 4) |
| `pin_max_length` | integer | `64` | Maximum PIN length in bytes (must be ≥ pin_min_length) |
| `max_failed_logins` | integer | `10` | Failed login attempts before PIN lockout (range: 3–100) |
| `pbkdf2_iterations` | integer | `600000` | PBKDF2-HMAC-SHA256 iterations for PIN hashing (must be ≥ 100,000; SP 800-132) |
## `[algorithms]` — Cryptographic Policy
| `crypto_backend` | string | `"rustcrypto"` | Crypto backend: `"rustcrypto"` (default) or `"awslc"` (requires [craton_hsm-enterprise](https://github.com/craton-co/craton-hsm-core-enterprise)) |
| `fips_approved_only` | bool | `false` | Restrict to FIPS 140-3 approved algorithms only |
| `enable_pqc` | bool | `true` | Enable post-quantum mechanisms (ML-KEM, ML-DSA, SLH-DSA) |
| `allow_weak_rsa` | bool | `false` | Allow RSA key sizes below 2048 bits |
| `allow_sha1_signing` | bool | `false` | Allow SHA-1 in signing contexts (deprecated per SP 800-131A) |
| `derived_keys_extractable_by_default` | bool | `false` | Derived keys whose template omits `CKA_SENSITIVE` / `CKA_EXTRACTABLE` are non-sensitive and extractable (see below). Not allowed with `fips_approved_only` |
### Derived key defaults
`C_DeriveKey` (and the daemon `DeriveKey` RPC) honour `CKA_SENSITIVE` and `CKA_EXTRACTABLE`
in the derivation template. When the template leaves them unset, derived keys are sensitive and
non-extractable, so their value cannot be read back.
Some callers read the derived secret without asking for a readable key. Java SunPKCS11's ECDH
`KeyAgreement` is the common case. Either enable `derived_keys_extractable_by_default`, or keep
the secure default and add this to the SunPKCS11 configuration:
```
attributes(generate, CKO_SECRET_KEY, CKK_GENERIC_SECRET) = {
CKA_SENSITIVE = false
CKA_EXTRACTABLE = true
}
```
### FIPS Approved Mode
When `fips_approved_only = true`:
**Allowed**: RSA (>=2048), ECDSA (P-256, P-384), AES (GCM/CBC/CTR), SHA-256/384/512, SHA3-256/384/512, ECDH, AES Key Wrap
**Blocked**: EdDSA (Ed25519), SHA-1 signing, all PQC mechanisms, RSA < 2048
See [FIPS Mode Guide](fips-mode-guide.md) for deployment details.
## `[audit]` — Audit Logging
| `enabled` | bool | `true` | Enable tamper-evident audit logging |
| `log_path` | string | `"craton_hsm_audit.jsonl"` | Path to the append-only audit log file |
| `log_level` | string | `"all"` | Log verbosity: `"all"`, `"crypto"`, `"auth"`, `"admin"`, or `"none"` |
## `[daemon]` — gRPC Server (craton-hsm-daemon only)
| `bind` | string | `"127.0.0.1:5696"` | gRPC listen address and port |
| `tls_cert` | string | *(none)* | Path to PEM server certificate file |
| `tls_key` | string | *(none)* | Path to PEM server private-key file |
| `tls_client_ca` | string | *(none)* | PEM CA bundle for mandatory client-certificate validation (mTLS) on non-loopback binds |
| `tls_client_crl` | string | *(none)* | PEM/DER client-certificate revocation list, used with `tls_client_ca` |
| `allow_unauthenticated_tls` | bool | `false` | Explicitly permit server-authentication-only TLS on a non-loopback bind; only use behind an independent access-control boundary |
TLS on `127.0.0.1` and `[::1]` may omit `tls_client_ca` for local development. Any non-loopback TLS listener fails closed without mTLS unless `allow_unauthenticated_tls = true` is explicitly set.
## Example: Default Configuration
```toml
[token]
label = "Craton HSM Token 0"
storage_path = "craton_hsm_store"
max_sessions = 100
max_rw_sessions = 10
persist_objects = false
slot_count = 1
[security]
pin_min_length = 8
pin_max_length = 64
max_failed_logins = 10
pbkdf2_iterations = 600000
[algorithms]
crypto_backend = "rustcrypto"
fips_approved_only = false
enable_pqc = true
allow_weak_rsa = false
allow_sha1_signing = false
[audit]
enabled = true
log_path = "craton_hsm_audit.jsonl"
log_level = "all"
```
## Example: FIPS 140-3 Deployment
```toml
[algorithms]
crypto_backend = "awslc"
fips_approved_only = true
enable_pqc = false
allow_weak_rsa = false
allow_sha1_signing = false
[security]
pbkdf2_iterations = 600000
max_failed_logins = 5
[audit]
enabled = true
log_level = "all"
```
## Example: High-Session Server
```toml
[token]
max_sessions = 1000
max_rw_sessions = 100
persist_objects = true
slot_count = 4
```