This page enumerates the adversaries Craton HSM defends against, the
attack surfaces exposed by the module, and the mitigations in place. It
complements the high-level model by taking a STRIDE-style view
of concrete threats rather than describing protection layers.
Where a threat is out of scope, the reason is stated. Deployments with
stronger threat models (regulated workloads, multi-tenant SaaS, exposed
network services) should combine Craton HSM with the OS, network, and
physical controls described in hardening.
| Class | Capabilities | Example |
|---|
| Local unprivileged | Runs a process on the same host under an unprivileged account. No elevated privileges, no code execution in the HSM process. | A compromised non-root service on a shared Linux host. |
| Local privileged | Root or Administrator on the host. Can read arbitrary memory, install kernel modules, modify binaries. | A malicious system administrator; a kernel-level rootkit. |
| Remote (unauthenticated) | Reachable over the network to the gRPC daemon; no valid client certificate. | Internet-facing port, leaked listen address. |
| Remote (authenticated) | Holds a valid client certificate or session credential with limited role. | Compromised application host in the same VPC. |
| Supply chain | Can influence a dependency, a build artefact, or an upstream toolchain. | Compromised crate on crates.io; malicious CI runner. |
| Physical | Hands-on access to the host. Can dump RAM, replace storage media, boot into a recovery environment. | Stolen laptop; disgruntled data-centre employee. |
| Threat | Mitigation |
|---|
| Caller claims to be the Security Officer or a User without authentication | Session state machine requires C_Login with the correct role before privileged operations; every service checks the state, not a flag |
| Impersonate a remote client to the gRPC daemon | Mutual TLS; client certificate validated against a configured trust store with optional CRL |
| Replay a PIN captured over a passive observation channel | PINs travel only inside the TLS channel; out-of-band capture is out of scope |
| Threat | Mitigation |
|---|
| Modify the module binary on disk before load | HMAC-SHA256 sidecar integrity check at POST; FIPS build requires the sidecar to be present |
| Modify the persistent object database while offline | Per-object AES-256-GCM authenticated encryption; tampering produces decryption failure on load |
Inject malicious attributes via C_CreateObject or C_SetAttributeValue | Template parser enforces CKA_CLASS presence, type sizes, and mutual consistency (e.g. SENSITIVE=true is incompatible with subsequent EXTRACTABLE=true via C_SetAttributeValue) |
| Forge audit log entries | Chained SHA-256 hashes; any insertion, deletion, or reordering breaks the chain |
| Threat | Mitigation |
|---|
| Operator denies performing a privileged operation | Every operation that touches key material or authentication writes an audit entry synchronously before returning; entries include the session handle, operation, mechanism, result, and timestamp |
| Missing entries around a suspicious operation | Chained hashes detect deletion; a break in the chain points at the region that was modified |
| Threat | Mitigation |
|---|
| Key bytes leak through debug output | Custom Debug impls print [REDACTED]; key types never derive Debug |
| Key bytes leak through error messages | Errors are mapped to generic CK_RV codes; the error mapping in src/error.rs never includes runtime values |
| Key bytes remain in swap after process exit | mlock/VirtualLock on allocation; zeroize-then-munlock on drop |
| Timing side-channel on PIN verification | PBKDF2 dominates the runtime; subtle::ConstantTimeEq prevents byte-by-byte leakage |
| Timing side-channel on HMAC verification | subtle::ConstantTimeEq on tag comparison |
Key material leaks via CKA_VALUE read | CKA_SENSITIVE=true, CKA_EXTRACTABLE=false returns CKR_ATTRIBUTE_SENSITIVE; default for generated keys is both true/false respectively |
| Core dumps after a crash expose memory | Operator responsibility — ulimit -c 0 and disabling systemd-coredump is part of the hardening guide |
| Threat | Mitigation |
|---|
| Panic inside the module crashes the host process | catch_unwind wraps every extern "C" export; panics are converted to CKR_GENERAL_ERROR |
| Malformed templates or mechanism parameters cause undefined behaviour | Input validation at the ABI layer; all buffers bounds-checked by Rust ownership; panic-on-error paths return errors |
| Concurrent processes corrupt the persistent database | Exclusive flock at open time; second opener receives an error |
| Authentication brute force | PIN lockout after configurable N failures (default 10) per role |
| Oversized RSA keys | Maximum 16384-bit modulus; keys above the limit are rejected |
| AES-GCM nonce exhaustion | Per-key counter with 2^31 limit and graduated warnings at 50%/75%/90%/95%/99% |
| Threat | Mitigation |
|---|
| Non-approved mechanism used in a FIPS deployment | fips_approved_only = true rejects non-approved mechanisms at *Init time; C_GetMechanismList returns only the approved subset |
| Keys past their end date still used for signing | SP 800-57 lifecycle: deactivated keys are rejected for sign/encrypt/wrap/derive |
| Forked child inherits parent session state and corrupts RNG / audit chain | PID comparison on every PKCS#11 call; child receives CKR_CRYPTOKI_NOT_INITIALIZED until it re-initialises — see fork-safety |
| Multiple processes open the same persistent database | flock prevents concurrent open; the daemon is the supported path for multi-process access |
| Threat | Why out of scope |
|---|
| Cold-boot RAM extraction | Physical access required; mlock prevents swap only, not physical dumps |
| DMA or bus-snooping attacks | Require IOMMU and platform-level mitigation outside the module |
| OS kernel compromise | A hostile kernel can read all process memory; operator must harden the OS |
| Power analysis / EM emanation | Hardware-level side-channels; software HSMs cannot mitigate |
| Spectre / Meltdown-class speculative execution attacks | Depend on CPU microcode and kernel patches |
| Cache-timing on systems without AES-NI | Modern x86/ARM ships with AES instructions; pre-Westmere hardware is not a supported platform |
| Social engineering | Outside any technical control |
| Vulnerabilities in upstream dependencies | Reported to the upstream project; cargo audit and cargo deny run in CI to detect advisories early |
FIPS boundary <--- aws-lc-rs (when the awslc-backend is linked)
Module boundary <--- everything described on this page
Application boundary <--- calls into the module; enforces RBAC, quotas, etc.
Network boundary <--- untrusted; all inputs validated, mTLS required
Anything crossing a boundary inward is treated as untrusted. Anything
crossing outward is a potential leakage path and is audited or redacted.
Cargo.lock committed; exact versions pinned.
cargo audit runs in CI against the RustSec advisory database.
cargo deny check advisories licenses gates merges on licence and
vulnerability policy.
- Release artefacts are signed (GPG, Sigstore/cosign, or Windows
Authenticode depending on the platform).
- The integrity HMAC sidecar is computed against the released binary and
distributed alongside it.
- Reproducible build instructions are published and tested before each
release.
The following risks remain after the documented mitigations. Deployments
that cannot accept them should choose a hardware HSM.
- A compromised kernel defeats every software mitigation.
- The entropy source (the OS CSPRNG) is assumed to be healthy; failure
modes of the OS RNG are detected only by the continuous health test,
which catches stuck outputs but not biased outputs.
- The side-channel posture of the default RustCrypto backend is limited
to the countermeasures those crates implement; the enterprise AWS-LC
backend is preferred for workloads with a side-channel threat model.
- model — security model
- policy — formal security policy
- hardening — deployment hardening
- ../fips/overview — FIPS 140-3 posture