Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
".venv_docs",
"_build",
"examples/README.md",
"score/crypto/backend/README.md", # developer-only README
]

templates_path = ["templates"]
Expand Down
2 changes: 1 addition & 1 deletion docs/crypto/architecture/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ through two complementary abstractions:
``OpenSSLProviderFactory``
Internal factory used by ``ScoreProviderFactory``. Constructs
``score::openssl::OpenSSL`` and registers it as ``CryptoProviderType::SOFTWARE``
under the ``common::kProviderNameOpenSSL`` name. No per-instance configuration required.
under the name read from config (e.g. ``"OPENSSL"``). No per-instance configuration required.

``Pkcs11ProviderFactory``
Accepts an injected ``std::vector<Pkcs11ProviderConfig>`` via
Expand Down
111 changes: 101 additions & 10 deletions docs/crypto/architecture/provider_architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,98 @@ integer constants (``HASH_INIT``, ``HASH_UPDATE``, ``HASH_FINALIZE``,
Both provider families include these headers directly — the constants are not
specific to any algorithm family or provider.

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.

1. 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_ENABLED`` and
``SCORE_CRYPTO_PKCS11_ENABLED``). ``ProviderManagerFactory`` registers a factory
for every family that is compiled in.

2. Provider-specific parameters — config file / defaults
Each family parses its own parameters from the daemon configuration:

- ``ScoreProviderConfig`` (``score_provider/score_provider_config.hpp``)
holds one ``ScoreProviderEntry`` per 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 one
``Pkcs11TokenEntry`` per 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 ``Config`` class can own them without pulling in
backend-specific headers.

3. Runtime enablement and type mapping — ``ProviderInitConfig``
After all factories have created and registered their providers, and after
every provider has been initialized, ``ProviderManager::Initialize()`` loads
``ProviderInitConfig`` to 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``).

``ProviderInitConfig`` identifies providers by their stable
``ProviderName`` (for example ``"OPENSSL"`` or ``"hsm_slot_1"``), not by the
runtime ``ProviderId`` assigned during registration. This keeps the
configuration stable across restarts and independent of registration order.

If the daemon config does not supply a ``ProviderInitConfig``,
``ProviderManager`` creates a default one that enables every successfully
initialized provider and selects defaults using the preference order
``HARDWARE`` → ``SOFTWARE``.

Configuration flow
^^^^^^^^^^^^^^^^^^

.. code-block:: text

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

.. code-block:: text

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
Expand All @@ -91,18 +176,24 @@ Directory Layout
├── score_provider/
│ ├── score_provider_config.hpp/.cpp ← Config / visitor
│ ├── score_provider_factory.hpp/.cpp
│ ├── score_provider.hpp/.cpp ← Abstract base provider
│ ├── operations/
│ │ ├── hash/ ← ScoreHashHandler + HashExecutor
│ │ ├── mac/ ← ScoreMacHandler + MacExecutor
│ │ ├── key_management/ ← ScoreKeyManagementHandler
│ │ └── factory/ ← ScoreHandlerFactory
│ ├── 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
│ ├── openssl_provider_factory.hpp/.cpp
│ ├── operations/ ← OpenSsl*Handler implementations
│ ├── key_management/ ← OpenSslKeyHandler, OpenSslKeyFactory
│ └── detail/
├── pkcs11/ ← PKCS#11 provider family
└── src/
└── provider_manager.cpp
└── 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/
92 changes: 92 additions & 0 deletions score/crypto/backend/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

load("@rules_cc//cc:defs.bzl", "cc_library")
load(
":backend_exports.bzl",
"BACKEND_DEFINES",
"ENABLE_PKCS11_BACKEND",
"PKCS11_BACKEND_DEFAULT_LABEL",
"PKCS11_BACKEND_DEPS",
"SCORE_BACKEND_DEPS",
)

# ============================================================================
# Backend Architecture:
# ============================================================================
#
# MASTER CONFIGURATION: All backend selection flags are in backend_exports.bzl
#
# PKCS#11 Backend:
# - Enable/disable: Set ENABLE_PKCS11_BACKEND in backend_exports.bzl
# - Implementation selection: Set PKCS11_BACKEND = "softhsm" | "vendor_hsm" | ...
#
# Score Provider Backends (multiple can be active simultaneously):
# - openssl/ : OpenSSL crypto backend
# - primula/ : Primula backend (future)
# Enable/disable by setting ENABLE_BACKEND_OPENSSL, etc. in backend_exports.bzl
#
# See backend_exports.bzl for the single source of truth for all backend flags.
# ============================================================================
#

# ============================================================================
# Score Provider Backends
# ============================================================================
#

# Heavy: actual adapter implementations.
# Only score_provider_factory should consume this (via implementation_deps).
cc_library(
name = "active_score_backends",
visibility = ["//visibility:public"],
deps = [
"//score/crypto/backend/score_provider:score_backend_defines",
] + SCORE_BACKEND_DEPS,
)

# ============================================================================
# PKCS#11 Backend
# ============================================================================
#

# Label flag allowing command-line override of the PKCS#11 backend.
# Default value is derived from PKCS11_BACKEND in backend_exports.bzl.
# Example override:
# bazel build //score/crypto/daemon:crypto_daemon \
# --//score/crypto/backend:pkcs11_backend=//external/vendor_hsm:backend
label_flag(
name = "pkcs11_backend",
build_setting_default = PKCS11_BACKEND_DEFAULT_LABEL,
)

# Lightweight: single define exposing whether PKCS#11 is compiled in.
# Replaces the __has_include anti-pattern in provider_manager_factory.
cc_library(
name = "pkcs11_backend_defines",
defines = (["SCORE_CRYPTO_PKCS11_ENABLED=1"] if ENABLE_PKCS11_BACKEND else []),
visibility = ["//visibility:public"],
)

# PKCS#11 backend: selected library + fixed config parser.
# Only provider_pkcs11_library/factory should consume this (via implementation_deps).
cc_library(
name = "active_pkcs11_backend",
visibility = ["//visibility:public"],
deps = [
":pkcs11_backend_defines",
] + ([
":pkcs11_backend",
"//score/crypto/backend/pkcs11:pkcs11_config_parser",
] if ENABLE_PKCS11_BACKEND else []),
)
137 changes: 137 additions & 0 deletions score/crypto/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Backend Configuration

This folder controls which cryptographic backends are compiled into the daemon.
It is the **single source of truth** for backend selection at build time.

## Files

| File | Purpose |
|------|---------|
| `backend_exports.bzl` | Master flags (`ENABLE_BACKEND_OPENSSL`, `PKCS11_BACKEND`, ...) |
| `backend_config.bzl` | Helper functions that map flags to Bazel labels/defines |
| `BUILD` | Bazel targets: `active_score_backends`, `active_pkcs11_backend`, `pkcs11_backend` label_flag |
| `score_provider/active_backends_list.hpp` | Compile-time discovery of enabled score backends |

## How It Works

### Score Provider Backends

A single `ScoreProviderFactory` handles multiple score backends (OpenSSL, Primula, etc.).
The factory discovers enabled backends at compile time via `score_provider/active_backends_list.hpp`.
Each backend adapter exposes:

- `backend_id` — implementation tag used for dispatch (e.g. `"openssl"`)
- `backend_name` — human-readable provider name (e.g. `"OPENSSL"`)
- `provider_type` — `"SOFTWARE"`, `"HARDWARE"` or `"SPECIALIZED"`
- `create_provider` — factory function for the concrete provider

### PKCS#11 Backends

A separate `Pkcs11ProviderFactory` handles the PKCS#11 family. Only one PKCS#11
backend can be active at a time. The active backend is selected through a Bazel
`label_flag`:

```starlark
# backend/BUILD
label_flag(
name = "pkcs11_backend",
build_setting_default = PKCS11_BACKEND_DEFAULT_LABEL,
)
```

The default value comes from `PKCS11_BACKEND` in `backend_exports.bzl`. It can be
overridden on the command line:

```bash
bazel build //score/crypto/daemon:crypto_daemon \
--//score/crypto/backend:pkcs11_backend=//external/vendor_hsm:backend
```

Each PKCS#11 backend target provides:

1. A `Pkcs11Config::ParseConfig()` implementation with backend-specific defaults
2. The PKCS#11 library and headers for linking

## Configuration (`backend_exports.bzl`)

```starlark
# Backend family flags
ENABLE_PKCS11_BACKEND = True # Enable/disable PKCS#11
ENABLE_SCORE_BACKEND = True # Enable/disable all score backends

# Individual score backends (only if ENABLE_SCORE_BACKEND = True)
ENABLE_BACKEND_OPENSSL = True
ENABLE_BACKEND_PRIMULA = False

# Active PKCS#11 backend (only if ENABLE_PKCS11_BACKEND = True)
PKCS11_BACKEND = "softhsm" # Options: "softhsm", "vendor_hsm", ...
```

## Adding a New Score Backend

1. Implement the provider in `score_provider/<backend>/`
2. Create an adapter in `backend/<backend>/`:
```cpp
ProviderCreator GetProviderCreator() const override {
return {
.backend_id = "<backend>",
.backend_name = "<BACKEND>",
.provider_type = "SOFTWARE", // or "HARDWARE", "SPECIALIZED"
.create_provider = []() { return std::make_unique<...>(); }
};
}
```
3. Add flags to `backend_exports.bzl` and update `backend_config.bzl`
4. Update `score_provider/active_backends_list.hpp` (include + instantiate)

## Adding a New PKCS#11 Backend

Config parsing (`Pkcs11Config::ParseConfig`) lives in `backend/pkcs11/` and is
independent of which backend library is selected. Backend targets provide only
the PKCS#11 library and headers.

1. Add the backend name → library label mapping in `backend_config.bzl`:
```starlark
def _pkcs11_backend_map():
return {
"softhsm": "//third_party/soft_hsm:softhsm",
"<name>": "//third_party/<name>:<name>", # NEW
}
```
2. Select it in `backend_exports.bzl`:
```starlark
PKCS11_BACKEND = "<name>"
```
Or override at build time:
```bash
bazel build //score/crypto/daemon:crypto_daemon \
--//score/crypto/backend:pkcs11_backend=//third_party/<name>:<name>
```

## Common Configurations

| Use Case | Config |
|----------|--------|
| **Software-only** | `ENABLE_PKCS11_BACKEND = False`<br/>`ENABLE_SCORE_BACKEND = True`<br/>`ENABLE_BACKEND_OPENSSL = True` |
| **HSM-only** | `ENABLE_PKCS11_BACKEND = True`<br/>`ENABLE_SCORE_BACKEND = False`<br/>`PKCS11_BACKEND = "vendor_hsm"` |
| **Hybrid** | Both families enabled |

## Command-Line Overrides

| What | Example |
|------|---------|
| PKCS#11 backend | `--//score/crypto/backend:pkcs11_backend=//external/vendor_hsm:backend` |

## Verification

Check which backends are compiled into the daemon:

```bash
bazel query 'deps(//score/crypto/daemon:crypto_daemon)' | grep -E "openssl|softhsm"
```

Check the effective PKCS#11 backend:

```bash
bazel cquery //score/crypto/daemon:crypto_daemon --output=build | grep pkcs11_backend
```
Loading
Loading