Feature Architecture#

Crypto Architecture
status: draft
security: YES
safety: QM
version: 1
Security & Crypto
status: valid
security: YES
safety: QM
version: 1

Overview#

The Security & Crypto feature provides applications with a provider-independent way to execute cryptographic operations without coupling application code to a specific software library, PKCS#11 token, HSM, or TEE. The current implementation uses a client-daemon split: applications use the C++ API, while a dedicated daemon selects providers, owns operation contexts, and executes cryptographic jobs.

The feature is security-relevant but currently classified as QM. In particular, the complete client, IPC/shared-memory, daemon, and provider path is not presented as an ISO 26262-qualified replacement for safety-certified Baselibs hashing.

Description#

The feature is decomposed into the following responsibilities:

  • The public API creates a crypto stack, logical crypto contexts, and typed operation contexts such as hash and MAC contexts.

  • The control plane serializes lifecycle and operation requests and transports them to the daemon.

  • The data plane selects in-band, pooled shared-memory, or registered bulk shared-memory transport based on the supplied buffers.

  • The daemon validates requests, maintains context state, selects a provider, and dispatches the requested job.

  • Provider adapters translate the common operation contract to a concrete backend. The implemented provider families include OpenSSL and PKCS#11.

  • Key-management services resolve key slots and provider-owned key objects without exposing provider-specific handles through the application API.

Important design decisions are:

  • Provider-independent algorithm identifiers are part of the API and wire contract. Provider-native identifiers are resolved only inside the daemon.

  • Operation contexts are explicit resources with a daemon-managed lifecycle.

  • Large buffers use validated shared-memory references to avoid unnecessary copies while keeping ownership with the caller.

  • Provider selection is performed during context creation; an operation does not silently change providers after the context has been created.

  • Streaming jobs use an explicit state machine so invalid ordering is rejected before a provider call is made.

The design is constrained by provider capability differences, PKCS#11 token and session limits, process-boundary failure modes, and the lifetime of caller-owned buffers. Applications must handle unavailable providers and unsupported algorithms explicitly. Algorithms with variable output or provider-specific parameters require an API-level contract before they can be exposed portably.

Requirements#

Component requirements and assumptions of use are maintained with the Crypto component documentation. Feature-level ownership and cross-repository consumer migration for the Baselibs hash transition remain tracked by inc_security_crypto issue #125. The consumer migration and removal of Baselibs algorithms are deliberately not claimed by this repository’s component requirements.

Rationale Behind Architecture Decomposition#

The process boundary isolates applications from provider initialization, credentials, sessions, and provider-specific failure handling. Separating the control and data planes permits small requests to remain simple while large data can use shared memory. A common handler contract lets OpenSSL serve development and software deployments while PKCS#11 connects the same API to hardware-backed implementations. Keeping key and operation resources in the daemon also reduces the amount of provider-specific state exposed to clients.

Static Architecture#

The principal static dependencies are:

Application
    |
    v
Crypto C++ API -- Control plane client -- IPC -- Crypto daemon
    |                                      |
    +-- Buffer/SHM data plane -------------+
                                           |
                                           v
                                  Provider manager
                                    /          \
                                   v            v
                            OpenSSL provider  PKCS#11 provider
                                                 |
                                                 v
                                          Token / HSM / TEE

Detailed component, interface, data-plane, provider, and key-management views are available in the score/crypto/docs/architecture documentation.

Dynamic Architecture#

A typical operation follows this sequence:

  1. The application creates a stack and connects to the configured daemon endpoint.

  2. It creates a crypto context and requests a typed operation context with an algorithm and optional provider selection.

  3. The daemon resolves and validates the provider, creates a handler, and returns an opaque context identifier.

  4. Each operation request carries control metadata and either in-band data or validated shared-memory references.

  5. The handler validates the operation state and dispatches to the selected provider.

  6. The daemon returns a status and output length; output bytes are written to the caller-owned buffer.

  7. Reset returns a reusable operation context to its idle state, while context destruction releases daemon and provider resources.

For hashing, valid flows are SingleShot or Init followed by zero or more Update calls and Finalize. A retryable validation error such as an undersized final output buffer does not consume the active stream.

Logical Interfaces#

The public logical interface is the provider-independent Crypto C++ API. The client-daemon protocol and provider handler interfaces are internal logical interfaces and are versioned with the component implementation. Provider-native APIs, including OpenSSL EVP and PKCS#11 Cryptoki, terminate at their respective daemon adapters and are not exposed to applications.

Used Components#

The feature is currently realized by the Crypto component (comp__crypto). External consumers and the eventual Baselibs cleanup are separate repository changes and are outside this component’s implementation boundary.