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