TLS backend matrix
Which TLS backends build and pass the suite, on which platforms.
---xtc’s TLS layer (xtc_tls) is one internal seam fronted by several
configure-time-selected backends. The OpenSSL-API backend
(src/io/tls_openssl.c) compiles unchanged against any
OpenSSL-compatible library – OpenSSL, LibreSSL, and BoringSSL – and
the other libraries have their own backend source. This document
records the tested combinations.
Backends and their source
| –with-tls | source file | flavor notes |
|---|---|---|
| openssl | tls_openssl.c | default |
| libressl | tls_openssl.c | OpenSSL-API alias; documents what you built against |
| boringssl | tls_openssl.c | OpenSSL-API; tls_openssl.c gates the API gap (no SSL_read_ex/SSL_write_ex) on OPENSSL_IS_BORINGSSL |
| mbedtls | tls_mbedtls.c | native mbedTLS API |
| gnutls | tls_gnutls.c | native GnuTLS API |
| wolfssl | tls_wolfssl.c | native wolfSSL API |
| schannel | tls_schannel.c | Windows SSPI; compile-only |
| none | tls_none.c | XTC_E_NOSYS stubs |
OpenSSL-API source compatibility
src/io/tls_openssl.c uses only the public OpenSSL 1.1+ API:
TLS_method/TLS_client_method/TLS_server_methodSSL_CTX_new/SSL_CTX_set_min_proto_version/SSL_CTX_set_max_proto_versionSSL_CTX_use_certificate_chain_file/SSL_CTX_use_PrivateKey_file/SSL_CTX_check_private_keySSL_CTX_load_verify_locations/SSL_CTX_set_verifySSL_CTX_set_alpn_protos/SSL_CTX_set_alpn_select_cbSSL_new/SSL_set_fd/SSL_do_handshake/SSL_read/SSL_write/SSL_shutdown/SSL_freeSSL_get_error/ERR_get_error/ERR_error_string
These are stable across OpenSSL 1.1.1+, 3.x, and LibreSSL 3.x+ with no
version-specific #ifdefs. BoringSSL is the one exception: it omits
the OpenSSL 1.1.1 SSL_read_ex / SSL_write_ex byte-count forms, so
tls_openssl.c wraps the classic SSL_read / SSL_write behind the
same 1-on-success/size_t-out contract, gated on the
OPENSSL_IS_BORINGSSL macro BoringSSL defines.
Tested matrix
Each backend builds the library and runs the m18 TLS suite
(test_tls_server, test_tls_client; test_tls_basic where present).
All certs are generated at runtime with an explicit -config, so the
suite is backend-agnostic.
| Backend | Build | tls_server (5) | tls_client (2) | Notes |
|---|---|---|---|---|
| OpenSSL 3.x | OK | 5/5 | 2/2 | Linux Nix; default |
| LibreSSL 4.x | OK | 5/5 | 2/2 | OpenSSL-API; re-verified against LibreSSL 4.2.1 (2026-07-06) – full client<->server handshake + verify + bad-CA reject all pass |
| BoringSSL (2026-05) | OK | 5/5 | 2/2 | OpenSSL-API; SSL_read_ex shim; static libssl.a + -lstdc++ |
| mbedTLS 3.x | OK | 5/5 | 2/2 | native backend; client needs mbedtls_ssl_set_hostname(NULL) |
| GnuTLS 3.x | OK | 5/5 | 2/2 | native backend |
| wolfSSL 5.x | OK | 5/5 | 2/2 | native backend |
| SChannel (Windows) | compile-only | – | – | written to the seam; not runtime-verified (no Windows host) |
All listed backends except SChannel are runtime-verified on Linux/Nix.
Dedicated CI jobs (tls-backends) re-build and re-run the suite on
every push: the GitHub mirror covers openssl, gnutls, wolfssl,
mbedtls (built 3.x from source – apt ships an incompatible 2.x), and
boringssl (built from source – no distro packages it); the Codeberg
/ Forgejo side covers openssl, gnutls, and wolfssl from apt.
Reproducing
OpenSSL (default):
cd build_unix
nix-shell -p openssl pkg-config liburing --command \
'../dist/configure --with-tls=auto && make -j4 test_tls_basic test_tls_client test_tls_server'
./test_tls_basic
./test_tls_client
./test_tls_server
LibreSSL (drop-in replacement, same source):
mkdir -p /tmp/xtc_libressl_build && cd /tmp/xtc_libressl_build
nix-shell -p libressl pkg-config liburing --command \
'CFLAGS="-I$(pkg-config --variable=prefix libssl)/include" \
LDFLAGS="-L$(pkg-config --variable=prefix libssl)/lib \
-Wl,-rpath,$(pkg-config --variable=prefix libssl)/lib" \
/home/gburd/ws/xtc/dist/configure --with-tls=libressl \
--with-liburing=/nix/store/ydz5gvanzqmy8cnfyp0y0sy4ypfx4fss-liburing-2.14-dev && \
make -j4 test_tls_basic test_tls_server'
./test_tls_basic # 9/9
./test_tls_server # 5/5
BoringSSL (OpenSSL-API; ships static libssl.a/libcrypto.a and is part C++, so name the lib dir and add -lstdc++):
mkdir -p /tmp/xtc_boringssl_build && cd /tmp/xtc_boringssl_build
nix-shell -p boringssl pkg-config liburing --command '
DEV=$(echo /nix/store/*boringssl*-dev); LIB=$(dirname $(echo /nix/store/*boringssl*/lib/libssl.a));
CPPFLAGS="-I$DEV/include" LDFLAGS="-L$LIB" LIBS="-lstdc++" \
/home/gburd/ws/xtc/dist/configure --with-tls=boringssl && \
make -j4 test_tls_server test_tls_client'
./test_tls_server # 5/5
./test_tls_client # 2/2
Cert generation
Tests that need a self-signed cert call generate_cert() in
test/m18/test_tls_{client,server}.c. This shell-out to the
system openssl req -x509 ... was previously fragile because
LibreSSL on Nix and stripped distros ship openssl without a
default openssl.cnf. The current implementation writes a minimal
inline config to <cert_path>.cnf and passes -config explicitly,
so cert generation works regardless of distribution.