TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/corosio
9 : //
10 :
11 : #ifndef BOOST_COROSIO_TLS_CONTEXT_HPP
12 : #define BOOST_COROSIO_TLS_CONTEXT_HPP
13 :
14 : #include <boost/corosio/detail/config.hpp>
15 :
16 : #include <cstddef>
17 : #include <functional>
18 : #include <span>
19 : #include <system_error>
20 : #include <memory>
21 : #include <string_view>
22 :
23 : namespace boost::corosio {
24 :
25 : //
26 : // Enumerations
27 : //
28 :
29 : /** TLS protocol version.
30 :
31 : Specifies the minimum or maximum TLS protocol version to use
32 : for connections. Only modern, secure versions are supported.
33 :
34 : @see tls_context::set_min_protocol_version
35 : @see tls_context::set_max_protocol_version
36 : */
37 : enum class tls_version
38 : {
39 : /// TLS 1.2 (RFC 5246).
40 : tls_1_2,
41 :
42 : /// TLS 1.3 (RFC 8446).
43 : tls_1_3
44 : };
45 :
46 : /** Certificate and key file format.
47 :
48 : Specifies the encoding format for certificate and key data.
49 :
50 : @see tls_context::use_certificate
51 : @see tls_context::use_private_key
52 : */
53 : enum class tls_file_format
54 : {
55 : /// PEM format (Base64-encoded with header/footer lines).
56 : pem,
57 :
58 : /// DER format (raw ASN.1 binary encoding).
59 : der
60 : };
61 :
62 : /** Peer certificate verification mode.
63 :
64 : Controls how the TLS implementation verifies the peer's
65 : certificate during the handshake.
66 :
67 : @see tls_context::set_verify_mode
68 : */
69 : enum class tls_verify_mode
70 : {
71 : /// Do not request or verify the peer certificate.
72 : none,
73 :
74 : /// Request and verify the peer certificate if presented.
75 : peer,
76 :
77 : /// Require and verify the peer certificate (fail if not presented).
78 : require_peer
79 : };
80 :
81 : /** Certificate revocation checking policy.
82 :
83 : Controls how certificate revocation status is checked during
84 : verification.
85 :
86 : @see tls_context::set_revocation_policy
87 : */
88 : enum class tls_revocation_policy
89 : {
90 : /// Do not check revocation status.
91 : disabled,
92 :
93 : /// Check revocation but allow connection if status is unknown.
94 : soft_fail,
95 :
96 : /// Require successful revocation check (fail if status is unknown).
97 : hard_fail
98 : };
99 :
100 : /** Purpose for password callback invocation.
101 :
102 : Indicates whether the password is needed for reading (decrypting)
103 : or writing (encrypting) key material.
104 :
105 : @see tls_context::set_password_callback
106 : */
107 : enum class tls_password_purpose
108 : {
109 : /// Password needed to decrypt/read protected key material.
110 : for_reading,
111 :
112 : /// Password needed to encrypt/write protected key material.
113 : for_writing
114 : };
115 :
116 : class tls_context;
117 :
118 : /** Exposes the certificate and error state to a verification callback.
119 :
120 : An instance is passed to the callback installed via
121 : tls_context::set_verify_callback during the TLS handshake. It
122 : exposes the backend's native verification handle so the callback
123 : can inspect the certificate and chain currently being verified.
124 :
125 : The value returned by native_handle() is, for the OpenSSL and
126 : WolfSSL backends, an `X509_STORE_CTX*`. For portable inspection that
127 : works across backends (for example certificate pinning), prefer
128 : certificate(), which returns the DER encoding of the certificate
129 : currently being verified.
130 :
131 : @par Lifetime
132 :
133 : The wrapped handle and the certificate() bytes are owned by the TLS
134 : backend and are valid only for the duration of a single callback
135 : invocation. Do not retain them beyond the call.
136 :
137 : @see tls_context::set_verify_callback
138 : */
139 : class verify_context
140 : {
141 : void* handle_;
142 : unsigned char const* der_;
143 : std::size_t der_len_;
144 :
145 : public:
146 : /** Construct from a native handle and the current certificate.
147 :
148 : @param handle The backend verification handle (for OpenSSL and
149 : WolfSSL, an `X509_STORE_CTX*`).
150 : @param der Pointer to the DER encoding of the certificate under
151 : verification, or `nullptr` if unavailable.
152 : @param der_len Length of the DER encoding in bytes.
153 : */
154 : verify_context(
155 : void* handle, unsigned char const* der, std::size_t der_len) noexcept
156 : : handle_(handle)
157 : , der_(der)
158 : , der_len_(der_len)
159 : {
160 : }
161 :
162 : /** Return the native verification handle.
163 :
164 : Cast the result to the backend's verification context type
165 : (e.g. `X509_STORE_CTX*`) to inspect the certificate chain using
166 : backend-specific APIs.
167 :
168 : @return The native handle, or `nullptr` if none is available.
169 : */
170 : void* native_handle() const noexcept
171 : {
172 : return handle_;
173 : }
174 :
175 : /** Return the DER encoding of the certificate being verified.
176 :
177 : This is the portable way to inspect the peer certificate from a
178 : verification callback. It works identically on every backend,
179 : without depending on backend-specific build options. A DER
180 : certificate is an ASN.1 `SEQUENCE`, so the first byte is `0x30`.
181 :
182 : @return A view of the certificate's DER bytes, valid only for the
183 : duration of the callback. Empty if the certificate is not
184 : available.
185 : */
186 MIS 0 : std::span<unsigned char const> certificate() const noexcept
187 : {
188 0 : return {der_, der_len_};
189 : }
190 : };
191 :
192 : namespace detail {
193 : struct tls_context_data;
194 : tls_context_data const& get_tls_context_data(tls_context const&) noexcept;
195 : } // namespace detail
196 :
197 : #ifdef _MSC_VER
198 : #pragma warning(push)
199 : #pragma warning(disable : 4251) // shared_ptr needs dll-interface
200 : #endif
201 :
202 : /** Configures the certificates, keys, and protocol settings a TLS stream uses.
203 :
204 : The `tls_context` class provides a backend-agnostic interface for
205 : configuring TLS connections. It stores credentials (certificates and
206 : private keys), trust anchors, protocol settings, and verification
207 : options that are used when establishing TLS connections.
208 :
209 : This class is a shared handle to an opaque implementation. Copies
210 : share the same underlying state. This allows contexts to be passed
211 : by value and shared across multiple TLS streams.
212 :
213 : This class abstracts the configuration phase of TLS across the
214 : OpenSSL and WolfSSL backends. Portable code therefore works
215 : regardless of which TLS library is linked.
216 :
217 : @par Modification After Stream Creation
218 :
219 : Modifying a context after creating a TLS stream from it
220 : results in undefined behavior. Most settings are captured at the
221 : first handshake of any stream using it; others, such as callbacks,
222 : are read later. A modification may therefore apply partly or not at
223 : all.
224 :
225 : If different configurations are needed, create separate context
226 : objects.
227 :
228 : @par Thread Safety
229 :
230 : Distinct objects: Safe.
231 :
232 : Shared objects: Unsafe. A context must not be modified while
233 : any thread is creating streams from it.
234 :
235 : @par Example
236 : @par !example tls_context
237 :
238 : @see tls_role
239 : */
240 : class BOOST_COROSIO_DECL tls_context
241 : {
242 : struct implementation;
243 : std::shared_ptr<implementation> impl_;
244 :
245 : friend detail::tls_context_data const&
246 : detail::get_tls_context_data(tls_context const&) noexcept;
247 :
248 : public:
249 : /** Construct a default TLS context.
250 :
251 : Creates a context with default settings suitable for TLS 1.2
252 : and TLS 1.3 connections. No certificates or trust anchors are
253 : loaded; call the appropriate methods to configure credentials
254 : and verification.
255 :
256 : @par Example
257 : @par !example tls_context
258 : */
259 : tls_context();
260 :
261 : /** Creates a new handle that shares ownership of the underlying
262 : TLS context state with `other`.
263 :
264 : @param other The context to copy from.
265 : */
266 HIT 2 : tls_context(tls_context const& other) = default;
267 :
268 : /** Releases the current context's shared ownership and acquires
269 : shared ownership of `other`'s underlying state.
270 :
271 : @param other The context to copy from.
272 :
273 : @return Reference to this context.
274 : */
275 1 : tls_context& operator=(tls_context const& other) = default;
276 :
277 : /** Transfers ownership of the TLS context from another instance.
278 : After the move, `other` is in a valid but empty state.
279 :
280 : @param other The context to move from.
281 : */
282 2 : tls_context(tls_context&& other) noexcept = default;
283 :
284 : /** Releases the current context's shared ownership and transfers
285 : ownership from another instance. After the move, `other` is
286 : in a valid but empty state.
287 :
288 : @param other The context to move from.
289 :
290 : @return Reference to this context.
291 : */
292 1 : tls_context& operator=(tls_context&& other) noexcept = default;
293 :
294 : /** Releases this handle's shared ownership of the underlying
295 : context. The context state is destroyed when the last handle
296 : is released.
297 : */
298 56 : ~tls_context() = default;
299 :
300 : //
301 : // Credential Loading
302 : //
303 :
304 : /** Load the entity certificate from a memory buffer.
305 :
306 : Sets the certificate that identifies this endpoint to the peer.
307 : For servers, this is the server certificate. For clients using
308 : mutual TLS, this is the client certificate.
309 :
310 : The certificate must match the private key loaded via
311 : `use_private_key()` or `use_private_key_file()`.
312 :
313 : @param certificate The certificate data.
314 :
315 : @param format The encoding format of the certificate data.
316 :
317 : @return Success. The certificate is recorded and decoded when the
318 : native context is first built; a malformed certificate surfaces
319 : as a handshake failure.
320 :
321 : @see use_certificate_file
322 : @see use_private_key
323 : */
324 : [[nodiscard]] std::error_code
325 : use_certificate(std::string_view certificate, tls_file_format format);
326 :
327 : /** Load the entity certificate from a file.
328 :
329 : Sets the certificate that identifies this endpoint to the peer.
330 : For servers, this is the server certificate. For clients using
331 : mutual TLS, this is the client certificate.
332 :
333 : @param filename Path to the certificate file.
334 :
335 : @param format The encoding format of the file.
336 :
337 : @return Success, or an error if the file could not be read. The
338 : certificate is decoded when the native context is first built;
339 : a malformed certificate surfaces as a handshake failure.
340 :
341 : @par Example
342 : @par !example use_certificate_file
343 :
344 : @see use_certificate
345 : @see use_private_key_file
346 : */
347 : [[nodiscard]] std::error_code
348 : use_certificate_file(std::string_view filename, tls_file_format format);
349 :
350 : /** Load a certificate chain from a memory buffer.
351 :
352 : Loads the entity certificate followed by intermediate CA certificates.
353 : The chain should be ordered from leaf to root (excluding the root).
354 : This is the typical format for PEM certificate bundles.
355 :
356 : @param chain The certificate chain data in PEM format (concatenated
357 : certificates).
358 :
359 : @return Success. The chain is recorded and decoded when the native
360 : context is first built; a malformed chain surfaces as a
361 : handshake failure.
362 :
363 : @see use_certificate_chain_file
364 : */
365 : [[nodiscard]] std::error_code use_certificate_chain(std::string_view chain);
366 :
367 : /** Load a certificate chain from a file.
368 :
369 : Loads the entity certificate followed by intermediate CA certificates
370 : from a PEM file. The file should contain concatenated PEM certificates
371 : ordered from leaf to root (excluding the root).
372 :
373 : @param filename Path to the certificate chain file.
374 :
375 : @return Success, or an error if the file could not be read. The
376 : chain is decoded when the native context is first built; a
377 : malformed chain surfaces as a handshake failure.
378 :
379 : @par Example
380 : @par !example use_certificate_chain_file
381 :
382 : @see use_certificate_chain
383 : */
384 : [[nodiscard]] std::error_code
385 : use_certificate_chain_file(std::string_view filename);
386 :
387 : /** Load the private key from a memory buffer.
388 :
389 : Sets the private key corresponding to the entity certificate.
390 : The key must match the certificate loaded via `use_certificate()`
391 : or `use_certificate_chain()`.
392 :
393 : If the key is encrypted, set a password callback via
394 : `set_password_callback()` before calling this function.
395 :
396 : @param private_key The private key data.
397 :
398 : @param format The encoding format of the key data.
399 :
400 : @return Success. The key is recorded and decoded when the native
401 : context is first built. Three faults surface only as a handshake
402 : failure: a malformed key, a missing password callback for an
403 : encrypted key, and a certificate mismatch.
404 :
405 : @see use_private_key_file
406 : @see set_password_callback
407 : */
408 : [[nodiscard]] std::error_code
409 : use_private_key(std::string_view private_key, tls_file_format format);
410 :
411 : /** Load the private key from a file.
412 :
413 : Sets the private key corresponding to the entity certificate.
414 : The key must match the certificate loaded via `use_certificate_file()`
415 : or `use_certificate_chain_file()`.
416 :
417 : If the key file is encrypted, set a password callback via
418 : `set_password_callback()` before calling this function.
419 :
420 : @param filename Path to the private key file.
421 :
422 : @param format The encoding format of the file.
423 :
424 : @return Success, or an error if the file could not be read. The
425 : key is decoded when the native context is first built; a
426 : malformed key or a certificate mismatch surfaces as a
427 : handshake failure.
428 :
429 : @par Example
430 : @par !example use_private_key_file
431 :
432 : @see use_private_key
433 : @see set_password_callback
434 : */
435 : [[nodiscard]] std::error_code
436 : use_private_key_file(std::string_view filename, tls_file_format format);
437 :
438 : /** Load credentials from a PKCS#12 bundle in memory.
439 :
440 : PKCS#12 (also known as PFX) is a binary format that bundles a
441 : certificate, private key, and optionally intermediate certificates
442 : into a single password-protected file.
443 :
444 : @param data The PKCS#12 bundle data.
445 :
446 : @param passphrase The password protecting the bundle.
447 :
448 : @return Success. The bundle is recorded and decoded into the
449 : certificate, private key, and chain when the native context is
450 : first built. A malformed bundle or a wrong passphrase surfaces as a
451 : handshake failure.
452 :
453 : @note Intermediate certificates inside the bundle are loaded and
454 : sent during the handshake on both backends.
455 :
456 : @see use_pkcs12_file
457 : */
458 : [[nodiscard]] std::error_code
459 : use_pkcs12(std::string_view data, std::string_view passphrase);
460 :
461 : /** Load credentials from a PKCS#12 file.
462 :
463 : PKCS#12 (also known as PFX) is a binary format that bundles a
464 : certificate, private key, and optionally intermediate certificates
465 : into a single password-protected file. This is common on Windows
466 : and for certificates exported from browsers.
467 :
468 : @param filename Path to the PKCS#12 file.
469 :
470 : @param passphrase The password protecting the file.
471 :
472 : @return Success, or an error if the file could not be read. The
473 : bundle is decoded when the native context is first built; a
474 : malformed bundle or wrong passphrase surfaces as a handshake
475 : failure.
476 :
477 : @note Intermediate certificates inside the bundle are loaded and
478 : sent during the handshake on both backends.
479 :
480 : @par Example
481 : @par !example use_pkcs12_file
482 :
483 : @see use_pkcs12
484 : */
485 : [[nodiscard]] std::error_code
486 : use_pkcs12_file(std::string_view filename, std::string_view passphrase);
487 :
488 : //
489 : // Trust Anchors
490 : //
491 :
492 : /** Add a certificate authority for peer verification.
493 :
494 : Adds one or more CA certificates to the trust store used for
495 : verifying peer certificates. The data may contain multiple
496 : concatenated PEM certificates.
497 :
498 : @param ca The CA certificate data in PEM format.
499 :
500 : @return Success. The certificates are recorded and decoded when
501 : the native context is first built. Whether a malformed
502 : certificate fails the handshake depends on the backend. On
503 : OpenSSL, any one does. WolfSSL skips certificates it cannot
504 : use and fails only when none load.
505 :
506 : @see load_verify_file
507 : @see set_default_verify_paths
508 : */
509 : [[nodiscard]] std::error_code
510 : add_certificate_authority(std::string_view ca);
511 :
512 : /** Load CA certificates from a file.
513 :
514 : Loads one or more CA certificates from a PEM file. The file may
515 : contain multiple concatenated PEM certificates.
516 :
517 : @param filename Path to a PEM file containing CA certificates.
518 :
519 : @return Success, or an error if the file could not be read. The
520 : certificates are decoded when the native context is first
521 : built. Malformed certificates are handled as described for
522 : `add_certificate_authority()`.
523 :
524 : @par Example
525 : @par !example load_verify_file
526 :
527 : @see add_certificate_authority
528 : @see add_verify_path
529 : */
530 : [[nodiscard]] std::error_code load_verify_file(std::string_view filename);
531 :
532 : /** Add a directory of CA certificates for verification.
533 :
534 : Adds a directory of CA certificates to the trust store. The
535 : directory is applied when the native context is first built from
536 : this context.
537 :
538 : The expected directory layout depends on the backend. OpenSSL
539 : performs on-demand lookups. Each certificate file must be named
540 : by its subject-name hash, as generated by `openssl rehash` or
541 : `c_rehash`. WolfSSL loads every certificate file in the
542 : directory.
543 :
544 : @param path Path to the directory of CA certificates.
545 :
546 : @return Success. The path is recorded and applied when the native
547 : context is built. A directory that cannot be read at that time is
548 : skipped rather than reported here.
549 :
550 : @par Example
551 : @par !example add_verify_path
552 :
553 : @see load_verify_file
554 : @see set_default_verify_paths
555 : */
556 : [[nodiscard]] std::error_code add_verify_path(std::string_view path);
557 :
558 : /** Use the system default CA certificate store.
559 :
560 : Configures the context to use the backend's default trust store
561 : for peer certificate verification. This is the
562 : recommended approach for HTTPS clients connecting to public
563 : servers.
564 :
565 : The system store is loaded when the native context is first built
566 : from this context. For a verified-safe client, combine this with
567 : `set_verify_mode( tls_verify_mode::peer )` and, when connecting by
568 : name, `tls_stream::set_hostname()`.
569 :
570 : @return Success. The request is recorded and applied when the
571 : native context is built. A system store that cannot be loaded at
572 : that time is skipped rather than reported here. A context that
573 : must reject unverified peers should therefore also use
574 : `set_verify_mode( tls_verify_mode::peer )`.
575 :
576 : @note OpenSSL reads the CA file and directory it was built with,
577 : or those named by `SSL_CERT_FILE` and `SSL_CERT_DIR`. It does
578 : not read the macOS Keychain or the Windows Certificate Store.
579 : WolfSSL reads the platform store and requires a build with
580 : `WOLFSSL_SYS_CA_CERTS`; without it this call has no effect.
581 :
582 : @par Example
583 : @par !example set_default_verify_paths
584 :
585 : @see load_verify_file
586 : @see add_verify_path
587 : @see set_verify_mode
588 : */
589 : [[nodiscard]] std::error_code set_default_verify_paths();
590 :
591 : //
592 : // Protocol Configuration
593 : //
594 :
595 : /** Set the minimum TLS protocol version.
596 :
597 : Connections reject protocol versions older than this.
598 : The default allows TLS 1.2 and newer.
599 :
600 : @param v The minimum protocol version to accept.
601 :
602 : @return Success. The version is recorded and applied when the
603 : native context is first built.
604 :
605 : @par Example
606 : @par !example set_min_protocol_version
607 :
608 : @see set_max_protocol_version
609 : */
610 : [[nodiscard]] std::error_code set_min_protocol_version(tls_version v);
611 :
612 : /** Set the maximum TLS protocol version.
613 :
614 : Connections do not negotiate protocol versions newer than this.
615 : The default allows the newest supported version.
616 :
617 : @param v The maximum protocol version to accept.
618 :
619 : @return Success. The version is recorded and applied when the
620 : native context is first built.
621 :
622 : @note On WolfSSL the ceiling is applied by selecting a
623 : version-specific method, because no native set-max API exists. An
624 : invalid window, where the minimum exceeds the maximum, yields a
625 : context that fails the handshake.
626 :
627 : @see set_min_protocol_version
628 : */
629 : [[nodiscard]] std::error_code set_max_protocol_version(tls_version v);
630 :
631 : /** Set the allowed cipher suites.
632 :
633 : Configures which cipher suites may be used for connections.
634 : The format is backend-specific but typically follows OpenSSL
635 : cipher list syntax.
636 :
637 : @param ciphers The cipher suite specification string.
638 :
639 : @return Success. The string is recorded and applied when the
640 : native context is first built; an invalid cipher string
641 : surfaces as a handshake failure.
642 :
643 : @par Example
644 : @par !example set_ciphersuites
645 :
646 : @note This configures cipher suites for TLS 1.2 and below. For
647 : TLS 1.3, use @ref set_ciphersuites_tls13.
648 : */
649 : [[nodiscard]] std::error_code set_ciphersuites(std::string_view ciphers);
650 :
651 : /** Set the allowed TLS 1.3 cipher suites.
652 :
653 : TLS 1.3 uses a distinct, fixed set of cipher suites configured
654 : separately from earlier versions. The format is a colon-separated
655 : list of TLS 1.3 suite names.
656 :
657 : @param ciphers The TLS 1.3 cipher suite list.
658 :
659 : @return Success. The string is recorded and applied when the
660 : native context is first built; an invalid cipher string
661 : surfaces as a handshake failure.
662 :
663 : @par Example
664 : @par !example set_ciphersuites_tls13
665 :
666 : @note On the WolfSSL backend, TLS 1.2 and TLS 1.3 suites share a
667 : single cipher list; this call and @ref set_ciphersuites are
668 : merged into one list.
669 :
670 : @see set_ciphersuites
671 : */
672 : [[nodiscard]] std::error_code
673 : set_ciphersuites_tls13(std::string_view ciphers);
674 :
675 : /** Set the ALPN protocol list.
676 :
677 : Configures Application-Layer Protocol Negotiation (ALPN) for
678 : the connection. ALPN is used to negotiate which application
679 : protocol to use over the TLS connection (e.g., "h2" for HTTP/2,
680 : "http/1.1" for HTTP/1.1).
681 :
682 : The protocols are tried in preference order (first = highest).
683 :
684 : @param protocols Ordered list of protocol identifiers.
685 :
686 : @return Success, or an error if ALPN configuration fails.
687 :
688 : @note Read the negotiated protocol after the handshake via
689 : @ref tls_stream::alpn_protocol. On WolfSSL, ALPN requires a
690 : build with `HAVE_ALPN`; without it, offering protocols fails
691 : the handshake with `std::errc::function_not_supported` rather
692 : than negotiate nothing silently.
693 :
694 : @par Example
695 : @par !example set_alpn
696 : */
697 : [[nodiscard]] std::error_code
698 : set_alpn(std::initializer_list<std::string_view> protocols);
699 :
700 : //
701 : // Certificate Verification
702 : //
703 :
704 : /** Set the peer certificate verification mode.
705 :
706 : Controls whether and how peer certificates are verified during
707 : the TLS handshake.
708 :
709 : @param mode The verification mode to use.
710 :
711 : @return Success. The mode is recorded and applied when the native
712 : context is first built.
713 :
714 : @par Example
715 : @par !example set_verify_mode
716 :
717 : @see tls_verify_mode
718 : */
719 : [[nodiscard]] std::error_code set_verify_mode(tls_verify_mode mode);
720 :
721 : /** Set the maximum certificate chain verification depth.
722 :
723 : Limits how many intermediate certificates can appear between
724 : the peer certificate and a trusted root. The default is
725 : typically 100, which is sufficient for most certificate chains.
726 :
727 : @param depth Maximum number of intermediate certificates allowed.
728 :
729 : @return Success. The depth is recorded and applied when the native
730 : context is first built.
731 :
732 : @par Example
733 : @par !example set_verify_depth
734 : */
735 : [[nodiscard]] std::error_code set_verify_depth(int depth);
736 :
737 : /** Set a custom certificate verification callback.
738 :
739 : Installs a callback that is invoked during certificate chain
740 : verification. The callback can perform additional validation
741 : beyond the standard checks and can override verification
742 : results.
743 :
744 : The callback receives the built-in verification result so far and
745 : a `verify_context` describing the certificate being verified. Return
746 : `true` to accept the certificate, `false` to reject. Inspect the
747 : certificate portably via `verify_context::certificate()` (its DER
748 : encoding) — for example to pin a specific certificate.
749 :
750 : @par Backend Support
751 :
752 : The exact set of certificates the callback sees differs by backend:
753 :
754 : - OpenSSL: the callback runs once per certificate in the chain,
755 : including certificates that passed the built-in checks. It can
756 : therefore relax verification by returning `true` for a
757 : certificate the library rejected. It can also tighten
758 : verification by returning `false` for a certificate the library
759 : accepted, as pinning does.
760 : - WolfSSL built with `WOLFSSL_ALWAYS_VERIFY_CB` (implied by
761 : `--enable-opensslextra`): same as OpenSSL.
762 : - WolfSSL without that option: the library invokes the callback
763 : only on verification *failure*, so it cannot be honored on a
764 : successful handshake. Silently ignoring a verification-tightening
765 : callback would fail open. On such a build, a context that carries
766 : a callback instead **fails the handshake** with
767 : `std::errc::function_not_supported`. Rebuild
768 : WolfSSL with `WOLFSSL_ALWAYS_VERIFY_CB`, or omit the callback.
769 :
770 : @tparam Callback A callable with signature
771 : `bool( bool preverified, verify_context& ctx )`.
772 :
773 : @param callback The verification callback. Recorded here and
774 : applied during the handshake; on a WolfSSL build that
775 : cannot honor it, the handshake fails with
776 : `std::errc::function_not_supported` (see Backend Support).
777 :
778 : @par Example
779 : @par !example set_verify_callback
780 :
781 : @see verify_context
782 : @see set_verify_mode
783 : */
784 : template<typename Callback>
785 : void set_verify_callback(Callback callback);
786 :
787 : /** Set a callback for Server Name Indication (SNI).
788 :
789 : For server connections, this callback is invoked during the TLS
790 : handshake when a client sends an SNI extension. The callback
791 : receives the requested hostname and can accept or reject the
792 : connection.
793 :
794 : @tparam Callback A callable with signature
795 : `bool( std::string_view hostname )`.
796 :
797 : @param callback The SNI callback. Return `true` to accept the
798 : connection or `false` to reject it with an alert.
799 :
800 : @par Example
801 : @par !example set_servername_callback
802 :
803 : @note For virtual hosting with different certificates per hostname,
804 : create separate contexts and select the appropriate one before
805 : creating the TLS stream.
806 :
807 : @see tls_stream::set_hostname
808 : */
809 : template<typename Callback>
810 : void set_servername_callback(Callback callback);
811 :
812 : private:
813 : void set_servername_callback_impl(
814 : std::function<bool(std::string_view)> callback);
815 :
816 : void set_password_callback_impl(
817 : std::function<std::string(std::size_t, tls_password_purpose)> callback);
818 :
819 : void set_verify_callback_impl(
820 : std::function<bool(bool, verify_context&)> callback);
821 :
822 : public:
823 : //
824 : // Revocation Checking
825 : //
826 :
827 : /** Add a Certificate Revocation List from memory.
828 :
829 : Adds a CRL to the verification store for checking whether
830 : certificates are revoked. CRLs are typically fetched
831 : from the URLs in a certificate's CRL Distribution Points
832 : extension.
833 :
834 : @param crl The CRL data in DER or PEM format.
835 :
836 : @return Success. The CRL is recorded and decoded when the native
837 : context is first built; a malformed CRL surfaces as a
838 : handshake failure.
839 :
840 : @note CRLs are consulted only when a revocation policy is set via
841 : @ref set_revocation_policy. On WolfSSL, CRL checking requires a
842 : build with `HAVE_CRL`; without it, a revocation policy
843 : other than `disabled` fails the handshake with
844 : `std::errc::function_not_supported`.
845 :
846 : @see add_crl_file
847 : @see set_revocation_policy
848 : */
849 : [[nodiscard]] std::error_code add_crl(std::string_view crl);
850 :
851 : /** Add a Certificate Revocation List from a file.
852 :
853 : Adds a CRL to the verification store for checking whether
854 : certificates are revoked.
855 :
856 : @param filename Path to a CRL file (DER or PEM format).
857 :
858 : @return Success, or an error if the file could not be read. The
859 : CRL is decoded when the native context is first built; a
860 : malformed CRL surfaces as a handshake failure.
861 :
862 : @note CRLs are consulted only when a revocation policy is set via
863 : @ref set_revocation_policy (WolfSSL requires a `HAVE_CRL`
864 : build).
865 :
866 : @par Example
867 : @par !example add_crl_file
868 :
869 : @see add_crl
870 : @see set_revocation_policy
871 : */
872 : [[nodiscard]] std::error_code add_crl_file(std::string_view filename);
873 :
874 : /** Set the certificate revocation checking policy.
875 :
876 : Controls how certificate revocation status is checked during
877 : verification via CRLs.
878 :
879 : @param policy The revocation checking policy.
880 :
881 : @par Example
882 : @par !example set_revocation_policy
883 :
884 : @note Revocation is checked via CRLs supplied with @ref add_crl /
885 : @ref add_crl_file. `soft_fail` accepts a certificate whose
886 : status cannot be determined (missing/expired CRL) but rejects
887 : one that is actually revoked; `hard_fail` also rejects unknown
888 : status. OCSP-based revocation is not available (see the TLS
889 : guide). On WolfSSL a non-disabled policy requires a `HAVE_CRL`
890 : build, else the handshake fails with
891 : `std::errc::function_not_supported`.
892 :
893 : @see tls_revocation_policy
894 : @see add_crl
895 : */
896 : void set_revocation_policy(tls_revocation_policy policy);
897 :
898 : //
899 : // Password Handling
900 : //
901 :
902 : /** Set the password callback for encrypted keys.
903 :
904 : Installs a callback that provides passwords for encrypted
905 : private keys and PKCS#12 files. The callback is invoked when
906 : loading encrypted key material.
907 :
908 : @tparam Callback A callable with signature
909 : `std::string( std::size_t max_length, tls_password_purpose purpose )`.
910 :
911 : @param callback The password callback. It receives the maximum
912 : password length and the purpose (reading or writing), and
913 : returns the password string.
914 :
915 : @par Example
916 : @par !example set_password_callback
917 :
918 : @see tls_password_purpose
919 : */
920 : template<typename Callback>
921 : void set_password_callback(Callback callback);
922 : };
923 : #ifdef _MSC_VER
924 : #pragma warning(pop)
925 : #endif
926 :
927 : template<typename Callback>
928 : void
929 1 : tls_context::set_servername_callback(Callback callback)
930 : {
931 1 : set_servername_callback_impl(std::move(callback));
932 1 : }
933 :
934 : template<typename Callback>
935 : void
936 4 : tls_context::set_password_callback(Callback callback)
937 : {
938 4 : set_password_callback_impl(std::move(callback));
939 4 : }
940 :
941 : template<typename Callback>
942 : void
943 2 : tls_context::set_verify_callback(Callback callback)
944 : {
945 2 : set_verify_callback_impl(std::move(callback));
946 2 : }
947 :
948 : } // namespace boost::corosio
949 :
950 : #endif
|