libsofthsm2.so) that any PKCS#11-aware application can load. There is no daemon process — the library runs entirely in the calling application’s address space.
Component overview
SoftHSM does not expose a network socket or run a background process. It is loaded directly by the calling application via
dlopen (or the platform equivalent), just like any other shared library.Core components
SoftHSM
The central singleton class (
src/lib/SoftHSM.h). It owns all subsystem pointers and implements every PKCS#11 function as a method. Accessed through SoftHSM::i().SlotManager
Manages the set of slots exposed to the application (
src/lib/slot_mgr/SlotManager.h). Each slot holds a Token. SoftHSM always keeps one extra slot with an uninitialized token so new tokens can be created.SessionManager
Tracks all open sessions (
src/lib/session_mgr/SessionManager.h). Each Session object records its state, the active cryptographic operation, and a reference to the slot it was opened against.ObjectStore
Manages persistent token storage (
src/lib/object_store/ObjectStore.h). It is rooted at a configurable directory and enumerates tokens from that path. Supports two storage backends.SessionObjectStore
Holds session objects — objects that exist only for the lifetime of the session that created them. Backed entirely in memory.
HandleManager
Translates opaque
CK_OBJECT_HANDLE values returned to callers into internal OSObject pointers. Isolates callers from internal memory addresses.CryptoFactory
Abstract singleton (
src/lib/crypto/CryptoFactory.h) that vends SymmetricAlgorithm, AsymmetricAlgorithm, HashAlgorithm, MacAlgorithm, and RNG instances. Concrete subclasses implement these against OpenSSL or Botan.MutexFactory
Provides portable mutex primitives. When a caller passes
CKF_OS_LOCKING_OK to C_Initialize, the library uses OS-level locking; otherwise it uses the locking callbacks supplied by the caller.How a PKCS#11 call flows through the library
main.cpp is the sole entry point file. It defines a static CK_FUNCTION_LIST structure that maps every standard PKCS#11 function name to a thin wrapper function. Each wrapper catches unhandled C++ exceptions at the library boundary, then calls through to the SoftHSM singleton.
C_GetFunctionList returns a pointer to this static functionList structure directly, without routing through SoftHSM, since no library state is required.
Application calls C_GetFunctionList
The application resolves
C_GetFunctionList from the shared library and calls it. main.cpp returns a pointer to the static CK_FUNCTION_LIST (functionList), which contains pointers to every exported wrapper function.Application calls C_Initialize
main.cpp calls SoftHSM::i()->C_Initialize(pInitArgs). The singleton is created on first access. C_Initialize sets up the ObjectStore, SlotManager, SessionManager, HandleManager, and SessionObjectStore, and calls into CryptoFactory to initialize the crypto backend.Application opens a session
C_OpenSession is routed to SoftHSM::C_OpenSession, which asks SlotManager for the requested slot, then instructs SessionManager to create a new Session object. The new CK_SESSION_HANDLE is registered in HandleManager.Application performs a cryptographic operation
Two-phase operations (e.g.
C_SignInit / C_Sign) store operation context on the Session object. The SoftHSM method resolves the key handle via HandleManager, loads key material from ObjectStore or SessionObjectStore, requests an algorithm instance from CryptoFactory, and drives the operation to completion.The SoftHSM singleton
SoftHSM follows the classic singleton pattern. The private constructor and a static std::unique_ptr<SoftHSM> instance prevent external instantiation.
forkID member and detectFork() method handle the case where an application forks after calling C_Initialize. PKCS#11 requires that the child re-initialize the library.
Slot and token model
SlotManager holds a SlotMap (std::map<CK_SLOT_ID, Slot*>). Each Slot wraps an ObjectStoreToken that represents one persistent token directory on disk.
C_InitToken is called against that slot, the new token is assigned a serial-number-based slot ID and another empty slot is appended. This means slot IDs are not stable across re-initialization — applications should locate tokens by label or serial number, not by slot ID.
Object store backends
TheObjectStore class supports two storage backends selected at compile time.
File-based backend (default)
Token objects are stored as individual files inside a per-token subdirectory. The root directory is configured via
softhsm2.conf. Backup is a plain file-system copy. Implemented by OSToken and ObjectFile in src/lib/object_store/.SQLite3 backend
Enabled with
--with-objectstore-backend-db at configure time. Each token is a SQLite3 database file. Implemented by DBToken and DBObject in src/lib/object_store/. Also required for the SoftHSM v1 migration tool (--with-migrate).SessionObjectStore is a separate, always-in-memory store for session objects. The SoftHSM class holds both an ObjectStore (persistent) and a SessionObjectStore (ephemeral) simultaneously.
The token directory is set by the
directories.tokendir key in softhsm2.conf. The default path is /var/lib/softhsm/tokens/. Override the config file path with the SOFTHSM2_CONF environment variable.Crypto backend abstraction
CryptoFactory is an abstract singleton. At build time exactly one concrete subclass is compiled in:
| Configure flag | Concrete class | Source |
|---|---|---|
--with-crypto-backend=openssl | OSSLCryptoFactory | src/lib/crypto/OSSLCryptoFactory.cpp |
--with-crypto-backend=botan | BotanCryptoFactory | src/lib/crypto/BotanCryptoFactory.cpp |
SoftHSM.cpp selects the concrete header at the preprocessor level:
recycle* methods when the operation completes. This allows backend implementations to pool or cache algorithm objects if needed.
Algorithm dispatch inside SoftHSM
For operations that can apply to either symmetric or asymmetric keys,SoftHSM uses internal helper methods to select the right code path before delegating to CryptoFactory:
C_GenerateKeyPair dispatches to typed helpers (generateRSA, generateEC, generateED, generateDH, generateDSA, generateGOST, generateMLDSA) based on the mechanism type.
Optional algorithm support
Several algorithms are conditionally compiled:--enable-ecc, --enable-eddsa, --enable-mldsa, and --enable-gost.
Shared library deployment
Aftermake install, the library is placed where p11-kit or the calling application can find it. The install path for the p11-kit module can be overridden with --with-p11-kit=PATH.
Log output goes to syslog (or the Windows Event Log). Each message is prefixed with the source file name and line number. The log level is controlled by the
log.level key in softhsm2.conf.