Open-Source Wikis

/

OpenSSL

/

Providers

openssl/openssl

Providers

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

Purpose

A provider is a module that contributes algorithm implementations to libcrypto. Since OpenSSL 3.0, every cryptographic algorithm reachable through the EVP API comes from one. Providers can be built into libcrypto itself or compiled as separate shared modules (.so/.dll) loaded at runtime.

The five providers shipped with OpenSSL:

Provider Built-in or module What it offers Source
default Built-in All standard algorithms (AES, SHA-2/3, RSA, EC, ChaCha20-Poly1305, HKDF, ML-KEM, ML-DSA, …) providers/defltprov.c
base Built-in Encoders/decoders and store loaders only — no crypto. Use with FIPS. providers/baseprov.c
legacy Module (legacy.so) Older algorithms: MD2/4, MDC2, RIPEMD-160, CAST5, Blowfish, IDEA, SEED, RC2/4/5, single DES providers/legacyprov.c
fips Module (fips.so) FIPS-validatable subset of the default provider providers/fips/fipsprov.c
null Built-in Nothing. Used to forbid implicit loading of default. providers/nullprov.c

External providers exist in the wild (oqs-provider, pkcs11-provider, gost-engine (as a provider), various HSM bindings); the in-tree submodule placeholders external/, oqs-provider/, pkcs11-provider/, and gost-engine/ are mount points used by the external test suites.

How providers integrate with libcrypto

graph TD
    LibCtx[OSSL_LIB_CTX] -->|tracks loaded| Prov[OSSL_PROVIDER list]
    Prov -->|each provides| Algos[OSSL_ALGORITHM array per OSSL_OP_*]
    LibCtx -->|EVP_*_fetch| Fetch[crypto/core_fetch.c]
    Fetch -->|consults| Namemap[crypto/core_namemap.c]
    Fetch -->|filters by| Property[crypto/property/]
    Fetch -->|returns| Disp[OSSL_DISPATCH bound to a provider]
    Disp -->|bound into| EVP[EVP_CIPHER, EVP_MD, EVP_PKEY, …]

The data flow on a fetch:

  1. The application calls EVP_MD_fetch(libctx, "SHA2-256", "fips=yes").
  2. Core looks up the integer name id in the namemap.
  3. Core asks every loaded provider in the libctx for its OSSL_OP_DIGEST algorithm table.
  4. Core picks the first algorithm whose algorithm_names matches and whose property_definition satisfies the query.
  5. Core builds an EVP_MD object whose method pointers are bound to the chosen provider's dispatch entries.

The full sequence with the relevant function ids lives in subsystems/core-and-libctx.

Provider operations (OSSL_OP_*)

Every operation a provider can implement has a numeric id defined in include/openssl/core_dispatch.h:

Operation id What it covers
OSSL_OP_DIGEST EVP_MD
OSSL_OP_CIPHER EVP_CIPHER
OSSL_OP_MAC EVP_MAC
OSSL_OP_KDF EVP_KDF
OSSL_OP_RAND EVP_RAND
OSSL_OP_KEYMGMT EVP_KEYMGMT
OSSL_OP_KEYEXCH EVP_KEYEXCH
OSSL_OP_SIGNATURE EVP_SIGNATURE
OSSL_OP_ASYM_CIPHER EVP_ASYM_CIPHER
OSSL_OP_KEM EVP_KEM
OSSL_OP_ENCODER / OSSL_OP_DECODER EVP_ENCODER / EVP_DECODER
OSSL_OP_STORE OSSL_STORE_LOADER
OSSL_OP_SKEYMGMT EVP_SKEYMGMT

Each operation has a set of OSSL_FUNC_*_* function ids — newctx, freectx, init, update, final, dupctx, get_ctx_params, set_ctx_params, gettable_ctx_params, settable_ctx_params, get_params, set_params. A provider declares which of these it implements in its OSSL_DISPATCH table for that algorithm.

Where the implementations live

Algorithm implementations live under providers/implementations/:

providers/implementations/
├── asymciphers/      -- RSA-OAEP, RSA-PKCS#1, SM2
├── ciphers/          -- AES, ChaCha20-Poly1305, AES-GCM-SIV, …
├── digests/          -- SHA-2, SHA-3, BLAKE2, KECCAK-KMAC, MDC2, MD2/4/5, …
├── encode_decode/    -- DER↔PEM↔text↔structured-params codecs
├── exchange/         -- DH, ECDH
├── kdfs/             -- HKDF, PBKDF2, scrypt, Argon2, IKEv2-KDF, KBKDF, KRB5KDF, SSH-KDF, X9.42, X9.63, SS-KDF, SRTP-KDF, TLS1-PRF, hmac-DRBG-KDF
├── kem/              -- RSA-KEM, ML-KEM
├── keymgmt/          -- key import/export/check for every public-key algorithm
├── macs/             -- HMAC, CMAC, GMAC, KMAC, Poly1305, SipHash, BLAKE2-MAC
├── rands/            -- DRBGs (HMAC, HASH, CTR), the test/seed source
├── signature/        -- RSA, DSA, ECDSA, EdDSA, ML-DSA, SLH-DSA, LMS, SM2, mac-as-signature
├── skeymgmt/         -- opaque symmetric keys (3.4+)
├── storemgmt/        -- file:, pkcs11:, etc. URI loaders
└── include/          -- per-area helpers

The default and FIPS providers select subsets of the same source tree. providers/fips.module.sources lists every file (and SHA-256 of every file) that goes into the FIPS module — that's how the integrity check works. See providers/fips.

Common helpers

providers/common/ holds shared helpers used by every algorithm implementation:

File Purpose
provider_ctx.c, bio_prov.c, digest_to_nid.c Per-context boilerplate.
capabilities.c The OSSL_OP_PROVIDER capability table (TLS-GROUP, TLS-SIGALG, …).
securitycheck.c, securitycheck_default.c, securitycheck_fips.c Strength/key-size policy enforcement.
der/ Generated DER encoders for SignatureAlgorithm parameters, AlgorithmIdentifier values, etc.
provider_seeding.c Seed-source plumbing for the DRBGs.
provider_util.c Shared utilities (e.g. property string parsing helpers).
provider_err.c The PROV_R_* reason codes.

Loading at runtime

OSSL_PROVIDER *p_default = OSSL_PROVIDER_load(NULL, "default");
OSSL_PROVIDER *p_legacy  = OSSL_PROVIDER_load(NULL, "legacy");
OSSL_PROVIDER_unload(p_default);
OSSL_PROVIDER_unload(p_legacy);

Or via openssl.cnf:

[providers_section]
default = default_sect
legacy  = legacy_sect

[default_sect]
activate = 1

[legacy_sect]
activate = 1

A provider module's only required public symbol is OSSL_provider_init (declared in include/openssl/core.h). The function gets a callback dispatch table from libcrypto, decides what it offers, and returns its own dispatch table.

Writing a provider

doc/man7/provider.pod is the canonical guide. The minimal skeleton:

  1. OSSL_provider_init(handle, in, out, provctx) — return your dispatch table and any provctx.
  2. Implement OSSL_FUNC_provider_query_operation — return an OSSL_ALGORITHM[] for each OSSL_OP_* you handle.
  3. For each algorithm, implement the OSSL_FUNC_<op>_* functions defined in core_dispatch.h.

test/p_test.c and test/p_minimal.c are tiny example providers; test/tls-provider.c is a more substantial one used to stress the TLS-GROUP / TLS-SIGALG capability path.

How the FIPS module differs

The FIPS provider is loaded just like any other. The differences are:

  • It is shipped as a separate shared object (fips.so) so its bytes can be checksummed independently.
  • It runs Known-Answer Tests at startup before any algorithm is exposed (providers/fips/self_test.c, self_test_data.c, self_test_kats.c).
  • It enforces stricter parameter ranges (providers/common/securitycheck_fips.c).
  • It applies a per-machine fipsmodule.cnf (generated by openssl fipsinstall) that records the module's checksum and self-test status.

See providers/fips.

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

Providers – OpenSSL wiki | Factory