Provider Architecture#
The daemon hosts two parallel provider families — Score (software-oriented,
currently backed by OpenSSL) and PKCS#11 (hardware token / SoftHSM). Both
families implement the same IProvider / IProviderFactory interfaces and
are registered with ProviderManager through an identical visitor-pattern
bootstrapping sequence.
Fig. 8 Daemon Provider Architecture — Score and PKCS#11 families, handler hierarchy, and config visitor pattern.#
Provider Families#
Score Provider Family#
The score family (provider/score_provider/) provides typed abstract handler
bases that sit between the generic IHandler interface and concrete
implementations:
ScoreHashHandlerowns aHashExecutorthat drives the stream state machine (HASH_INIT→HASH_UPDATE→HASH_FINALIZE).ScoreMacHandlerowns aMacExecutorwith the equivalent MAC state machine.ScoreKeyManagementHandlerdelegates to a sharedKeyManagementExecutor(fromprovider/executors/).
Concrete providers (e.g. openssl/) inherit from these bases and override
only the typed crypto primitive methods (InitHash, UpdateHash,
FinalizeHash). They do not re-implement the state machine logic.
PKCS#11 Provider Family#
The PKCS#11 family (provider/pkcs11/) implements IHandler directly.
Each handler translates generic operation requests into PKCS#11 C API calls
against a token. Shared key management logic is provided via the same
KeyManagementExecutor used by the score family.
Provider Configuration#
Provider configuration is split into three layers. Each layer is owned by a separate config type and resolved at a different point during daemon startup.
Provider-family topology — build time The set of provider families that can exist in a given daemon binary is decided by compile-time flags (for example
SCORE_BACKEND_ENABLEDandSCORE_CRYPTO_PKCS11_ENABLED).ProviderManagerFactoryregisters a factory for every family that is compiled in.Provider-specific parameters — config file / defaults Each family parses its own parameters from the daemon configuration:
ScoreProviderConfig(score_provider/score_provider_config.hpp) holds oneScoreProviderEntryper score backend. An entry contains the provider name, the backend implementation tag (for example"openssl"), and the provider type (SOFTWARE,HARDWARE,SPECIALIZED).ScoreProviderConfig::ParseConfig()populates entries from the config file; when no config is present it falls back to the active backends discovered at compile time.Pkcs11Config(pkcs11/pkcs11_token_config.hpp) holds onePkcs11TokenEntryper token. An entry contains the token label, model, user PIN, provider name, provider type, and session cleanup strategy.Pkcs11Config::ParseConfig()reads these values from the daemon config.
Both config classes use only standard-library types in their public headers so that the top-level
Configclass can own them without pulling in backend-specific headers.Runtime enablement and type mapping —
ProviderInitConfigAfter all factories have created and registered their providers, and after every provider has been initialized,ProviderManager::Initialize()loadsProviderInitConfigto decide:Which registered providers are enabled. Disabled providers are shut down and removed from lookup tables.
Which provider is the default for each
CryptoProviderType(DEFAULT,SOFTWARE,HARDWARE,SPECIALIZED).
ProviderInitConfigidentifies providers by their stableProviderName(for example"OPENSSL"or"hsm_slot_1"), not by the runtimeProviderIdassigned during registration. This keeps the configuration stable across restarts and independent of registration order.If the daemon config does not supply a
ProviderInitConfig,ProviderManagercreates a default one that enables every successfully initialized provider and selects defaults using the preference orderHARDWARE→SOFTWARE.
Configuration flow#
Config::ParseConfig()
│
├── ScoreProviderConfig::ParseConfig() ──► ScoreProviderEntry list
│
└── Pkcs11Config::ParseConfig() ──► Pkcs11TokenEntry list
│
ProviderManagerFactory::Create(config)
│
├── CreateScoreProviderFactory(config)
│ ScoreProviderConfig::Configure(ScoreProviderFactory)
│
├── CreatePkcs11ProviderFactory(config)
│ Pkcs11Config::Configure(Pkcs11ProviderFactory)
│
└── provider_manager->Initialize()
│
├── CreateProviders() ← factories create & RegisterProvider()
├── InitializeAll() ← providers initialize
│
├── ApplyEnablement(ProviderInitConfig.providers)
│ shut down / hide disabled providers
│
└── BuildTypeMappings(ProviderInitConfig.typeToProviderName)
resolve names → runtime ProviderId
Directory Layout#
provider/
├── i_provider.hpp ← IProvider interface
├── i_provider_factory.hpp ← IProviderFactory interface
├── provider_manager.hpp/.cpp ← Provider registry & lifecycle
├── provider_manager_factory.hpp/.cpp ← Build-time factory wiring
├── handler/
│ ├── i_handler.hpp ← Handler interface
│ ├── i_crypto_handler_factory.hpp ← Factory interface
│ ├── handler_init_params.hpp
│ ├── context_data_node.hpp
│ ├── operations/
│ │ ├── hash_handler_operations.hpp ← Shared hash OperationAction constants
│ │ └── mac_handler_operations.hpp ← Shared MAC OperationAction constants
│ └── src/
│ ├── handler_utils.hpp/.cpp
│ └── context_data_node.cpp
├── executors/
│ ├── key_mgmt_executor.hpp/.cpp ← Shared KM executor (both families)
│ ├── key_mgmt_context.hpp
│ └── key_mgmt_request_parser.hpp
├── score_provider/
│ ├── score_provider_config.hpp/.cpp ← Config / visitor
│ ├── score_provider_factory.hpp/.cpp
│ ├── score_provider.hpp ← Abstract base provider
│ ├── score_backend_adapter.hpp ← Backend adapter interface
│ ├── operations/ ← Score*Handler + *Executor bases
│ │ ├── hash/
│ │ ├── mac/
│ │ ├── key_management/
│ │ └── factory/
│ └── openssl/ ← OpenSSL concrete provider
│ ├── provider_openssl.hpp/.cpp
│ ├── operations/ ← OpenSsl*Handler implementations
│ ├── key_management/ ← OpenSslKeyHandler, OpenSslKeyFactory
│ └── detail/
└── pkcs11/ ← PKCS#11 provider family
├── pkcs11_token_config.hpp/.cpp ← Token config / visitor
├── pkcs11_provider_factory.hpp/.cpp
├── pkcs11_provider.hpp/.cpp
├── pkcs11_module.hpp/.cpp
├── pkcs11_session_guard.hpp
├── operations/
├── key_management/
└── detail/