Craton HSM

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