Craton HSM

Threat Model

Threat Model

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.

Adversary Classes

ClassCapabilitiesExample
Local unprivilegedRuns 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 privilegedRoot 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 chainCan influence a dependency, a build artefact, or an upstream toolchain.Compromised crate on crates.io; malicious CI runner.
PhysicalHands-on access to the host. Can dump RAM, replace storage media, boot into a recovery environment.Stolen laptop; disgruntled data-centre employee.

In-Scope Threats and Mitigations

Spoofing

ThreatMitigation
Caller claims to be the Security Officer or a User without authenticationSession 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 daemonMutual TLS; client certificate validated against a configured trust store with optional CRL
Replay a PIN captured over a passive observation channelPINs travel only inside the TLS channel; out-of-band capture is out of scope

Tampering

ThreatMitigation
Modify the module binary on disk before loadHMAC-SHA256 sidecar integrity check at POST; FIPS build requires the sidecar to be present
Modify the persistent object database while offlinePer-object AES-256-GCM authenticated encryption; tampering produces decryption failure on load
Inject malicious attributes via C_CreateObject or C_SetAttributeValueTemplate 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 entriesChained SHA-256 hashes; any insertion, deletion, or reordering breaks the chain

Repudiation

ThreatMitigation
Operator denies performing a privileged operationEvery 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 operationChained hashes detect deletion; a break in the chain points at the region that was modified

Information Disclosure

ThreatMitigation
Key bytes leak through debug outputCustom Debug impls print [REDACTED]; key types never derive Debug
Key bytes leak through error messagesErrors 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 exitmlock/VirtualLock on allocation; zeroize-then-munlock on drop
Timing side-channel on PIN verificationPBKDF2 dominates the runtime; subtle::ConstantTimeEq prevents byte-by-byte leakage
Timing side-channel on HMAC verificationsubtle::ConstantTimeEq on tag comparison
Key material leaks via CKA_VALUE readCKA_SENSITIVE=true, CKA_EXTRACTABLE=false returns CKR_ATTRIBUTE_SENSITIVE; default for generated keys is both true/false respectively
Core dumps after a crash expose memoryOperator responsibility — ulimit -c 0 and disabling systemd-coredump is part of the hardening guide

Denial of Service

ThreatMitigation
Panic inside the module crashes the host processcatch_unwind wraps every extern "C" export; panics are converted to CKR_GENERAL_ERROR
Malformed templates or mechanism parameters cause undefined behaviourInput validation at the ABI layer; all buffers bounds-checked by Rust ownership; panic-on-error paths return errors
Concurrent processes corrupt the persistent databaseExclusive flock at open time; second opener receives an error
Authentication brute forcePIN lockout after configurable N failures (default 10) per role
Oversized RSA keysMaximum 16384-bit modulus; keys above the limit are rejected
AES-GCM nonce exhaustionPer-key counter with 2^31 limit and graduated warnings at 50%/75%/90%/95%/99%

Elevation of Privilege

ThreatMitigation
Non-approved mechanism used in a FIPS deploymentfips_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 signingSP 800-57 lifecycle: deactivated keys are rejected for sign/encrypt/wrap/derive
Forked child inherits parent session state and corrupts RNG / audit chainPID 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 databaseflock prevents concurrent open; the daemon is the supported path for multi-process access

Out-of-Scope Threats

ThreatWhy out of scope
Cold-boot RAM extractionPhysical access required; mlock prevents swap only, not physical dumps
DMA or bus-snooping attacksRequire IOMMU and platform-level mitigation outside the module
OS kernel compromiseA hostile kernel can read all process memory; operator must harden the OS
Power analysis / EM emanationHardware-level side-channels; software HSMs cannot mitigate
Spectre / Meltdown-class speculative execution attacksDepend on CPU microcode and kernel patches
Cache-timing on systems without AES-NIModern x86/ARM ships with AES instructions; pre-Westmere hardware is not a supported platform
Social engineeringOutside any technical control
Vulnerabilities in upstream dependenciesReported to the upstream project; cargo audit and cargo deny run in CI to detect advisories early

Trust Boundary Summary

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.

Supply Chain Controls

  • 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.

Residual Risks

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.

Further Reading