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:
- The application calls
EVP_MD_fetch(libctx, "SHA2-256", "fips=yes"). - Core looks up the integer name id in the namemap.
- Core asks every loaded provider in the libctx for its
OSSL_OP_DIGESTalgorithm table. - Core picks the first algorithm whose
algorithm_namesmatches and whoseproperty_definitionsatisfies the query. - Core builds an
EVP_MDobject 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 helpersThe 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 = 1A 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:
OSSL_provider_init(handle, in, out, provctx)— return your dispatch table and any provctx.- Implement
OSSL_FUNC_provider_query_operation— return anOSSL_ALGORITHM[]for eachOSSL_OP_*you handle. - For each algorithm, implement the
OSSL_FUNC_<op>_*functions defined incore_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 byopenssl 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.