Craton HSM

Craton HSM Security Policy

DISCLAIMER: Craton HSM is NOT FIPS 140-3 certified. This document describes the security design targeting FIPS 140-3 Level 1 requirements. The module has not been validated by a CMVP-accredited laboratory.

Document Information

PropertyValue
Module NameCraton HSM
Module Version0.9.1
Module TypeSoftware
FIPS 140-3 Target Level1 (not certified)
Document Version4.0
Date2026-03-17

1. Module Description

Craton HSM is a PKCS#11 v3.0-compliant software Hardware Security Module (HSM) implemented in Rust. It provides cryptographic key management, generation, storage, and operations through the standard PKCS#11 C API interface.

The module runs as a shared library (libcraton_hsm.so / craton_hsm.dll) loaded into an application's address space, or as a standalone gRPC daemon for remote access.

1.1 Module Architecture

+---------------------------------------------------------------+
|                    Cryptographic Module Boundary                |
|                                                                 |
|  +-------------------+  +------------------+  +--------------+ |
|  | PKCS#11 C ABI     |  | gRPC Interface   |  | Admin CLI    | |
|  | (libcraton_hsm.so)   |  | (craton-hsm-daemon) |  | (craton_hsm-   | |
|  |                    |  |                  |  |  admin)      | |
|  +--------+-----------+  +--------+---------+  +------+-------+ |
|           |                       |                    |         |
|  +--------v-----------------------v--------------------v-------+ |
|  |                      HsmCore                                | |
|  |  +------------------+  +------------------+                 | |
|  |  | SessionManager   |  | SlotManager      |                 | |
|  |  | (DashMap)        |  | (Token, PIN)     |                 | |
|  |  +------------------+  +------------------+                 | |
|  |  +------------------+  +------------------+                 | |
|  |  | ObjectStore      |  | CryptoBackend    |                 | |
|  |  | (in-memory +     |  | (RustCrypto or   |                 | |
|  |  |  EncryptedStore) |  |  aws-lc-rs)      |                 | |
|  |  +------------------+  +------------------+                 | |
|  |  +------------------+  +------------------+                 | |
|  |  | AuditLog         |  | Self-Test (POST) |                 | |
|  |  +------------------+  +------------------+                 | |
|  +-------------------------------------------------------------+ |
+---------------------------------------------------------------+

1.2 Physical Boundary

As a software-only module (FIPS 140-3 Level 1), the physical boundary is defined by the process address space of the host application loading the module. There are no physical security mechanisms.


2. Ports and Interfaces

2.1 Logical Interfaces

InterfaceTypeDescription
Data InputPKCS#11 API parametersPlaintext data, mechanism parameters, templates
Data OutputPKCS#11 API return valuesCiphertext, signatures, digests, object handles
Control InputPKCS#11 management functionsC_Initialize, C_Login, C_InitToken, C_InitPIN
Control OutputCK_RV return codesStatus/error codes per PKCS#11 specification
Status OutputC_GetInfo, C_GetSlotInfo, C_GetTokenInfoModule status, slot configuration

2.2 API Entry Points

The module exports 70+ PKCS#11 v3.0 C functions via #[no_mangle] pub extern "C" declarations. All entry points use catch_unwind at the FFI boundary to prevent Rust panics from unwinding through C callers.


3. Roles, Services, and Authentication

3.1 Roles

RolePKCS#11 IdentityAuthentication
Security Officer (SO)CKU_SOPIN (PBKDF2-HMAC-SHA256, 600K iterations)
Crypto UserCKU_USERPIN (PBKDF2-HMAC-SHA256, 600K iterations)
Unauthenticated(no login)None — limited to read-only public objects

3.2 Services

ServiceSO AccessUser AccessUnauthenticated
Key generationNoYesNo
Signing/VerificationNoYesNo
Encryption/DecryptionNoYesNo
Digest computationNoYesYes (no key needed)
Object creation (private)NoYesNo
Object creation (public)NoYesYes
Token initializationYesNoNo
PIN managementYes (set User PIN)Yes (change own PIN)No
Object destructionYes (any)Yes (own objects)No
Random number generationNoYesYes

3.3 Authentication Mechanism

PINs are verified using PBKDF2-HMAC-SHA256 with 600,000 iterations and a random 32-byte salt. The PIN hash is stored; the plaintext PIN is never persisted. PIN comparison uses constant-time comparison (subtle::ConstantTimeEq) to prevent timing attacks.

Default PINs:

  • SO PIN: "12345678" (must be changed on first use via C_InitToken)
  • User PIN: Set by SO via C_InitPIN

4. Finite State Model

4.1 Module States

                    +---------------+
                    |   Power Off   |
                    +-------+-------+
                            |
                            v
                    +-------+-------+
             +----->|  POST Running |
             |      +-------+-------+
             |              |
             |        Pass  |  Fail
             |     +--------+--------+
             |     v                 v
      +------+-----+        +-------+-------+
      | Initialized |        |  POST Failed  |
      | (Ready)     |        | (Error State)  |
      +------+------+        +---------------+
             |                  All operations
             |                  return CKR_
             |                  GENERAL_ERROR
     C_Login |
             v
      +------+------+
      | Authenticated|
      | (Operational)|
      +------+------+
             |
     C_Logout|
             v
      (back to Initialized)

4.2 Session States

Per PKCS#11 specification, each session has an independent state:

StateDescription
R/O PublicRead-only, no authentication
R/W PublicRead-write, no authentication
R/O UserRead-only, user authenticated
R/W UserRead-write, user authenticated
R/W SORead-write, SO authenticated

4.3 Error States

  • POST_FAILED: If any Power-On Self-Test fails, POST_FAILED AtomicBool is set. All subsequent cryptographic operations return CKR_GENERAL_ERROR.
  • Fork Detected (Unix): If a child process calls any PKCS#11 function after fork(), it receives CKR_CRYPTOKI_NOT_INITIALIZED and must re-initialize.

5. Cryptographic Algorithms

5.1 Approved Algorithms

AlgorithmStandardKey SizesUse
AES-GCMSP 800-38D256-bitAuthenticated encryption
AES-CBCSP 800-38A128/192/256-bitBlock encryption
AES-CTRSP 800-38A128/256-bitStream encryption
AES-KWSP 800-38F128/256-bitKey wrapping
RSA PKCS#1 v1.5FIPS 186-52048/3072/4096Signing, verification
RSA-PSSFIPS 186-52048/3072/4096Signing, verification
RSA-OAEPPKCS#1 v2.22048/3072/4096Key transport
ECDSA P-256FIPS 186-5256-bitSigning, verification
ECDSA P-384FIPS 186-5384-bitSigning, verification
ECDH P-256SP 800-56A256-bitKey agreement
ECDH P-384SP 800-56A384-bitKey agreement
SHA-256/384/512FIPS 180-4-Message digest
SHA3-256/384/512FIPS 202-Message digest
HMAC-SHA256/384/512FIPS 198-1-Message authentication
PBKDF2-HMAC-SHA256SP 800-132-PIN hashing
ML-DSA-44/65/87FIPS 204-Post-quantum signing
ML-KEM-512/768/1024FIPS 203-Post-quantum key encapsulation
SLH-DSAFIPS 205MultiplePost-quantum signing (stateless hash-based)

5.2 Non-Approved Algorithms

AlgorithmStatusControl
Ed25519Available (not yet FIPS-approved)Allowed by default
SHA-1Digest only — blocked for signingallow_sha1_signing = false
RSA < 2048Blockedallow_weak_rsa = false

5.3 Crypto Backend Selection

Two backends are available at compile time:

BackendFeature FlagFIPS Status
RustCrypto (default)rustcrypto-backendNot FIPS-certified
aws-lc-rsawslc-backendBacked by AWS-LC (FIPS 140-3 certified)

For FIPS deployments, build with --features awslc-backend. The backend is selected by the crypto_backend configuration parameter. Both backends implement the identical CryptoBackend trait (26 methods).

5.4 Random Number Generation

The module uses an SP 800-90A-compliant HMAC_DRBG (HMAC-SHA256) for all cryptographic random number generation. The DRBG is seeded from the operating system's CSPRNG (OsRng):

  • Linux: getrandom(2) system call
  • Windows: BCryptGenRandom
  • macOS: SecRandomCopyBytes

The DRBG provides:

  • Prediction resistance: fresh entropy from OsRng on every generate call
  • Continuous health test: compares consecutive DRBG outputs per SP 800-90B
  • Reseed interval: 2^48 requests before mandatory reseed
  • POST KAT: NIST CAVP known-answer test validates DRBG correctness at initialization

A continuous RNG health test on the entropy source (per SP 800-90B) compares each 32-byte output block against the previous output. Identical consecutive outputs cause the operation to fail.


6. Key Management

6.1 Key Generation

Keys are generated using approved algorithms and the SP 800-90A HMAC_DRBG (seeded from OS CSPRNG). Key material is allocated in process memory and immediately locked via mlock() (Unix) or VirtualLock() (Windows) to prevent paging to disk.

6.1.1 Key Lifecycle States (SP 800-57)

Keys support lifecycle state tracking per SP 800-57 Part 1:

StateTriggerPermitted Operations
Pre-activationBefore CKA_START_DATENone
ActiveBetween start and end datesAll permitted operations
DeactivatedAfter CKA_END_DATEVerify, decrypt, unwrap only
CompromisedManual markingNone
DestroyedC_DestroyObjectHandle invalid

State transitions based on CKA_START_DATE and CKA_END_DATE are evaluated automatically at each cryptographic operation.

6.2 Key Storage

Storage ModeDescription
In-memory (default)Keys exist only in process memory; lost on process exit
PersistentKeys stored in redb database, encrypted per-object with AES-256-GCM

Persistent storage uses a master encryption key derived from the SO PIN via PBKDF2 (600K iterations). Each object is serialized, encrypted with a unique random nonce, and stored as an opaque blob.

6.3 Key Protection

ProtectionMechanism
Memory lockingmlock() / VirtualLock() prevents swap
ZeroizationZeroizeOnDrop trait + manual Drop impl
Access controlCKA_EXTRACTABLE, CKA_SENSITIVE, session authentication
Constant-time comparisonsubtle::ConstantTimeEq for PIN verification
Debug redactionCustom Debug impls show [REDACTED] for key bytes

6.4 Key Destruction

When a key object is destroyed (via C_DestroyObject or session close for session objects):

  1. RawKeyMaterial::drop() is called
  2. Memory is overwritten with zeros via zeroize()
  3. munlock_buffer() / VirtualUnlock() releases the memory lock
  4. If persistent, the encrypted blob is deleted from the database

6.5 Key Import/Export

  • Import: Via C_CreateObject with CKA_VALUE. Subject to CKA_TOKEN and CKA_PRIVATE attribute enforcement.
  • Export: Only if CKA_EXTRACTABLE = true (defaults to false). Exported via C_GetAttributeValue for CKA_VALUE.
  • Wrapping: AES Key Wrap (SP 800-38F) via C_WrapKey / C_UnwrapKey.

7. Self-Tests

7.1 Power-On Self-Tests (POST)

17 self-tests run at module initialization (C_Initialize):

#TestType
0Software integrityHMAC-SHA256 of module binary (§9.4)
1SHA-256Known Answer (NIST "abc")
2SHA-384Known Answer (NIST "abc")
3SHA-512Known Answer (NIST "abc")
4SHA3-256Known Answer (NIST "abc")
5HMAC-SHA256Known Answer (RFC 4231 TC2)
6HMAC-SHA384Known Answer (RFC 4231 TC2)
7HMAC-SHA512Known Answer (RFC 4231 TC2)
8AES-256-GCMEncrypt/Decrypt roundtrip + known-answer decrypt
9AES-256-CBCKnown Answer (hardcoded expected ciphertext)
10AES-256-CTRKnown Answer (hardcoded expected ciphertext)
11RSA 2048 PKCS#1 v1.5Sign/Verify roundtrip
12ECDSA P-256Sign/Verify roundtrip
13ML-DSA-44Sign/Verify roundtrip
14ML-KEM-768Encap/Decap roundtrip
15RNG healthEntropy + continuous test (SP 800-90B)
16HMAC_DRBGKnown Answer (NIST CAVP)

The RNG health test verifies the OS random number generator produces non-zero, non-repeating output, and the DRBG continuous health test validates non-repeating DRBG output.

Note on KAT design (v0.9.1): AES-CBC and AES-CTR KATs use genuine known-answer tests with hardcoded expected ciphertexts (not circular encrypt/decrypt roundtrips). This catches symmetric implementation bugs that a roundtrip-only test would miss.

7.2 POST Failure Behavior

If any POST fails:

  • POST_FAILED atomic flag is set to true
  • All subsequent cryptographic operations return CKR_GENERAL_ERROR
  • On re-initialization (after C_Finalize), POST_FAILED is reset and POST re-runs
  • If POST fails again, the module remains in error state

7.3 Conditional Self-Tests (§9.6)

TestTriggerBehavior
Continuous RNGEvery C_GenerateRandom callCompare 32-byte output against previous; fail if identical
DRBG continuousEvery DRBG generate() callCompare consecutive outputs; fail if identical
RSA pairwiseC_GenerateKeyPair(CKM_RSA_PKCS_KEY_PAIR_GEN)Sign/verify roundtrip with SHA-256 RSA PKCS#1v15
ECDSA P-256 pairwiseC_GenerateKeyPair(CKM_EC_KEY_PAIR_GEN) with P-256Sign/verify roundtrip
ECDSA P-384 pairwiseC_GenerateKeyPair(CKM_EC_KEY_PAIR_GEN) with P-384Sign/verify roundtrip
Ed25519 pairwiseC_GenerateKeyPair(CKM_EDDSA)Sign/verify roundtrip
ML-DSA pairwiseC_GenerateKeyPair(CKM_ML_DSA_*)Sign/verify roundtrip
ML-KEM pairwiseC_GenerateKeyPair(CKM_ML_KEM_*)Encap/decap roundtrip
SLH-DSA pairwiseC_GenerateKeyPair(CKM_SLH_DSA_*)Sign/verify roundtrip

Pairwise test failure sets POST_FAILED and the module enters error state.


8. Operational Environment

8.1 Requirements

  • Operating System: Any OS supporting Rust compilation (Linux, Windows, macOS)
  • Rust Compiler: Edition 2021 or later
  • Memory: Process must have sufficient mlock quota for key material

8.2 Multi-Process Considerations

  • The module is NOT fork-safe on Unix. Child processes must call C_Initialize after fork.
  • If persistent storage is enabled, only one process may access a given database path (enforced by exclusive file lock via fs2).
  • Multi-process access is supported via the gRPC daemon (craton-hsm-daemon).

9. Design Assurance

9.1 Source Code Management

  • All source code managed in Git
  • Rust's ownership model provides compile-time memory safety guarantees
  • No unsafe code outside the PKCS#11 C ABI boundary (where catch_unwind protects callers)

9.2 Testing

CategoryCountDescription
Unit + integration tests617+Covers all algorithms, error paths, state machine, multi-part ops, FIPS mode
PKCS#11 conformance tests46ABI-level tests: zero IV rejection, session mgmt, PIN security, crypto roundtrips, config validation
Pairwise consistency tests6RSA, ECDSA P-256/P-384, Ed25519, ML-DSA, ML-KEM sign/verify roundtrips
FIPS approved mode tests11Mechanism blocking, policy enforcement, approved classification
Zeroization tests7Verify key material cleared after drop
Persistence tests9Verify storage integrity across restarts
Fuzz targets5C ABI, crypto ops, attributes, session lifecycle, buffer overflow
POST verification1Validates all 17 self-tests pass (integrity + 16 KATs)

9.3 Build Configuration

For FIPS deployments:

# Build with FIPS-certified crypto backend
cargo build --release --features awslc-backend

# Verify all tests pass
cargo test --features awslc-backend -- --test-threads=1

10. Mitigation of Other Attacks

FIPS 140-3 Level 1 does not require mitigation of attacks beyond the module boundary. However, the module implements:

MitigationAttackMechanism
Constant-time PIN comparisonTiming attackssubtle::ConstantTimeEq
Memory lockingCold boot / swap recoverymlock() / VirtualLock()
ZeroizationMemory remanenceZeroizeOnDrop on all key material
Audit loggingUnauthorized use detectionTamper-evident append-only log with chained SHA-256
Fork detectionState corruption after forkPID comparison on every API call (Unix)
File lockingDatabase corruptionExclusive advisory lock on database file

11. Critical Security Parameters (CSPs)

The following table documents all Critical Security Parameters managed by the module, their storage location, protection mechanism, and zeroization method.

CSPTypeStorageProtectionZeroization
AES-256 keysSymmetric key (32 bytes)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
AES-128 keysSymmetric key (16 bytes)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
RSA private keysAsymmetric key (PKCS#8 DER)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
ECDSA P-256 private keysAsymmetric key (32 bytes scalar)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
ECDSA P-384 private keysAsymmetric key (48 bytes scalar)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
Ed25519 private keysAsymmetric key (32 bytes)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
ML-DSA signing keysPQC key (variable size)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
ML-KEM decapsulation keysPQC key (variable size)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
SLH-DSA signing keysPQC key (variable size)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
HMAC keysSymmetric key (variable)RawKeyMaterial (process memory)mlock, ZeroizeOnDropOverwrite with zeros on drop, then munlock
SO PIN hashPBKDF2 output (32 bytes + 32 bytes salt)Token struct (process memory)Not extractable via APIZeroized on process exit
User PIN hashPBKDF2 output (32 bytes + 32 bytes salt)Token struct (process memory)Not extractable via APIZeroized on process exit
Storage encryption keyAES-256 key (32 bytes)ObjectStore::persist_key (Mutex)mlock, in-memory onlyCleared via clear_persist_key() on C_Logout/C_InitToken
HMAC_DRBG state (K, V)DRBG internal state (64 bytes)HmacDrbg struct (Mutex)Process memory, Mutex-protectedZeroizeOnDrop on K and V
AES-GCM nonces12-byte random valuesEphemeral (stack)Generated fresh per DRBG callDropped from stack
PBKDF2 salt32 random bytesStored alongside PIN hashNot sensitive (public parameter)N/A
Integrity HMAC key32-byte constantEmbedded in binary (compile-time)Per FIPS IG 9.7 (software module)N/A (constant)
Intermediate plaintextVariable-length buffersActiveOperation fields (session memory)Zeroizing<Vec<u8>> — zeroized on dropAutomatic via ZeroizeOnDrop

11.1 CSP Lifecycle

Generation/Import --> mlock() --> Active Use --> zeroize() --> munlock() --> Destroyed
                      |                           |
                      |  (if persistent)           |
                      +-> AES-256-GCM encrypt ->   |
                          store in redb             |
                                                   |
                      (if persistent)              |
                      delete from redb <-----------+

11.2 CSP Access Control

CSP CategoryWho Can AccessAPI Function
Private keysAuthenticated UserC_Sign, C_Decrypt, C_UnwrapKey
Secret keysAuthenticated UserC_Encrypt, C_Decrypt, C_WrapKey
Key material (raw)Authenticated User + CKA_EXTRACTABLE=trueC_GetAttributeValue(CKA_VALUE)
PIN hashesModule internals onlyNot exposed via any API
Storage encryption keyModule internals onlyDerived from SO PIN during C_Login(CKU_SO)