xref: /netbsd-src/external/mpl/bind/dist/lib/isc/include/isc/tls.h (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: tls.h,v 1.4 2025/01/26 16:25:43 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 #pragma once
17 
18 #include <isc/mem.h>
19 #include <isc/region.h>
20 #include <isc/result.h>
21 #include <isc/types.h>
22 
23 typedef struct ssl_ctx_st isc_tlsctx_t;
24 typedef struct ssl_st	  isc_tls_t;
25 
26 typedef struct x509_store_st isc_tls_cert_store_t;
27 
28 void
29 isc_tlsctx_free(isc_tlsctx_t **ctpx);
30 /*%<
31  * Free a TLS client or server context.
32  *
33  * Requires:
34  *\li	'ctxp' != NULL and '*ctxp' != NULL.
35  */
36 
37 void
38 isc_tlsctx_attach(isc_tlsctx_t *src, isc_tlsctx_t **ptarget);
39 /*%<
40  * Attach to the TLS context.
41  *
42  * Requires:
43  *\li	'src' != NULL;
44  *\li	'ptarget' != NULL;
45  *\li	'*ptarget' == NULL.
46  */
47 
48 isc_result_t
49 isc_tlsctx_createserver(const char *keyfile, const char *certfile,
50 			isc_tlsctx_t **ctxp);
51 /*%<
52  * Set up a TLS server context, using the key and certificate specified in
53  * 'keyfile' and 'certfile', or a self-generated ephemeral key and
54  * certificdate if both 'keyfile' and 'certfile' are NULL.
55  *
56  * Requires:
57  *\li	'ctxp' != NULL and '*ctxp' == NULL.
58  *\li	'keyfile' and 'certfile' are either both NULL or both non-NULL.
59  */
60 
61 isc_result_t
62 isc_tlsctx_createclient(isc_tlsctx_t **ctxp);
63 /*%<
64  * Set up a TLS client context.
65  *
66  * Requires:
67  *\li	'ctxp' != NULL and '*ctxp' == NULL.
68  */
69 
70 isc_result_t
71 isc_tlsctx_load_certificate(isc_tlsctx_t *ctx, const char *keyfile,
72 			    const char *certfile);
73 /*%<
74  * Load a TLS certificate into a TLS context.
75  *
76  * Requires:
77  *\li	'ctx' != NULL;
78  *\li	'keyfile' and 'certfile' are both non-NULL.
79  */
80 
81 typedef enum isc_tls_protocol_version {
82 	/* these must be the powers of two */
83 	ISC_TLS_PROTO_VER_1_2 = 1 << 0,
84 	ISC_TLS_PROTO_VER_1_3 = 1 << 1,
85 	ISC_TLS_PROTO_VER_UNDEFINED,
86 } isc_tls_protocol_version_t;
87 
88 void
89 isc_tlsctx_set_protocols(isc_tlsctx_t *ctx, const uint32_t tls_versions);
90 /*%<
91  * Sets the supported TLS protocol versions via the 'tls_versions' bit
92  * set argument (see `isc_tls_protocol_version_t` enum for the
93  * expected values).
94  *
95  * Requires:
96  *\li	'ctx' != NULL;
97  *\li	'tls_versions' != 0.
98  */
99 
100 bool
101 isc_tls_protocol_supported(const isc_tls_protocol_version_t tls_ver);
102 /*%<
103  * Check in runtime that the specified TLS protocol versions is supported.
104  */
105 
106 isc_tls_protocol_version_t
107 isc_tls_protocol_name_to_version(const char *name);
108 /*%<
109  * Convert the protocol version string into the version of
110  * 'isc_tls_protocol_version_t' type.
111  * Requires:
112  *\li	'name' != NULL.
113  */
114 
115 bool
116 isc_tlsctx_load_dhparams(isc_tlsctx_t *ctx, const char *dhparams_file);
117 /*%<
118  * Load Diffie-Hellman parameters file and apply it to the given TLS context
119  * 'ctx'.
120  *
121  * Requires:
122  * \li	'ctx' != NULL;
123  * \li	'dhaprams_file' a valid pointer to a non empty string.
124  */
125 
126 bool
127 isc_tls_cipherlist_valid(const char *cipherlist);
128 /*%<
129  * Check if cipher list string is valid.
130  *
131  * Requires:
132  * \li	'cipherlist' a valid pointer to a non empty string.
133  */
134 
135 void
136 isc_tlsctx_set_cipherlist(isc_tlsctx_t *ctx, const char *cipherlist);
137 /*%<
138  * Set cipher list string for on the given TLS context 'ctx'. This affects only
139  * TLSv1.2 (and older).
140  *
141  * Requires:
142  * \li	'ctx' != NULL;
143  * \li	'cipherlist' a valid pointer to a non empty string.
144  */
145 
146 bool
147 isc_tls_cipher_suites_valid(const char *cipher_suites);
148 /*%<
149  * Check if cipher suites string is valid.
150  *
151  * Requires:
152  * \li	'cipher_suites' a valid pointer to a non empty string.
153  */
154 
155 void
156 isc_tlsctx_set_cipher_suites(isc_tlsctx_t *ctx, const char *cipher_suites);
157 /*%<
158  * Set cipher suites string for on the given TLS context 'ctx'. This affects
159  * only TLSv1.3.
160  *
161  * Requires:
162  * \li	'ctx' != NULL;
163  * \li	'cipher_suites' a valid pointer to a non empty string.
164  */
165 
166 void
167 isc_tlsctx_prefer_server_ciphers(isc_tlsctx_t *ctx, const bool prefer);
168 /*%<
169  * Make the given TLS context 'ctx' to prefer or to not prefer
170  * server side ciphers during the ciphers negotiation.
171  *
172  * Requires:
173  * \li	'ctx' != NULL.
174  */
175 
176 void
177 isc_tlsctx_session_tickets(isc_tlsctx_t *ctx, const bool use);
178 /*%<
179  * Enable/Disable stateless session resumptions tickets on the given
180  * TLS context 'ctx' (see RFC5077).
181  *
182  * Requires:
183  * \li	'ctx' != NULL.
184  */
185 
186 isc_tls_t *
187 isc_tls_create(isc_tlsctx_t *ctx);
188 /*%<
189  * Set up the structure to hold data for a new TLS connection.
190  *
191  * Requires:
192  *\li	'ctx' != NULL.
193  */
194 
195 void
196 isc_tls_free(isc_tls_t **tlsp);
197 /*%<
198  * Free a TLS structure.
199  *
200  * Requires:
201  *\li	'tlsp' != NULL and '*tlsp' != NULL.
202  */
203 
204 const char *
205 isc_tls_verify_peer_result_string(isc_tls_t *tls);
206 /*%<
207  * Return a user readable description of a remote peer's certificate
208  * validation.
209  *
210  * Requires:
211  *\li	'tls' != NULL.
212  */
213 
214 #if HAVE_LIBNGHTTP2
215 void
216 isc_tlsctx_enable_http2client_alpn(isc_tlsctx_t *ctx);
217 void
218 isc_tlsctx_enable_http2server_alpn(isc_tlsctx_t *ctx);
219 /*%<
220  * Enable HTTP/2 Application Layer Protocol Negotation for 'ctx'.
221  *
222  * Requires:
223  *\li	'ctx' is not NULL.
224  */
225 #endif /* HAVE_LIBNGHTTP2 */
226 
227 void
228 isc_tls_get_selected_alpn(isc_tls_t *tls, const unsigned char **alpn,
229 			  unsigned int *alpnlen);
230 
231 #define ISC_TLS_DOT_PROTO_ALPN_ID     "dot"
232 #define ISC_TLS_DOT_PROTO_ALPN_ID_LEN 3
233 
234 void
235 isc_tlsctx_enable_dot_client_alpn(isc_tlsctx_t *ctx);
236 void
237 isc_tlsctx_enable_dot_server_alpn(isc_tlsctx_t *ctx);
238 /*%<
239  * Enable DoT Application Layer Protocol Negotation for 'ctx'.
240  *
241  * Requires:
242  *\li	'ctx' is not NULL.
243  */
244 
245 isc_result_t
246 isc_tlsctx_enable_peer_verification(isc_tlsctx_t *ctx, const bool is_server,
247 				    isc_tls_cert_store_t *store,
248 				    const char		 *hostname,
249 				    bool hostname_ignore_subject);
250 /*%<
251  * Enable peer certificate and, optionally, hostname (for client contexts)
252  * verification.
253  *
254  * Requires:
255  *\li	'ctx' is not NULL;
256  *\li	'store' is not NULL.
257  */
258 
259 isc_result_t
260 isc_tlsctx_load_client_ca_names(isc_tlsctx_t *ctx, const char *ca_bundle_file);
261 /*%<
262  * Load the list of CA-certificate names from a CA-bundle file to
263  * send by the server to a client when requesting a peer certificate.
264  * Usually used in conjunction with
265  * isc_tlsctx_enable_peer_validation().
266  *
267  * Requires:
268  *\li	'ctx' is not NULL;
269  *\li	'ca_bundle_file' is not NULL.
270  */
271 
272 isc_result_t
273 isc_tls_cert_store_create(const char		*ca_bundle_filename,
274 			  isc_tls_cert_store_t **pstore);
275 /*%<
276  * Create X509 certificate store. The 'ca_bundle_filename' might be
277  * 'NULL' or an empty string, which means use the default system wide
278  * bundle/directory.
279  *
280  * Requires:
281  *\li	'pstore' is a valid pointer to a pointer containing 'NULL'.
282  */
283 
284 void
285 isc_tls_cert_store_free(isc_tls_cert_store_t **pstore);
286 /*%<
287  * Free X509 certificate store.
288  *
289  * Requires:
290  *\li	'pstore' is a valid pointer to a pointer containing a non-'NULL' value.
291  */
292 
293 typedef struct isc_tlsctx_client_session_cache isc_tlsctx_client_session_cache_t;
294 /*%<
295  * TLS client session cache is an object which allows efficient
296  * storing and retrieval of previously saved TLS sessions so that they
297  * can be resumed. This object is supposed to be a foundation for
298  * implementing TLS session resumption - a standard technique to
299  * reduce the cost of re-establishing a connection to the remote
300  * server endpoint.
301  *
302  * OpenSSL does server-side TLS session caching transparently by
303  * default. However, on the client-side, a TLS session to resume must
304  * be manually specified when establishing the TLS connection. The TLS
305  * client session cache is precisely the foundation for that.
306  *
307  * The cache has been designed to have the following characteristics:
308  *
309  * - Fixed maximal number of entries to not keep too many obsolete
310  * sessions within the cache;
311  *
312  * - The cache is indexed by character string keys. Each string is a
313  * key representing a remote endpoint (unique remote endpoint name,
314  * e.g. combination of the remote IP address and port);
315  *
316  * - Least Recently Used (LRU) cache replacement policy while allowing
317  * easy removal of obsolete entries;
318  *
319  * - Ability to store multiple TLS sessions associated with the given
320  * key (remote endpoint name). This characteristic is important if
321  * multiple connections to the same remote server can be established;
322  *
323  * - Ability to efficiently retrieve the most recent TLS sessions
324  * associated with the key (remote endpoint name).
325  *
326  * Because of these characteristics, the cache will end up having the
327  * necessary amount of resumable TLS session parameters to the most
328  * used remote endpoints ("hot entries") after a short period of
329  * initial use ("warmup").
330  *
331  * Attempting to resume TLS sessions is an optimisation, which is not
332  * guaranteed to succeed because it requires the same session to be
333  * present in the server session caches. If it is not the case, the
334  * usual handshake procedure takes place. However, when session
335  * resumption is successful, it reduces the amount of the
336  * computational resources required as well as the amount of data to
337  * be transmitted when (re)establishing the connection. Also, it
338  * reduces round trip time (by reducing the number of packets to
339  * transmit).
340  *
341  * This optimisation is important in the context of DNS because the
342  * amount of data within the full handshake messages might be
343  * comparable to or surpass the size of a typical DNS message.
344  */
345 
346 void
347 isc_tlsctx_client_session_cache_create(
348 	isc_mem_t *mctx, isc_tlsctx_t *ctx, const size_t max_entries,
349 	isc_tlsctx_client_session_cache_t **cachep);
350 /*%<
351  * Create a new TLS client session cache object.
352  *
353  * Requires:
354  *\li	'mctx' is a valid memory context object;
355  *\li	'ctx' is a valid TLS context object;
356  *\li	'max_entries' is a positive number;
357  *\li	'cachep' is a valid pointer to a pointer which must be equal to NULL.
358  */
359 
360 void
361 isc_tlsctx_client_session_cache_attach(
362 	isc_tlsctx_client_session_cache_t  *source,
363 	isc_tlsctx_client_session_cache_t **targetp);
364 /*%<
365  * Create a reference to the TLS client session cache object.
366  *
367  * Requires:
368  *\li	'source' is a valid TLS client session cache object;
369  *\li	'targetp' is a valid pointer to a pointer which must equal NULL.
370  */
371 
372 void
373 isc_tlsctx_client_session_cache_detach(
374 	isc_tlsctx_client_session_cache_t **cachep);
375 /*%<
376  * Remove a reference to the TLS client session cache object.
377  *
378  * Requires:
379  *\li	'cachep' is a pointer to a pointer to a valid TLS client session cache
380  *object.
381  */
382 
383 void
384 isc_tlsctx_client_session_cache_keep(isc_tlsctx_client_session_cache_t *cache,
385 				     char *remote_peer_name, isc_tls_t *tls);
386 /*%<
387  * Add a resumable TLS client session within 'tls' to the TLS client
388  * session cache object 'cache' and associate it with
389  * 'remote_server_name' string. Also, the oldest entry from the cache
390  * might get removed if the cache is full.
391  *
392  * Requires:
393  *\li	'cache' is a pointer to a valid TLS client session cache object;
394  *\li	'remote_peer_name' is a pointer to a non empty character string;
395  *\li	'tls' is a valid, non-'NULL' pointer to a TLS connection state object.
396  */
397 
398 void
399 isc_tlsctx_client_session_cache_keep_sockaddr(
400 	isc_tlsctx_client_session_cache_t *cache, isc_sockaddr_t *remote_peer,
401 	isc_tls_t *tls);
402 /*%<
403  * The same as 'isc_tlsctx_client_session_cache_keep()', but uses a
404  * 'isc_sockaddr_t' as a key, instead of a character string.
405  *
406  * Requires:
407  *\li	'remote_peer' is a valid, non-'NULL', pointer to an 'isc_sockaddr_t'
408  *object.
409  */
410 
411 void
412 isc_tlsctx_client_session_cache_reuse(isc_tlsctx_client_session_cache_t *cache,
413 				      char *remote_server_name, isc_tls_t *tls);
414 /*%
415  * Try to restore a previously stored TLS session denoted by a remote
416  * server name as a key ('remote_server_name') into the given TLS
417  * connection state object ('tls'). The successfully restored session
418  * gets removed from the cache.
419  *
420  * Requires:
421  *\li	'cache' is a pointer to a valid TLS client session cache object;
422  *\li	'remote_peer_name' is a pointer to a non empty character string;
423  *\li	'tls' is a valid, non-'NULL' pointer to a TLS connection state object.
424  */
425 
426 void
427 isc_tlsctx_client_session_cache_reuse_sockaddr(
428 	isc_tlsctx_client_session_cache_t *cache, isc_sockaddr_t *remote_peer,
429 	isc_tls_t *tls);
430 /*%<
431  * The same as 'isc_tlsctx_client_session_cache_reuse()', but uses a
432  * 'isc_sockaddr_t' as a key, instead of a character string.
433  *
434  * Requires:
435  *\li	'remote_peer' is a valid, non-'NULL' pointer to an 'isc_sockaddr_t'
436  *object.
437  */
438 
439 const isc_tlsctx_t *
440 isc_tlsctx_client_session_cache_getctx(isc_tlsctx_client_session_cache_t *cache);
441 /*%<
442  * Returns a TLS context associated with the given TLS client
443  * session cache object. The function is intended to be used to
444  * implement the sanity checks ('INSIST()'s and 'REQUIRE()'s).
445  *
446  * Requires:
447  *\li	'cache' is a pointer to a valid TLS client session cache object.
448  */
449 
450 #define ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE (150)
451 /*%<
452  * The default maximum size of a TLS client session cache. The value
453  * should be large enough to hold enough sessions to successfully
454  * re-establish connections to the most remote TLS servers, but not
455  * too big to avoid keeping too much obsolete sessions.
456  */
457 
458 typedef struct isc_tlsctx_cache isc_tlsctx_cache_t;
459 /*%<
460  * The TLS context cache is an object which allows retrieving a
461  * previously created TLS context based on the following tuple:
462  *
463  * 1. The name of a TLS entry, as defined in the configuration file;
464  * 2. A transport type. Currently, only TLS (DoT) and HTTPS (DoH) are
465  *    supported;
466  * 3. An IP address family (AF_INET or AF_INET6).
467  *
468  * There are multiple uses for this object:
469  *
470  * First, it allows reuse of client-side contexts during zone transfers.
471  * That, in turn, allows use of session caches associated with these
472  * contexts, which enables TLS session resumption, making establishment
473  * of XoT connections faster and computationally cheaper.
474  *
475  * Second, it can be extended to be used as storage for TLS context related
476  * data, as defined in 'tls' statements in the configuration file (for
477  * example, CA-bundle intermediate certificate storage, client-side contexts
478  * with pre-loaded certificates in a case of Mutual TLS, etc). This will
479  * be used to implement Strict/Mutual TLS.
480  *
481  * Third, it avoids creating an excessive number of server-side TLS
482  * contexts, which might help to reduce the number of contexts
483  * created during server initialisation and reconfiguration.
484  */
485 
486 typedef enum {
487 	isc_tlsctx_cache_none = 0,
488 	isc_tlsctx_cache_tls,
489 	isc_tlsctx_cache_https,
490 	isc_tlsctx_cache_count
491 } isc_tlsctx_cache_transport_t;
492 /*%< TLS context cache transport type values. */
493 
494 void
495 isc_tlsctx_cache_create(isc_mem_t *mctx, isc_tlsctx_cache_t **cachep);
496 /*%<
497  * Create a new TLS context cache object.
498  *
499  * Requires:
500  *\li	'mctx' is a valid memory context;
501  *\li	'cachep' is a valid pointer to a pointer which must be equal to NULL.
502  */
503 
504 void
505 isc_tlsctx_cache_attach(isc_tlsctx_cache_t  *source,
506 			isc_tlsctx_cache_t **targetp);
507 /*%<
508  * Create a reference to the TLS context cache object.
509  *
510  * Requires:
511  *\li	'source' is a valid TLS context cache object;
512  *\li	'targetp' is a valid pointer to a pointer which must equal NULL.
513  */
514 
515 void
516 isc_tlsctx_cache_detach(isc_tlsctx_cache_t **cachep);
517 /*%<
518  * Remove a reference to the TLS context cache object.
519  *
520  * Requires:
521  *\li	'cachep' is a pointer to a pointer to a valid TLS
522  *	 context cache object.
523  */
524 
525 isc_result_t
526 isc_tlsctx_cache_add(
527 	isc_tlsctx_cache_t *cache, const char *name,
528 	const isc_tlsctx_cache_transport_t transport, const uint16_t family,
529 	isc_tlsctx_t *ctx, isc_tls_cert_store_t *store,
530 	isc_tlsctx_client_session_cache_t *client_sess_cache,
531 	isc_tlsctx_t **pfound, isc_tls_cert_store_t **pfound_store,
532 	isc_tlsctx_client_session_cache_t **pfound_client_sess_cache);
533 /*%<
534  *
535  * Add a new TLS context and its associated data to the TLS context
536  * cache. 'pfound' is an optional pointer, which can be used to
537  * retrieve an already existing TLS context object in a case it
538  * exists.
539  *
540  * The passed certificates store object ('store') possession is
541  * transferred to the cache object in a case of success. In some cases
542  * it might be destroyed immediately upon the call completion.
543  *
544  * The possession of the passed TLS client session cache
545  * ('client_sess_cache') is also transferred to the cache object in a
546  * case of success.
547  *
548  * Requires:
549  *\li	'cache' is a valid pointer to a TLS context cache object;
550  *\li	'name' is a valid pointer to a non-empty string;
551  *\li	'transport' is a valid transport identifier (currently only
552  *       TLS/DoT and HTTPS/DoH are supported);
553  *\li	'family' - either 'AF_INET' or 'AF_INET6';
554  *\li   'ctx' - a valid pointer to a valid TLS context object;
555  *\li   'store' - a valid pointer to a valid TLS certificates store object or
556  *		'NULL';
557  *\li   'client_sess_cache' - a valid pointer to a valid TLS client sessions
558  *cache object or 'NULL.
559  *
560  * Returns:
561  *\li	#ISC_R_EXISTS - node of the same key already exists;
562  *\li	#ISC_R_SUCCESS - the new entry has been added successfully.
563  */
564 
565 isc_result_t
566 isc_tlsctx_cache_find(
567 	isc_tlsctx_cache_t *cache, const char *name,
568 	const isc_tlsctx_cache_transport_t transport, const uint16_t family,
569 	isc_tlsctx_t **pctx, isc_tls_cert_store_t **pstore,
570 	isc_tlsctx_client_session_cache_t **pfound_client_sess_cache);
571 /*%<
572  * Look up a TLS context and its associated data in the TLS context cache.
573  *
574  * Requires:
575  *\li	'cache' is a valid pointer to a TLS context cache object;
576  *\li	'name' is a valid pointer to a non empty string;
577  *\li	'transport' - a valid transport identifier (currently only
578  *       TLS/DoT and HTTPS/DoH are supported;
579  *\li	'family' - either 'AF_INET' or 'AF_INET6';
580  *\li   'pctx' - a valid pointer to a non-NULL pointer;
581  *\li   'pstore' - a valid pointer to a non-NULL pointer or 'NULL'.
582  *\li   'pfound_client_sess_cache' - a valid pointer to a non-NULL pointer or
583  *'NULL'.
584  *
585  * Returns:
586  *\li	#ISC_R_SUCCESS - the context has been found;
587  *\li	#ISC_R_NOTFOUND	- the context has not been found. In such a case,
588  *		'pstore' still might get initialised as there is one to many
589  *		relation between stores and contexts.
590  */
591 
592 void
593 isc_tlsctx_set_random_session_id_context(isc_tlsctx_t *ctx);
594 /*%<
595  * Set context within which session can be reused to a randomly
596  * generated value. This one is used for TLS session resumption using
597  * session IDs. See OpenSSL documentation for
598  * 'SSL_CTX_set_session_id_context()'.
599  *
600  * It might be worth noting that usually session ID contexts are kept
601  * static for an application and particular certificate
602  * combination. However, for the cases when exporting server side TLS
603  * session cache to/loading from external memory is not required, we
604  * might use random IDs just fine. See,
605  * e.g. 'ngx_ssl_session_id_context()' in NGINX for an example of how
606  * a session ID might be obtained.
607  *
608  * Requires:
609  *\li   'ctx' - a valid non-NULL pointer;
610  */
611 
612 void
613 isc__tls_initialize(void);
614 
615 void
616 isc__tls_shutdown(void);
617 
618 void
619 isc__tls_setdestroycheck(bool check);
620