Open-Source Wikis

/

curl

/

Features

/

TLS backends

curl/curl

TLS backends

Active contributors: Daniel Stenberg, Stefan Eissing, Viktor Szakats, Jay Satiro

Purpose

curl supports multiple TLS implementations behind a uniform internal API called "vtls". Pick one (or several) at build time. The shared abstraction lives in lib/vtls/vtls.c and lib/vtls/vtls.h; each backend is a separate .c file in lib/vtls/ plus its Curl_ssl vtable.

Supported backends

Backend Source Notes
OpenSSL / LibreSSL / BoringSSL / AWS-LC / quictls lib/vtls/openssl.c (~171 KB) The reference and most-tested backend
GnuTLS lib/vtls/gtls.c (~74 KB) Common on Linux distros that avoid OpenSSL
mbedTLS lib/vtls/mbedtls.c (~51 KB) Popular for embedded
Schannel lib/vtls/schannel.c (~99 KB), lib/vtls/schannel_verify.c Native Windows, uses the OS cert store
wolfSSL lib/vtls/wolfssl.c (~74 KB) Embedded-focused, FIPS variants
Rustls lib/vtls/rustls.c (~45 KB) Memory-safe, increasingly popular
Apple SecTrust lib/vtls/apple.c (~9 KB) Replacement for SecureTransport, uses the system trust store

Removed since 2024: NSS, BearSSL, MesaLink, Hyper, msh3, GSKit, Heimdal-only paths. SecureTransport itself was deprecated in 2025.

Key abstractions

Symbol File Description
struct Curl_ssl lib/vtls/vtls.h The vtable each backend exports — connect, send, recv, shutdown, info, …
struct ssl_connect_data lib/vtls/vtls_int.h Per-connection TLS state (handshake state, peer info, certs)
struct ssl_primary_config lib/urldata.h The user-visible options that affect TLS connection identity
Curl_ssl_cfilter_add() lib/vtls/vtls.c Pushes the TLS cfilter onto a connection
Curl_ssl_cfilter_for_proxy_add() lib/vtls/vtls.c Same, for HTTPS-proxy CONNECT TLS
Curl_ssl_scache_* lib/vtls/vtls_scache.c TLS-session cache (PSK reuse, ticket reuse)
Curl_ssl_cipher_suite_* lib/vtls/cipher_suite.c Curl's portable cipher-suite naming
Curl_x509asn1_* lib/vtls/x509asn1.c Backend-independent ASN.1 + X.509 parser used for getinfo queries
keylog_* lib/vtls/keylog.c Single shared SSLKEYLOGFILE writer

How it works

The TLS layer is a connection filter. When a connection should use TLS, Curl_ssl_cfilter_add (or its proxy sibling) pushes a Curl_cftype whose do_connect drives the TLS handshake of the active backend.

sequenceDiagram
    participant Conn as connectdata
    participant CF as cf_tls
    participant SSL as Curl_ssl vtable
    participant Lib as backend (e.g. OpenSSL)
    Conn->>CF: connect()
    CF->>SSL: connect_blocking
    SSL->>Lib: SSL_connect / mbedtls_handshake / ...
    Lib-->>SSL: WANT_READ / WANT_WRITE / OK
    SSL-->>CF: CURLE_AGAIN or CURLE_OK
    CF-->>Conn: handshake done
    Conn->>CF: send/recv
    CF->>SSL: encrypt / decrypt
    SSL->>Lib: SSL_write / SSL_read

Each backend's Curl_ssl vtable implements the same shape:

const struct Curl_ssl Curl_ssl_openssl = {
  { CURLSSLBACKEND_OPENSSL, "openssl" },
  /* features */ SSLSUPP_..., size_of_per_connection_state,
  ossl_init, ossl_cleanup, ossl_version,
  ossl_data_pending, ossl_random,
  ossl_cert_status_request, ossl_connect, ossl_connect_nonblocking,
  /* … */
};

lib/vtls/vtls.c picks at runtime among the backends compiled in (multiSSL: a build can include several and choose one via CURLOPT_SSL_OPTIONS / --ssl-backend).

Session cache

lib/vtls/vtls_scache.c is a backend-agnostic cache of TLS session tickets / PSKs keyed on origin. It lets a TLS-resumed handshake skip a round trip on reconnect. The cache is shareable via CURL_LOCK_DATA_SSL_SESSION on a share handle.

Cipher suite naming

To let users specify cipher suites portably, curl maintains its own naming layer in lib/vtls/cipher_suite.c. --ciphers and --tls13-ciphers accept curl's spelling and the backend translates it into native names.

Trust roots

By default each backend uses its own trust source:

  • OpenSSL/GnuTLS/mbedTLS/wolfSSL/Rustls — use a CA bundle (/etc/ssl/..., CURLOPT_CAINFO, --cacert) or a CA path
  • Schannel/Apple — use the OS trust store
  • All — pinning via CURLOPT_PINNEDPUBLICKEY and --pinnedpubkey

The CA bundle generator is scripts/mk-ca-bundle.pl — it reads Mozilla's certdata.txt and produces a PEM file. Trust details: docs/SSLCERTS.md.

ECH (Encrypted Client Hello)

Experimental ECH support exists for OpenSSL forks that have it (BoringSSL, AWS-LC, OpenSSL with the relevant patches). Helpers live in the OpenSSL backend; docs/ECH.md documents the user-visible interface.

Integration points

  • Connection filters: TLS is a cfilter; the rest of curl never sees the encryption details. See Connection filters.
  • Connection cache: ssl_primary_config participates in the connection key — two requests with mismatched TLS options never share a connection.
  • HTTP/2 and HTTP/3: ALPN runs as part of the handshake; the result drives whether the next filter pushed is HTTP/2 or fallback HTTP/1.1. See HTTP/2 and HTTP/3.
  • Proxies: there can be two TLS filters in the stack (one to the proxy, one to the origin). See Proxies.

Entry points for modification

  • New backend → copy lib/vtls/openssl.c shape, implement Curl_ssl vtable, register in lib/vtls/vtls.c, wire build flags into configure.ac and CMakeLists.txt.
  • New TLS option → extend struct ssl_primary_config and struct ssl_general_config (lib/urldata.h), add a CURLOPT_* in include/curl/curl.h, dispatch in lib/setopt.c, then wire each backend's connect-config code.
  • New cipher suite name → lib/vtls/cipher_suite.c.

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

TLS backends – curl wiki | Factory