libxtc 0.4.0
Async concurrency for C: Tokio + Seastar + BEAM, in one library
Loading...
Searching...
No Matches
xtc_tls.h
1/*-
2 * Copyright (c) 2026, The XTC Project
3 * @stability stable
4 * Use of this source code is governed by the ISC License,
5 * a copy of which is in the file LICENSE in the top-level directory
6 * of this distribution.
7 *
8 * src/inc/xtc_tls.h
9 * Transport Layer Security (TLS) API for xtc.
10 *
11 * Provides TLS 1.2/1.3 over xtc_io sockets with the same async,
12 * single-threaded event-loop discipline as the rest of xtc. The
13 * implementation is backend-pluggable at configure time via
14 * --with-tls=openssl|none|auto; the public API is identical
15 * regardless of the backend selected.
16 *
17 * Two opaque types:
18 * xtc_tls_ctx_t -- per-process context: loaded cert + key + CA bundle.
19 * xtc_tls_t -- per-connection state machine.
20 *
21 * Usage pattern:
22 *
23 * // 1. Create a shared context (once per server/client role):
24 * xtc_tls_opts_t opts = { .size = sizeof(xtc_tls_opts_t),
25 * .cert_file = "srv.crt", .key_file = "srv.key",
26 * .min_version = XTC_TLS_VER_12 };
27 * xtc_tls_ctx_t *ctx;
28 * xtc_tls_ctx_create(XTC_TLS_SERVER, &opts, &ctx);
29 *
30 * // 2. Wrap an accepted fd:
31 * xtc_tls_t *tls;
32 * xtc_tls_create(ctx, fd, &tls);
33 *
34 * // 3. Drive the non-blocking handshake inside the event loop:
35 * for (;;) {
36 * int rc = xtc_tls_handshake(tls);
37 * if (rc == XTC_OK) break;
38 * if (rc != XTC_E_AGAIN) { break; } // hard error: tear down
39 * uint32_t want = xtc_tls_wants_read(tls)
40 * ? XTC_IO_READABLE : XTC_IO_WRITABLE;
41 * xtc_io_mod_fd(io, fd, want, tls);
42 * // yield, await event ...
43 * }
44 *
45 * // 4. Encrypted I/O:
46 * size_t n;
47 * xtc_tls_read(tls, buf, sizeof(buf), &n);
48 * xtc_tls_write(tls, "hello", 5, &n);
49 *
50 * // 5. Graceful shutdown + cleanup:
51 * xtc_tls_shutdown(tls);
52 * xtc_tls_destroy(tls);
53 * xtc_tls_ctx_destroy(ctx);
54 *
55 * When TLS support is not compiled in (--with-tls=none), every
56 * function returns XTC_E_NOSYS; callers may test for that at
57 * runtime to skip TLS-dependent code paths.
58 */
59
60#ifndef XTC_TLS_H
61#define XTC_TLS_H
62
63#include "xtc_export.h"
64
65#include <stddef.h>
66#include "xtc.h"
67
68/*
69 * XTC_TLS_ENABLED is defined (to 1) whenever a real TLS backend is
70 * compiled in -- any one of OpenSSL/LibreSSL, mbedTLS, GnuTLS, wolfSSL,
71 * or SChannel. It is NOT defined for --with-tls=none (the NOSYS
72 * stubs). Callers and tests use it to gate code that needs a working
73 * handshake without caring which backend provides it. The selecting
74 * XTC_TLS_BACKEND_* macro comes from xtc_config.h via configure.
75 */
76#if defined(XTC_TLS_BACKEND_OPENSSL) || \
77 defined(XTC_TLS_BACKEND_MBEDTLS) || \
78 defined(XTC_TLS_BACKEND_GNUTLS) || \
79 defined(XTC_TLS_BACKEND_WOLFSSL) || \
80 defined(XTC_TLS_BACKEND_SCHANNEL)
81#define XTC_TLS_ENABLED 1
82#endif
83
84#ifdef __cplusplus
85extern "C" {
86#endif
87
88/* -------------------------------------------------------------------------
89 * Opaque types.
90 * ----------------------------------------------------------------------- */
91
92/*
93 * xtc_tls_ctx_t -- per-process (or per-vhost) TLS context.
94 *
95 * Holds the loaded certificate, private key, and CA bundle. A
96 * single context may be shared by many concurrent connections of
97 * the same role; it is internally reference-safe via immutable
98 * configuration after creation.
99 */
100typedef struct xtc_tls_ctx xtc_tls_ctx_t;
101
102/*
103 * xtc_tls_t -- per-connection TLS state machine.
104 *
105 * Wraps an existing file descriptor. The fd remains owned by the
106 * caller; xtc_tls_destroy does not close it.
107 */
108typedef struct xtc_tls xtc_tls_t;
109
110/* -------------------------------------------------------------------------
111 * Role.
112 * ----------------------------------------------------------------------- */
113
114typedef enum xtc_tls_role {
115 XTC_TLS_SERVER = 0, /* accept connections, present certificate */
116 XTC_TLS_CLIENT = 1 /* initiate connections, verify server (default) */
117} xtc_tls_role_t;
118
119/* -------------------------------------------------------------------------
120 * TLS version constants.
121 * ----------------------------------------------------------------------- */
122
123#define XTC_TLS_VER_12 0x0303 /* TLS 1.2 (RFC 5246) */
124#define XTC_TLS_VER_13 0x0304 /* TLS 1.3 (RFC 8446) */
125
126/* -------------------------------------------------------------------------
127 * Peer-verification mode (tri-state).
128 *
129 * The legacy opts.verify_peer int is a two-state on/off. A TLS server
130 * often needs the third, middle behavior: REQUEST a client certificate
131 * but still complete the handshake if the client presents none (PG's
132 * default -- certificate auth is then optional, decided per-hba-line
133 * after the handshake). opts.verify_peer_mode expresses all three.
134 * See the compatibility note on opts.verify_peer below.
135 *
136 * Resolution, identical on every backend (OpenSSL, GnuTLS, wolfSSL,
137 * mbedTLS, and since 1.51 SChannel): verify_peer_mode wins when not
138 * DEFAULT; else a non-zero legacy verify_peer means REQUIRE; else the ROLE
139 * default -- CLIENT: REQUIRE, SERVER: NONE. (SChannel in 1.50 read only
140 * verify_peer, so a zeroed SChannel CLIENT verified nothing.)
141 *
142 * BEHAVIOR CHANGE: Since 1.50 a CLIENT verifies the server by default;
143 * set verify_peer_mode = XTC_TLS_VERIFY_NONE to opt out. Before 1.50 a
144 * zeroed opts (or NULL opts) resolved to NONE for a CLIENT too, so it
145 * accepted ANY server certificate; and the GnuTLS, wolfSSL and mbedTLS
146 * backends ignored verify_peer_mode and read only verify_peer.
147 *
148 * On a CLIENT, REQUEST behaves as REQUIRE (a server always presents a
149 * certificate). On a SERVER: NONE does not ask for a client
150 * certificate; REQUEST asks, completes the handshake when the client
151 * sends none, and fails it when the client sends one that does not
152 * verify against ca_file; REQUIRE also fails a client that sends none.
153 * ----------------------------------------------------------------------- */
154
155typedef enum xtc_tls_verify_mode {
156 XTC_TLS_VERIFY_DEFAULT = 0, /* legacy verify_peer, else role default */
157 XTC_TLS_VERIFY_NONE, /* do not request a peer certificate */
158 XTC_TLS_VERIFY_REQUEST, /* request; accept a handshake with none */
159 XTC_TLS_VERIFY_REQUIRE /* require a valid peer certificate */
160} xtc_tls_verify_mode_t;
161
162/* -------------------------------------------------------------------------
163 * Passphrase callback for an encrypted private key.
164 *
165 * Mirrors OpenSSL's pem_password_cb: write up to size bytes of the
166 * passphrase into buf and return the number written, or <= 0 to fail
167 * (which fails key load). userdata is opts.passphrase_userdata. When
168 * no callback is set and the key is encrypted, key load fails rather
169 * than prompting interactively -- a server must never block on a tty.
170 * ----------------------------------------------------------------------- */
171
172typedef int (*xtc_tls_passphrase_cb_t)(char *buf, int size, void *userdata);
173
174/* -------------------------------------------------------------------------
175 * Options.
176 * ----------------------------------------------------------------------- */
177
178/*
179 * xtc_tls_opts_t -- creation-time parameters for xtc_tls_ctx_create.
180 *
181 * All string pointers are borrowed for the duration of the
182 * xtc_tls_ctx_create call only; the implementation copies any data
183 * it needs before returning.
184 *
185 * Fields:
186 * cert_file Path to the PEM certificate file. Required for
187 * SERVER role; ignored (may be NULL) for CLIENT role
188 * unless mutual TLS is needed.
189 *
190 * key_file Path to the PEM private-key file matching cert_file.
191 * Required when cert_file is set.
192 *
193 * ca_file Path to a PEM CA bundle used for peer verification.
194 * If NULL, a verifying CLIENT uses the platform's
195 * default trust store: OpenSSL's default verify paths,
196 * GnuTLS's system trust, wolfSSL's system CA certs
197 * (when wolfSSL was built with WOLFSSL_SYS_CA_CERTS;
198 * otherwise there are no anchors and every handshake
199 * fails). mbedTLS has no platform store: there a
200 * verifying CLIENT with ca_file NULL is refused by
201 * xtc_tls_ctx_create with XTC_E_INVAL. A SERVER never
202 * trusts the platform store for client certificates;
203 * set ca_file to verify clients.
204 *
205 * verify_peer Legacy boolean. Non-zero = REQUIRE (for SERVER role
206 * that enables mutual TLS: the client must present a
207 * cert). 0 = the role default (see
208 * xtc_tls_verify_mode_t): since 1.50 that is REQUIRE for
209 * a CLIENT, NONE for a SERVER. Set
210 * verify_peer_mode = XTC_TLS_VERIFY_NONE to turn a
211 * client's verification off.
212 *
213 * alpn_protos ALPN protocol list in wire encoding:
214 * "\x02h2\x08http/1.1". NULL disables ALPN
215 * negotiation.
216 *
217 * min_version Minimum TLS version to accept. Use XTC_TLS_VER_12
218 * or XTC_TLS_VER_13. 0 means "backend default"
219 * (typically TLS 1.2).
220 *
221 * max_version Maximum TLS version to offer. 0 means "backend
222 * default" (typically TLS 1.3).
223 *
224 * Additions (all optional; a zeroed addition behaves as before 1.24 --
225 * except that since 1.50 a zeroed CLIENT opts verifies the server):
226 *
227 * verify_peer_mode Tri-state peer verification (see
228 * xtc_tls_verify_mode_t). When XTC_TLS_VERIFY_DEFAULT
229 * (0), the legacy verify_peer int is used, then the
230 * role default. Any other value takes precedence over
231 * verify_peer.
232 *
233 * cipher_list TLS 1.2 cipher list (OpenSSL SSL_CTX_set_cipher_list
234 * syntax). NULL = backend default.
235 * ciphersuites_13 TLS 1.3 ciphersuites. NULL = backend default.
236 * groups Key-exchange groups / curves, e.g.
237 * "X25519:prime256v1". NULL = backend default.
238 *
239 * crl_file PEM CRL file for revocation checking. NULL = none.
240 * crl_dir Hashed CRL directory. NULL = none. When either
241 * crl_file or crl_dir is set, full-chain CRL checking is
242 * enabled.
243 *
244 * prefer_server_ciphers Non-zero: honor the server's cipher order
245 * over the client's (SSL_OP_CIPHER_SERVER_PREFERENCE).
246 *
247 * passphrase_cb / passphrase_userdata Supply the passphrase for an
248 * encrypted key_file without an interactive prompt.
249 *
250 * Server hardening applied by default (no knob; a DB-server-safe posture
251 * the request asked to be a documented default rather than a field):
252 * TLS renegotiation is disabled, TLS compression is disabled, session
253 * tickets and the session cache are off, and the moving-write-buffer
254 * mode required for correct non-blocking sends is enabled.
255 */
256typedef struct xtc_tls_opts {
257 size_t size; /* sizeof(xtc_tls_opts_t): XTC_TLS_OPTS_INIT */
258 const char *cert_file;
259 const char *key_file;
260 const char *ca_file;
261 const char *alpn_protos;
262 int verify_peer; /* legacy on/off; see verify_peer_mode */
263 xtc_tls_verify_mode_t verify_peer_mode;
264 int min_version;
265 int max_version;
266 const char *cipher_list;
267 const char *ciphersuites_13;
268 const char *groups;
269 const char *crl_file;
270 const char *crl_dir;
271 int prefer_server_ciphers;
272 xtc_tls_passphrase_cb_t passphrase_cb;
273 void *passphrase_userdata;
275
276/* All defaults (role-default verification, library-default ciphers). */
277#define XTC_TLS_OPTS_INIT { .size = sizeof(xtc_tls_opts_t) }
278
279/* -------------------------------------------------------------------------
280 * Context lifecycle.
281 * ----------------------------------------------------------------------- */
282
283/*
284 * PUBLIC: int xtc_tls_ctx_create __P((xtc_tls_role_t,
285 * PUBLIC: const xtc_tls_opts_t *,
286 * PUBLIC: xtc_tls_ctx_t **));
287 * PUBLIC: void xtc_tls_ctx_destroy __P((xtc_tls_ctx_t *));
288 */
289
290/*
291 * xtc_tls_ctx_create --
292 * Allocate and initialise a TLS context.
293 *
294 * role SERVER or CLIENT.
295 * opts Options struct. May be NULL (all defaults; a CLIENT then
296 * verifies the server against the platform trust store).
297 * out On XTC_OK, *out points to the new context.
298 *
299 * Returns:
300 * XTC_OK on success
301 * XTC_E_INVAL if out is NULL or opts contains contradictory settings,
302 * or (mbedTLS only: no platform trust store) a
303 * verifying CLIENT has no ca_file
304 * XTC_E_NOMEM on allocation failure
305 * XTC_E_NOSYS if TLS support was not compiled in
306 */
307XTC_API int xtc_tls_ctx_create(xtc_tls_role_t role,
308 const xtc_tls_opts_t *opts,
309 xtc_tls_ctx_t **out);
310
311/*
312 * xtc_tls_ctx_destroy --
313 * Release all resources held by a TLS context.
314 * Must not be called while any xtc_tls_t created from it is live:
315 * live connections hold a raw pointer to the ctx (dereferenced e.g.
316 * by xtc_tls_get_server_cert_hash and xtc_tls_set_hostname), so
317 * destroying it underneath them is a use-after-free. The ctx is NOT
318 * refcounted. On config reload, build the NEW ctx and point new
319 * connections at it, but do NOT destroy the OLD ctx until all
320 * connections created from it have been xtc_tls_destroy()'d --
321 * retire it (e.g. to a list freed later) rather than freeing it in
322 * place. ctx may be NULL (no-op).
323 */
324XTC_API void xtc_tls_ctx_destroy(xtc_tls_ctx_t *ctx);
325
326/* -------------------------------------------------------------------------
327 * Per-connection lifecycle.
328 * ----------------------------------------------------------------------- */
329
330/*
331 * PUBLIC: int xtc_tls_create __P((xtc_tls_ctx_t *, int, xtc_tls_t **));
332 * PUBLIC: void xtc_tls_destroy __P((xtc_tls_t *));
333 */
334
335/*
336 * xtc_tls_create --
337 * Wrap an existing file descriptor in a TLS state machine.
338 *
339 * ctx The context created by xtc_tls_ctx_create.
340 * fd A non-blocking socket fd. Ownership remains with the caller;
341 * xtc_tls_destroy does not close fd.
342 * out On XTC_OK, *out points to the new xtc_tls_t.
343 *
344 * After this call the handshake has not yet run; call
345 * xtc_tls_handshake to drive it.
346 *
347 * Returns:
348 * XTC_OK on success
349 * XTC_E_INVAL if ctx or out is NULL, or fd < 0
350 * XTC_E_NOMEM on allocation failure
351 * XTC_E_NOSYS if TLS support was not compiled in
352 */
353XTC_API int xtc_tls_create(xtc_tls_ctx_t *ctx, int fd, xtc_tls_t **out);
354
355/* -------------------------------------------------------------------------
356 * SNI / ClientHello context-selection callback (multi-tenant servers).
357 *
358 * A server that presents different certificates for different requested
359 * host names (SNI) registers a selection callback on the SERVER context.
360 * During the handshake, after the ClientHello is parsed but before the
361 * certificate is chosen, the callback fires with the requested
362 * server_name (the SNI host, or NULL if the client sent none) and may
363 * return a DIFFERENT, pre-created xtc_tls_ctx_t whose certificate / key /
364 * CA / verify-mode is then used for the rest of THIS handshake -- exactly
365 * OpenSSL's SSL_CTX_set_client_hello_cb + SSL_set_SSL_CTX shape.
366 *
367 * Contract:
368 * - Return a pointer to one of your pre-created SERVER xtc_tls_ctx_t to
369 * swap it in for this connection, or
370 * - Return NULL (or the same ctx) to keep the current context.
371 * - The returned context MUST outlive the connection and MUST have
372 * been created with role XTC_TLS_SERVER; returning a CLIENT context
373 * or a destroyed one is undefined.
374 * - server_name points at backend-owned memory valid only for the
375 * duration of the callback; copy it if you need it later.
376 * - The callback runs on the carrier driving the handshake (the same
377 * thread as xtc_tls_handshake); it must not block.
378 *
379 * userdata is passed through unchanged. Registering on a CLIENT context
380 * or on a backend that cannot swap the context mid-handshake returns
381 * XTC_E_NOSYS.
382 * ----------------------------------------------------------------------- */
383
384typedef xtc_tls_ctx_t *(*xtc_tls_sni_cb_t)(xtc_tls_t *tls,
385 const char *server_name,
386 void *userdata);
387
388/*
389 * PUBLIC: int xtc_tls_ctx_set_sni_cb __P((xtc_tls_ctx_t *,
390 * PUBLIC: xtc_tls_sni_cb_t, void *));
391 */
392XTC_API int xtc_tls_ctx_set_sni_cb(xtc_tls_ctx_t *ctx,
393 xtc_tls_sni_cb_t cb, void *userdata);
394
395/* -------------------------------------------------------------------------
396 * Custom transport (caller owns recv/send instead of an fd).
397 *
398 * xtc_tls_create binds an fd and does its own recv/send. A consumer that
399 * must control the underlying transport -- to feed bytes it already read
400 * off the socket before deciding to negotiate TLS (pushback), to weave
401 * the read/write into its own interrupt / cancellation / fiber-yield
402 * discipline, or to handle a platform signal window -- supplies a
403 * transport instead, the same way OpenSSL's BIO lets an application own
404 * the wire. Only the TLS state machine lives in xtc_tls; every byte to
405 * or from the network flows through the caller's callbacks.
406 *
407 * Callback contract (BIO-like):
408 * read_cb: read up to len bytes into buf. Return >0 = bytes read;
409 * 0 = clean EOF (peer closed); XTC_E_AGAIN = would block
410 * (arm a readable watch and retry the TLS op); any other
411 * negative xtc error = hard failure.
412 * write_cb: write up to len bytes from buf. Return >0 = bytes
413 * written; XTC_E_AGAIN = would block (arm a writable watch);
414 * other negative = hard failure. A short write is fine.
415 * userdata: the transport's userdata, passed to both callbacks.
416 *
417 * A callback may yield the fiber (xtc_proc_wait_fd, xtc_proc_sleep, a
418 * channel receive) while other connections run on the same thread. The
419 * backend keeps each connection's TLS error state separate across that
420 * suspension (OpenSSL's error queue is per thread; it is saved before
421 * the callback and restored after it), so neither connection's failure
422 * is reported on the other. A callback must not itself call xtc_tls_*
423 * on the connection it serves.
424 *
425 * The caller retains ownership of whatever the transport wraps;
426 * xtc_tls_destroy does not touch it. There is no fd, so
427 * xtc_tls_wants_read/_write still report the direction the stall is in,
428 * but the caller drives its own transport readiness.
429 * ----------------------------------------------------------------------- */
430
431typedef struct xtc_tls_transport {
432 size_t size; /* sizeof(xtc_tls_transport_t): XTC_TLS_TRANSPORT_INIT */
433 int (*read_cb)(void *userdata, void *buf, size_t len);
434 int (*write_cb)(void *userdata, const void *buf, size_t len);
435 void *userdata;
437
438#define XTC_TLS_TRANSPORT_INIT { .size = sizeof(xtc_tls_transport_t) }
439
440/*
441 * PUBLIC: int xtc_tls_create_transport __P((xtc_tls_ctx_t *,
442 * PUBLIC: const xtc_tls_transport_t *,
443 * PUBLIC: xtc_tls_t **));
444 */
445XTC_API int xtc_tls_create_transport(xtc_tls_ctx_t *ctx,
446 const xtc_tls_transport_t *transport,
447 xtc_tls_t **out);
448
449/* -------------------------------------------------------------------------
450 * Client-side SNI / hostname (the other half of SNI).
451 *
452 * A CLIENT connection calls this before the handshake to send the
453 * requested host in the ClientHello's SNI extension (so a multi-tenant
454 * server's selection callback can pick the right certificate) and to
455 * enable RFC 6125 hostname verification against the server certificate
456 * (subjectAltName DNS entries, falling back to the CN where the backend
457 * does): a certificate that chains to a trusted CA but names a
458 * DIFFERENT host fails the handshake. The name is only enforced when
459 * the context verifies peers. name is copied; NULL or "" clears it
460 * (chain-only verification). Must be called before xtc_tls_handshake.
461 * Ignored (harmless) on a SERVER connection. Implemented on the
462 * OpenSSL, GnuTLS, wolfSSL and mbedTLS backends (before 1.50 only
463 * OpenSSL checked the name; the others returned XTC_E_NOSYS); still
464 * XTC_E_NOSYS on SChannel and --with-tls=none.
465 * ----------------------------------------------------------------------- */
466
467/*
468 * PUBLIC: int xtc_tls_set_hostname __P((xtc_tls_t *, const char *));
469 */
470XTC_API int xtc_tls_set_hostname(xtc_tls_t *tls, const char *name);
471
472/* -------------------------------------------------------------------------
473 * Kernel TLS (zero-copy TLS): let the kernel do the record crypto.
474 *
475 * By default every TLS byte is encrypted / decrypted in user space and
476 * copied between the application buffer, the TLS library's record
477 * buffer and the socket. With kernel TLS (Linux tls.ko, FreeBSD KTLS)
478 * the library hands the session keys to the socket after the handshake,
479 * xtc_tls_write / xtc_tls_read then pass plaintext straight to and from
480 * the kernel, and xtc_tls_sendfile sends a file region encrypted without
481 * it ever entering user space.
482 *
483 * xtc_tls_enable_ktls opts ONE fd-mode connection in. Call it after
484 * xtc_tls_create and before the first xtc_tls_handshake. It returns
485 * XTC_OK when the request is armed -- whether the kernel actually takes
486 * over is decided at the end of the handshake (kernel support, module
487 * loaded, negotiated cipher: AES-GCM / ChaCha20-Poly1305 on Linux) and
488 * reported by xtc_tls_ktls_active; a connection the kernel declines
489 * stays an ordinary, fully working user-space TLS connection.
490 * XTC_E_NOSYS: this backend or library build has no kTLS (only the
491 * OpenSSL backend implements it), or the connection uses a custom
492 * transport; XTC_E_INVAL: tls is NULL or the handshake has started.
493 * The connection keeps the no-SIGPIPE guarantee of fd mode (SO_NOSIGPIPE
494 * where the OS has it, else SIGPIPE is held off for the duration of each
495 * TLS call on the calling thread), provided the socket is closed with
496 * xtc_net_close: on Linux, close(2) of a kTLS socket whose peer has gone
497 * can raise SIGPIPE while the kernel flushes a queued record, and
498 * xtc_net_close holds it off; a raw close(2) does not. A write the
499 * kernel accepted but could not deliver because the peer has gone is
500 * reported as XTC_E_IO (the kernel itself returns the byte count).
501 *
502 * xtc_tls_ktls_active returns XTC_TLS_KTLS_TX and/or XTC_TLS_KTLS_RX for
503 * the directions the kernel handles (0 = none, or tls NULL). Meaningful
504 * after the handshake.
505 *
506 * xtc_tls_sendfile sends up to len bytes of file fd starting at off over
507 * the connection, encrypted by the kernel, the file pages never copied
508 * to user space. Returns XTC_OK with *out_n = bytes sent (may be < len,
509 * like xtc_tls_write), XTC_E_AGAIN (wants_write set) when the socket is
510 * full, XTC_E_NOSYS when kernel TX is not active (fall back to reading
511 * the file and xtc_tls_write), XTC_E_IO / XTC_E_INTERNAL like
512 * xtc_tls_write. The socket is non-blocking in fd mode, so a large len
513 * returns short; loop on it.
514 *
515 * PUBLIC: int xtc_tls_enable_ktls __P((xtc_tls_t *));
516 * PUBLIC: int xtc_tls_ktls_active __P((const xtc_tls_t *));
517 * PUBLIC: int xtc_tls_sendfile __P((xtc_tls_t *, int, int64_t, size_t, size_t *));
518 * ----------------------------------------------------------------------- */
519#define XTC_TLS_KTLS_TX 1
520#define XTC_TLS_KTLS_RX 2
521
522XTC_API int xtc_tls_enable_ktls(xtc_tls_t *tls);
523XTC_API int xtc_tls_ktls_active(const xtc_tls_t *tls);
524XTC_API int xtc_tls_sendfile(xtc_tls_t *tls, int fd, int64_t off,
525 size_t len, size_t *out_n);
526
527/*
528 * xtc_tls_destroy --
529 * Release per-connection TLS state. Does not close the underlying fd,
530 * does not send close_notify -- call xtc_tls_shutdown first if a clean
531 * shutdown is needed.
532 * tls may be NULL (no-op).
533 */
534XTC_API void xtc_tls_destroy(xtc_tls_t *tls);
535
536/* -------------------------------------------------------------------------
537 * Handshake.
538 * ----------------------------------------------------------------------- */
539
540/*
541 * PUBLIC: int xtc_tls_handshake __P((xtc_tls_t *));
542 * PUBLIC: int xtc_tls_wants_read __P((const xtc_tls_t *));
543 * PUBLIC: int xtc_tls_wants_write __P((const xtc_tls_t *));
544 */
545
546/*
547 * xtc_tls_handshake --
548 * Drive the TLS handshake state machine one step.
549 *
550 * Returns:
551 * XTC_OK handshake complete; the connection is ready for I/O
552 * XTC_E_AGAIN the fd is not yet ready; poll on
553 * xtc_tls_wants_read ? XTC_IO_READABLE
554 * : XTC_IO_WRITABLE
555 * and call again when the event fires
556 * XTC_E_INVAL tls is NULL
557 * XTC_E_NOSYS TLS not compiled in
558 * XTC_E_IO the peer or transport failed (EOF without close_notify,
559 * reset, send/recv error); tear the connection down
560 * (other) backend-specific hard error; connection must be torn down
561 *
562 * There is no built-in handshake deadline: pass the time left before
563 * your own deadline as the xtc_proc_wait_fd timeout (xtc_tls(3)).
564 *
565 * Errors are per connection. Each backend clears its per-thread error
566 * state before every handshake / read / write / shutdown call and after
567 * a failure, so one bad peer cannot fail a later call on another
568 * connection that shares the thread.
569 */
570XTC_API int xtc_tls_handshake(xtc_tls_t *tls);
571
572/* -------------------------------------------------------------------------
573 * Encrypted I/O.
574 * ----------------------------------------------------------------------- */
575
576/*
577 * PUBLIC: int xtc_tls_read __P((xtc_tls_t *, void *, size_t, size_t *));
578 * PUBLIC: int xtc_tls_write __P((xtc_tls_t *, const void *, size_t, size_t *));
579 */
580
581/*
582 * xtc_tls_read --
583 * Read up to buflen decrypted bytes into buf.
584 *
585 * On XTC_OK, *out_n holds the number of bytes read (may be < buflen);
586 * *out_n == 0 is a clean EOF (the peer sent close_notify).
587 * On XTC_E_AGAIN the fd was not readable; *out_n is 0.
588 * On XTC_E_IO the peer closed without close_notify (truncation), reset
589 * the connection, or the transport failed.
590 * On XTC_E_INVAL tls, buf, or out_n is NULL.
591 * On XTC_E_NOSYS TLS was not compiled in.
592 * Any other negative code is a hard TLS error; tear the connection down.
593 */
594XTC_API int xtc_tls_read(xtc_tls_t *tls, void *buf, size_t buflen, size_t *out_n);
595
596/*
597 * xtc_tls_write --
598 * Encrypt and write up to buflen bytes from buf.
599 *
600 * On XTC_OK, *out_n holds the number of bytes consumed (may be < buflen).
601 * On XTC_E_AGAIN the fd was not writable; *out_n is 0.
602 * On XTC_E_IO the peer or transport failed (reset, closed, send error).
603 * On XTC_E_INVAL tls, buf, or out_n is NULL.
604 * On XTC_E_NOSYS TLS was not compiled in.
605 */
606XTC_API int xtc_tls_write(xtc_tls_t *tls, const void *buf, size_t buflen,
607 size_t *out_n);
608
609/* -------------------------------------------------------------------------
610 * Readiness queries.
611 * ----------------------------------------------------------------------- */
612
613/*
614 * xtc_tls_wants_read --
615 * Return non-zero if the most recent TLS operation stalled waiting
616 * for the underlying fd to become readable. The caller should arm
617 * a POLLIN/XTC_IO_READABLE watch and retry.
618 */
619XTC_API int xtc_tls_wants_read(const xtc_tls_t *tls);
620
621/*
622 * xtc_tls_wants_write --
623 * Return non-zero if the most recent TLS operation stalled waiting
624 * for the underlying fd to become writable. The caller should arm
625 * a POLLOUT/XTC_IO_WRITABLE watch and retry.
626 */
627XTC_API int xtc_tls_wants_write(const xtc_tls_t *tls);
628
629/* -------------------------------------------------------------------------
630 * Graceful shutdown.
631 * ----------------------------------------------------------------------- */
632
633/*
634 * PUBLIC: int xtc_tls_shutdown __P((xtc_tls_t *));
635 */
636
637/*
638 * xtc_tls_shutdown --
639 * Initiate or continue a TLS close_notify shutdown.
640 *
641 * Returns:
642 * XTC_OK shutdown complete; the underlying fd may be closed
643 * XTC_E_AGAIN not yet done; poll for readiness as with the handshake
644 * and call again
645 * XTC_E_INVAL tls is NULL
646 * XTC_E_NOSYS TLS not compiled in
647 */
648XTC_API int xtc_tls_shutdown(xtc_tls_t *tls);
649
650/* -------------------------------------------------------------------------
651 * Post-handshake introspection.
652 *
653 * Valid only after xtc_tls_handshake has returned XTC_OK. These back a
654 * consumer's connection logging / statistics, certificate-based auth,
655 * and SCRAM channel binding. On an unconnected handle, a backend that
656 * does not implement the accessor, or --with-tls=none, the const char *
657 * getters return NULL, the int getters return 0 or XTC_E_NOSYS, and the
658 * buffer-filling getters return XTC_E_NOSYS.
659 * ----------------------------------------------------------------------- */
660
661/*
662 * PUBLIC: const char *xtc_tls_get_version __P((const xtc_tls_t *));
663 * PUBLIC: const char *xtc_tls_get_cipher __P((const xtc_tls_t *));
664 * PUBLIC: int xtc_tls_get_cipher_bits __P((const xtc_tls_t *));
665 * PUBLIC: int xtc_tls_get_alpn_selected __P((const xtc_tls_t *,
666 * PUBLIC: const unsigned char **, unsigned int *));
667 * PUBLIC: int xtc_tls_has_peer_cert __P((const xtc_tls_t *));
668 * PUBLIC: int xtc_tls_get_verify_error __P((const xtc_tls_t *, long *,
669 * PUBLIC: char *, size_t));
670 * PUBLIC: int xtc_tls_get_peer_subject_dn __P((const xtc_tls_t *, char *, size_t));
671 * PUBLIC: int xtc_tls_get_peer_common_name __P((const xtc_tls_t *, char *, size_t));
672 * PUBLIC: int xtc_tls_get_peer_issuer_dn __P((const xtc_tls_t *, char *, size_t));
673 * PUBLIC: int xtc_tls_get_peer_serial __P((const xtc_tls_t *, char *, size_t));
674 * PUBLIC: int xtc_tls_get_server_cert_hash __P((const xtc_tls_t *,
675 * PUBLIC: unsigned char *, size_t, size_t *));
676 */
677
678/* Negotiated protocol version string, e.g. "TLSv1.3". NULL if none. */
679XTC_API const char *xtc_tls_get_version(const xtc_tls_t *tls);
680
681/* Negotiated cipher suite name. NULL if none. */
682XTC_API const char *xtc_tls_get_cipher(const xtc_tls_t *tls);
683
684/* Symmetric key strength in bits of the negotiated cipher, or 0. */
685XTC_API int xtc_tls_get_cipher_bits(const xtc_tls_t *tls);
686
687/*
688 * ALPN protocol actually selected. On XTC_OK *out points to the
689 * selected protocol bytes (owned by the connection, valid until
690 * destroy) and *len is its length. XTC_E_NOTFOUND if none was
691 * negotiated; XTC_E_INVAL on a NULL argument; XTC_E_NOSYS if
692 * unsupported.
693 */
694XTC_API int xtc_tls_get_alpn_selected(const xtc_tls_t *tls,
695 const unsigned char **out, unsigned int *len);
696
697/* Non-zero if the peer presented a certificate that passed verification. */
698XTC_API int xtc_tls_has_peer_cert(const xtc_tls_t *tls);
699
700/*
701 * Detail of the most recent peer-certificate verification result, for
702 * diagnostics/log parity (e.g. PostgreSQL's verify_cb errdetail). On
703 * XTC_OK, *x509_err receives the backend verify-result code
704 * (OpenSSL X509_V_*; X509_V_OK == 0 means verification succeeded) and,
705 * if buf != NULL and len > 0, a human-readable reason string
706 * (OpenSSL X509_verify_cert_error_string()) is written NUL-terminated
707 * into buf (truncated to fit). x509_err may be NULL if only the text
708 * is wanted. XTC_E_INVAL on a NULL tls; XTC_E_NOSYS if the backend
709 * cannot report a verify result. Note the code is per-connection and
710 * only meaningful after the handshake.
711 */
712XTC_API int xtc_tls_get_verify_error(const xtc_tls_t *tls, long *x509_err,
713 char *buf, size_t len);
714
715/*
716 * Peer certificate subject / issuer distinguished name in RFC 2253
717 * form (e.g. "CN=x,O=y"), and the subject commonName, written
718 * NUL-terminated into buf. (Note the RFC 2253 comma form; this is not
719 * the legacy OpenSSL slash form "/CN=x/O=y" -- a consumer that needs
720 * the slash form must reformat.) A DN containing an embedded NUL is
721 * rejected with XTC_E_INVAL (guards the CVE-2009-4034 truncation
722 * class). XTC_E_NOTFOUND if there is no peer certificate; XTC_E_RANGE
723 * if buf is too small; XTC_E_NOSYS if unsupported.
724 */
725XTC_API int xtc_tls_get_peer_subject_dn(const xtc_tls_t *tls, char *buf, size_t len);
726XTC_API int xtc_tls_get_peer_common_name(const xtc_tls_t *tls, char *buf, size_t len);
727XTC_API int xtc_tls_get_peer_issuer_dn(const xtc_tls_t *tls, char *buf, size_t len);
728
729/* Peer certificate serial number as a decimal string. */
730XTC_API int xtc_tls_get_peer_serial(const xtc_tls_t *tls, char *buf, size_t len);
731
732/*
733 * Server-certificate hash for RFC 5929 tls-server-end-point channel
734 * binding (the input SCRAM-SHA-256-PLUS needs). Writes the hash into
735 * buf; *out_len receives its length. The digest follows RFC 5929: a
736 * certificate signed with MD5 or SHA-1 is hashed with SHA-256,
737 * otherwise the hash matching the certificate's signature algorithm is
738 * used. XTC_E_RANGE if buf is too small (SHA-512 needs 64 bytes),
739 * XTC_E_NOTFOUND if there is no certificate, XTC_E_NOSYS if
740 * unsupported.
741 */
742XTC_API int xtc_tls_get_server_cert_hash(const xtc_tls_t *tls,
743 unsigned char *buf, size_t buflen, size_t *out_len);
744
745#ifdef __cplusplus
746}
747#endif
748
749#endif /* XTC_TLS_H */