Open-Source Wikis

/

OpenSSL

/

Subsystems

/

Core and library contexts

openssl/openssl

Core and library contexts

Active contributors: Pauli, Tomas Mraz, Matt Caswell, slontis, Neil Horman

Purpose

The "core" of libcrypto is the small set of subsystems that knows how to find an algorithm implementation in a sea of providers and bind it to a usable handle. Everything in OpenSSL that operates on cryptographic data ultimately reaches into this code path.

There are five intertwined pieces:

  1. OSSL_LIB_CTX — a library context. The "world" that providers, properties, and per-context state live in.
  2. Namemap — a bidirectional table mapping algorithm names (and aliases, OIDs, …) to integer ids.
  3. Property store — a parsed/optimized representation of property strings like provider=fips,fips=yes.
  4. Fetch — the algorithm lookup machinery. EVP_*_fetch(libctx, "name", "props").
  5. Provider object — the runtime view of a loaded provider, including its dispatch table and teardown.

Directory layout

crypto/
├── context.c              -- OSSL_LIB_CTX_new/free, per-libctx data registry
├── init.c, initthread.c   -- one-time init, thread-stop callbacks
├── defaults.c             -- default property handling
├── core_namemap.c         -- the namemap
├── core_algorithm.c       -- algorithm cache helpers
├── core_fetch.c           -- the fetch implementation
├── property/              -- property string parser, query matcher, definition cache
│   ├── property.h, property_local.h
│   ├── property_parse.c, property_lookup.c
│   ├── property_string.c, property_query.c
│   └── defn_cache.c
├── provider.c             -- public OSSL_PROVIDER API
├── provider_core.c        -- 84 KB: the provider state machine, dispatch resolution
├── provider_conf.c        -- openssl.cnf [providers] section parser
├── provider_child.c       -- nested-libctx support (for FIPS internal libctx)
├── provider_predefined.c  -- the four built-in providers (default/base/legacy/null) registry
└── provider_local.h

Public headers: include/openssl/crypto.h.in (the OSSL_LIB_CTX API), include/openssl/core.h, core_dispatch.h, core_names.h.in, core_object.h, provider.h.

Key abstractions

Type What it is Where
OSSL_LIB_CTX The container for everything below. crypto/context.c
OSSL_PROVIDER A loaded provider's runtime handle. crypto/provider_core.c
OSSL_NAMEMAP Per-libctx name↔id table. crypto/core_namemap.c
OSSL_PROPERTY_LIST A parsed property query. crypto/property/property_parse.c
OSSL_METHOD_STORE Per-operation cache of (name id, property, provider) → method. crypto/property/property.c
OSSL_DISPATCH {function_id, function_pointer} pair (from core.h). include/openssl/core.h
OSSL_ALGORITHM A row published by a provider: {names, properties, dispatch, description}. include/openssl/core.h

Each subsystem in libcrypto (EVP_MD, EVP_CIPHER, EVP_KEYMGMT, etc.) maintains its own OSSL_METHOD_STORE keyed by the operation id (OSSL_OP_DIGEST, OSSL_OP_CIPHER, …) so that fetch results are cached.

How fetch works

sequenceDiagram
    participant Caller
    participant EVP as EVP_MD_fetch
    participant MS as OSSL_METHOD_STORE
    participant NM as OSSL_NAMEMAP
    participant PS as Property store
    participant PROV as OSSL_PROVIDER
    Caller->>EVP: EVP_MD_fetch(libctx, "SHA2-256", "fips=yes")
    EVP->>NM: name -> id
    EVP->>PS: parse "fips=yes"
    EVP->>MS: lookup (id, props) hit?
    alt cache hit
        MS-->>EVP: cached EVP_MD
    else miss
        EVP->>PROV: for each provider: query OSSL_OP_DIGEST table
        PROV-->>EVP: OSSL_ALGORITHM[] (rows include their property defs)
        EVP->>PS: match each row's property def vs. query
        EVP->>EVP: build EVP_MD bound to chosen dispatch table
        EVP->>MS: cache (id, props) -> method
    end
    EVP-->>Caller: EVP_MD *

Code path:

  • crypto/evp/evp_fetch.c:evp_generic_fetch() is the per-operation entry point. It calls inner_evp_generic_fetch(), which goes through OSSL_method_construct() in crypto/core_fetch.c.
  • OSSL_method_construct walks the loaded providers in the libctx via provider_iter, calls each one's OSSL_FUNC_provider_query_operation to get the OSSL_ALGORITHM[], and asks the per-operation method store to install it.
  • The method store filters by property using crypto/property/property_query.c.

Library context lifecycle

OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();

OSSL_PROVIDER *fips = OSSL_PROVIDER_load(libctx, "fips");
OSSL_PROVIDER *base = OSSL_PROVIDER_load(libctx, "base");
EVP_set_default_properties(libctx, "?fips=yes");

EVP_MD *md = EVP_MD_fetch(libctx, "SHA2-256", NULL);
/* ... use md ... */
EVP_MD_free(md);

OSSL_LIB_CTX_free(libctx);    /* unloads providers, releases caches */

NULL for libctx means "the implicit default context"; OSSL_LIB_CTX_get0_default() returns its handle. The default context is initialised on first use.

Per-libctx data

Subsystems register a slot in the libctx's per-context data table during init. The pattern, from many _init.c files:

static void *foo_ctx_new(OSSL_LIB_CTX *libctx) { /* alloc state */ }
static void  foo_ctx_free(void *vctx) { /* free state */ }

static const OSSL_LIB_CTX_METHOD foo_method = {
    OSSL_LIB_CTX_METHOD_PRIORITY_2,
    foo_ctx_new, foo_ctx_free,
};

void *ossl_foo_ctx_get(OSSL_LIB_CTX *libctx)
{
    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FOO_INDEX, &foo_method);
}

The slot indices are enumerated in crypto/context.c. The mechanism keeps subsystems decoupled (no global init order, no global state).

Properties

A property string is a comma-separated list of key=value (or ?key=value for "soft" — preferred but not required). Examples:

Query Meaning
provider=default Only algorithms registered with provider=default.
fips=yes Hard requirement.
?fips=yes Prefer fips=yes if available, fall back otherwise.
provider=fips,fips=yes Compose constraints.
provider!=legacy Exclude legacy.

Parsing lives in crypto/property/property_parse.c; matching in property_query.c. The grammar is described at the top of the parser file and in doc/man7/property.pod.

Default property

Every libctx has a "default property query" — applied when the caller doesn't pass one. Set via EVP_set_default_properties() (or in openssl.cnf).

Provider objects

crypto/provider_core.c is by far the largest file in the core (84 KB). It owns:

  • The list of providers per libctx.
  • Each provider's OSSL_DISPATCH tables (the core directions, exposing libctx services to the provider, and the provider directions, exposing algorithms to libcrypto).
  • Activation reference counts (you can OSSL_PROVIDER_load/unload repeatedly).
  • The OSSL_PROVIDER_set_default_search_path mechanism for finding .so modules.
  • Hooks for child-libctx propagation (used by FIPS to spawn an internal libctx for its own algorithms).

The provider configuration via openssl.cnf is parsed by crypto/provider_conf.c, which interprets [providers], [default_sect], etc. and calls into the provider load path.

Initialization

crypto/init.c and crypto/initthread.c implement OPENSSL_init_crypto() (the public initialiser) and the per-thread cleanup hooks. The library uses one-time init (CRYPTO_THREAD_run_once) for everything; explicit init is rarely needed.

Integration points

  • Every EVP API routes through this code on first use of an algorithm in a libctx.
  • Providers call back into core via the dispatch table they receive in OSSL_provider_init to register names, allocate per-context data, query parameters, etc.
  • apps/openssl uses apps/lib/app_libctx.c to maintain the CLI's libctx and apply -provider / -propquery options.

Entry points for modification

  • Adding a per-libctx state slot: register a new OSSL_LIB_CTX_*_INDEX in crypto/context.c with a new/free method.
  • Touching the property syntax: crypto/property/property_parse.c. Consider how it interacts with provider=… matching in property_query.c.
  • Touching the provider load path: crypto/provider_core.c, crypto/provider_conf.c. Be careful with reference counting — providers can be loaded multiple times.

Documentation

  • doc/man7/crypto.pod — concepts.
  • doc/man7/provider.pod — provider authoring.
  • doc/man7/property.pod — property syntax.
  • doc/man3/OSSL_LIB_CTX.pod, OSSL_PROVIDER.pod, EVP_MD_fetch.pod, etc.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Core and library contexts – OpenSSL wiki | Factory