openssl/openssl
Architecture
OpenSSL has two major libraries, a CLI front-end, and a pluggable provider model that decouples algorithm implementations from the public API.
Top-level layout
graph TD
subgraph Application
APP[Your application or apps/openssl]
end
subgraph libssl[libssl - TLS, DTLS, QUIC]
SSL[ssl/ssl_lib.c, statem, record, quic, ech]
end
subgraph libcrypto[libcrypto - everything else]
EVP[EVP API<br/>crypto/evp]
CORE[Core: libctx, namemap, fetch<br/>crypto/context.c, core_namemap.c]
BIO[BIO, BIGNUM, ASN.1, X.509,<br/>CMS, PKCS, OCSP, CMP, TS, …]
end
subgraph providers[Providers - algorithm impls]
DEF[default<br/>providers/defltprov.c]
FIPS[fips<br/>providers/fips/]
LEG[legacy<br/>providers/legacyprov.c]
BASE[base<br/>providers/baseprov.c]
NULL[null<br/>providers/nullprov.c]
IMPL[providers/implementations/<br/>ciphers digests kdfs kem signature …]
end
APP -->|TLS API: SSL_*, SSL_CTX_*| SSL
APP -->|crypto API: EVP_*, X509_*, BIO_*, …| EVP
SSL -->|EVP_CIPHER, EVP_MD, EVP_PKEY| EVP
EVP -->|fetch / dispatch table| CORE
CORE -->|OSSL_DISPATCH| DEF
CORE --> FIPS
CORE --> LEG
CORE --> BASE
CORE --> NULL
DEF --> IMPL
FIPS --> IMPL
LEG --> IMPL
BIO -.shared by.-> SSLThe arrows tell you the only sanctioned data flows:
- Applications call into
libssl(for TLS/DTLS/QUIC) or directly intolibcrypto(for everything else). libssluseslibcrypto's EVP API for all crypto. There is no secret-handling code that lives only inlibssl— it must go through EVP and end up in a provider. The TLS state machine itself does, of course, live inssl/statem/.- The EVP layer in
libcryptodoes not implement algorithms. It looks them up by name and properties from one of the loaded providers and calls through anOSSL_DISPATCHfunction table. - Providers are the only place where actual algorithm code (AES, SHA-3, RSA, ML-KEM, …) lives. The default and FIPS providers share most of
providers/implementations/; they differ in which algorithms they expose and in extra security checks.
libcrypto
libcrypto is the foundation. It is divided into roughly three layers:
- Core (
crypto/context.c,crypto/core_*.c,crypto/provider*.c,crypto/property/). Owns theOSSL_LIB_CTX(per-process or per-context state), the namemap (algorithm names → integers), the property store (e.g.fips=yes,provider=default), the provider loader, and the algorithm cache. - EVP (
crypto/evp/). The public, algorithm-agnostic API:EVP_CIPHER,EVP_MD,EVP_PKEY,EVP_KDF,EVP_MAC,EVP_RAND,EVP_KEM,EVP_SIGNATURE,EVP_KEYEXCH,EVP_KEYMGMT,EVP_ENCODER,EVP_DECODER,EVP_SKEYMGMT. Plus the legacy controller-styleEVP_PKEY_CTX_ctrl()translator (crypto/evp/ctrl_params_translate.c). - Domain libraries. ASN.1 (
crypto/asn1/), BIGNUM (crypto/bn/), X.509 (crypto/x509/), CMS (crypto/cms/), PKCS#7 (crypto/pkcs7/), PKCS#12 (crypto/pkcs12/), OCSP (crypto/ocsp/), CMP (crypto/cmp/,crypto/crmf/), TS (crypto/ts/), HTTP client (crypto/http/), STORE (crypto/store/), encoders/decoders (crypto/encode_decode/), error machinery (crypto/err/), threading (crypto/thread*.c), memory (crypto/mem*.c), tracing (crypto/trace.c), and many more. Each domain owns its part of the public API but routes the cryptographic primitives through EVP.
Per-domain pages: see subsystems/ for the most-used pieces (EVP, ASN.1, BIO, error, threading, memory, RAND, core/libctx).
libssl
libssl implements all current TLS, DTLS, and QUIC variants. Its directories:
ssl/ssl_lib.c(226 KB),149 KB),ssl/s3_lib.c(ssl/t1_lib.c(~173 KB) — the main connection objects (SSL,SSL_CTX), cipher suite logic, and TLS 1.0–1.3 protocol code.ssl/statem/— the handshake state machine. Separate files for client (statem_clnt.c), server (statem_srvr.c), DTLS (statem_dtls.c), and shared dispatch (statem.c,statem_lib.c). Extension handling lives inssl/statem/extensions*.c.ssl/record/— the record layer. Pluggable record method objects inssl/record/methods/and the record-layer code for TLS (rec_layer_s3.c) and DTLS (rec_layer_d1.c).ssl/quic/— the QUIC implementation: channel, port, transport parameters, packetization, retransmission, ACK manager, congestion control, demux, and a tserver test harness. See features/quic.ssl/ech/— ECH (Encrypted Client Hello), an experimental TLS extension. See features/tls.ssl/rio/— the RIO event-driven I/O abstraction used by QUIC.
For the handshake walk-through, see features/tls.
The openssl CLI
apps/openssl.c is the front door. Each subcommand is a .c file in apps/: req.c, x509.c, s_client.c, s_server.c, cms.c, cmp.c, speed.c, genpkey.c, pkeyutl.c, enc.c, dgst.c, verify.c, ts.c, … Subcommands share helpers in apps/lib/. The list of subcommands is generated from apps/progs.pl. See libraries/openssl-cli.
The provider model (key concept)
Since OpenSSL 3.0, every cryptographic algorithm in libcrypto is reached through a provider. A provider is a module (built-in or dynamically loadable shared object) that publishes a set of algorithms via dispatch tables.
sequenceDiagram
participant App
participant EVP as EVP_* in libcrypto
participant Core as core / libctx
participant Prov as provider (default/fips/...)
App->>EVP: EVP_CIPHER_fetch(libctx, "AES-256-GCM", "fips=yes")
EVP->>Core: OSSL_method_construct(...)
Core->>Core: lookup by namemap + property query
Core->>Prov: query operation table
Prov-->>Core: OSSL_ALGORITHM[] for OSSL_OP_CIPHER
Core->>Prov: provider's algorithm "newctx" function
Prov-->>Core: provctx
Core-->>EVP: EVP_CIPHER bound to dispatch table
EVP-->>App: EVP_CIPHER *
App->>EVP: EVP_EncryptInit_ex2 / Update / Final
EVP->>Prov: dispatch via OSSL_FUNC_cipher_*Key files:
include/openssl/core.h— the small set of types (OSSL_DISPATCH,OSSL_PARAM,OSSL_ALGORITHM,OSSL_CALLBACK) that flow between core and providers.include/openssl/core_dispatch.h— every dispatch ID and function signature (OSSL_FUNC_*).include/openssl/core_names.h.in— every well-known parameter and provider name string constant.crypto/provider_core.c— the core's view of a provider (load, init, query).crypto/core_fetch.c,crypto/core_namemap.c— algorithm lookup.crypto/property/— property string parser and matcher.providers/defltprov.c,providers/fips/fipsprov.c,providers/legacyprov.c,providers/baseprov.c,providers/nullprov.c— the five built-in providers' entry points.providers/implementations/**— the algorithm implementations themselves.
For the full discussion, see providers/ and subsystems/core-and-libctx.
Library context (OSSL_LIB_CTX)
Almost every public API in 3.x and later takes (or has a _ex variant that takes) an OSSL_LIB_CTX *libctx. A library context owns:
- Loaded providers
- The algorithm namemap and fetch cache
- Default property query
- Per-context RNG state
- Configuration
NULL means "the default library context". This is what makes it possible to have, in the same process, one context that uses the FIPS provider and another that uses the default provider. See subsystems/core-and-libctx.
Trust boundaries
graph LR
Net[Untrusted network bytes] -->|record layer parses| Record[ssl/record/, ssl/quic/quic_record_*.c]
Record -->|after AEAD decrypt| Statem[ssl/statem/]
User[Application bytes / files] -->|BIO_*| BIO[crypto/bio]
BIO -->|d2i_, PEM_read_| ASN1[crypto/asn1, x509]
ASN1 -->|verified| EVP[EVP_*]
EVP -->|via OSSL_DISPATCH| Prov[provider]
Conf[openssl.cnf] -->|crypto/conf/| Init[OPENSSL_init_*]
Init --> EVPAnything that comes from the network or the filesystem is parsed in crypto/asn1/, crypto/x509/, crypto/pem/, crypto/cms/, or the ssl/ record layer before it reaches the algorithm code in providers/. See pitfalls for security-sensitive integration gotchas.
Where to go next
- For a build-and-run walkthrough: getting-started.
- For the vocabulary: glossary.
- For the deeper "why" behind the provider split: background/migration-3x.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.