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