include/boost/corosio/tls_context.hpp

100.0% Lines (11/11) 100.0% List of functions (7/7)
tls_context.hpp
f(x) Functions (7)
Line TLA Hits 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 /** A non-owning view of certificate verification state.
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), der_(der), der_len_(der_len)
157 {
158 }
159
160 /** Return the native verification handle.
161
162 Cast the result to the backend's verification context type
163 (e.g. `X509_STORE_CTX*`) to inspect the certificate chain using
164 backend-specific APIs.
165
166 @return The native handle, or `nullptr` if none is available.
167 */
168 void* native_handle() const noexcept { return handle_; }
169
170 /** Return the DER encoding of the certificate being verified.
171
172 This is the portable way to inspect the peer certificate from a
173 verification callback: it works identically on every backend,
174 without depending on backend-specific build options. A DER
175 certificate is an ASN.1 `SEQUENCE`, so the first byte is `0x30`.
176
177 @return A view of the certificate's DER bytes, valid only for the
178 duration of the callback. Empty if the certificate is not
179 available.
180 */
181 std::span<unsigned char const> certificate() const noexcept
182 {
183 return {der_, der_len_};
184 }
185 };
186
187 namespace detail {
188 struct tls_context_data;
189 tls_context_data const& get_tls_context_data(tls_context const&) noexcept;
190 } // namespace detail
191
192 /** A portable TLS context for certificate and settings storage.
193
194 The `tls_context` class provides a backend-agnostic interface for
195 configuring TLS connections. It stores credentials (certificates and
196 private keys), trust anchors, protocol settings, and verification
197 options that are used when establishing TLS connections.
198
199 This class is a shared handle to an opaque implementation. Copies
200 share the same underlying state. This allows contexts to be passed
201 by value and shared across multiple TLS streams.
202
203 This class abstracts the configuration phase of TLS across multiple
204 backend implementations (OpenSSL, WolfSSL, mbedTLS, Schannel, etc.),
205 allowing portable code that works regardless of which TLS library
206 is linked.
207
208 @par Modification After Stream Creation
209
210 Modifying a context after a TLS stream has been created from it
211 results in undefined behavior. The context's configuration is
212 captured when the first stream is constructed, and subsequent
213 modifications are not reflected in existing or new streams
214 sharing the context.
215
216 If different configurations are needed, create separate context
217 objects.
218
219 @par Thread Safety
220
221 Distinct objects: Safe.
222
223 Shared objects: Unsafe. A context must not be modified while
224 any thread is creating streams from it.
225
226 @par Example
227 @code
228 // Create a client context with system trust anchors
229 corosio::tls_context ctx;
230 ctx.set_default_verify_paths();
231 ctx.set_verify_mode( corosio::tls_verify_mode::peer );
232
233 // Use with a TLS stream
234 corosio::openssl_stream secure( &sock, ctx );
235 secure.set_hostname( "example.com" );
236 co_await secure.handshake( corosio::tls_role::client );
237 @endcode
238
239 @see tls_role
240 */
241 #ifdef _MSC_VER
242 #pragma warning(push)
243 #pragma warning(disable : 4251) // shared_ptr needs dll-interface
244 #endif
245 class BOOST_COROSIO_DECL tls_context
246 {
247 struct impl;
248 std::shared_ptr<impl> impl_;
249
250 friend detail::tls_context_data const&
251 detail::get_tls_context_data(tls_context const&) noexcept;
252
253 public:
254 /** Construct a default TLS context.
255
256 Creates a context with default settings suitable for TLS 1.2
257 and TLS 1.3 connections. No certificates or trust anchors are
258 loaded; call the appropriate methods to configure credentials
259 and verification.
260
261 @par Example
262 @code
263 corosio::tls_context ctx;
264 @endcode
265 */
266 tls_context();
267
268 /** Copy constructor.
269
270 Creates a new handle that shares ownership of the underlying
271 TLS context state with `other`.
272
273 @param other The context to copy from.
274 */
275 1x tls_context(tls_context const& other) = default;
276
277 /** Copy assignment operator.
278
279 Releases the current context's shared ownership and acquires
280 shared ownership of `other`'s underlying state.
281
282 @param other The context to copy from.
283
284 @return Reference to this context.
285 */
286 1x tls_context& operator=(tls_context const& other) = default;
287
288 /** Move constructor.
289
290 Transfers ownership of the TLS context from another instance.
291 After the move, `other` is in a valid but empty state.
292
293 @param other The context to move from.
294 */
295 1x tls_context(tls_context&& other) noexcept = default;
296
297 /** Move assignment operator.
298
299 Releases the current context's shared ownership and transfers
300 ownership from another instance. After the move, `other` is
301 in a valid but empty state.
302
303 @param other The context to move from.
304
305 @return Reference to this context.
306 */
307 1x tls_context& operator=(tls_context&& other) noexcept = default;
308
309 /** Destructor.
310
311 Releases this handle's shared ownership of the underlying
312 context. The context state is destroyed when the last handle
313 is released.
314 */
315 33x ~tls_context() = default;
316
317 //
318 // Credential Loading
319 //
320
321 /** Load the entity certificate from a memory buffer.
322
323 Sets the certificate that identifies this endpoint to the peer.
324 For servers, this is the server certificate. For clients using
325 mutual TLS, this is the client certificate.
326
327 The certificate must match the private key loaded via
328 `use_private_key()` or `use_private_key_file()`.
329
330 @param certificate The certificate data.
331
332 @param format The encoding format of the certificate data.
333
334 @return Success, or an error if the certificate could not be parsed
335 or is invalid.
336
337 @see use_certificate_file
338 @see use_private_key
339 */
340 std::error_code
341 use_certificate(std::string_view certificate, tls_file_format format);
342
343 /** Load the entity certificate from a file.
344
345 Sets the certificate that identifies this endpoint to the peer.
346 For servers, this is the server certificate. For clients using
347 mutual TLS, this is the client certificate.
348
349 @param filename Path to the certificate file.
350
351 @param format The encoding format of the file.
352
353 @return Success, or an error if the file could not be read or the
354 certificate is invalid.
355
356 @par Example
357 @code
358 ctx.use_certificate_file( "server.crt", tls_file_format::pem );
359 @endcode
360
361 @see use_certificate
362 @see use_private_key_file
363 */
364 std::error_code
365 use_certificate_file(std::string_view filename, tls_file_format format);
366
367 /** Load a certificate chain from a memory buffer.
368
369 Loads the entity certificate followed by intermediate CA certificates.
370 The chain should be ordered from leaf to root (excluding the root).
371 This is the typical format for PEM certificate bundles.
372
373 @param chain The certificate chain data in PEM format (concatenated
374 certificates).
375
376 @return Success, or an error if the chain could not be parsed.
377
378 @see use_certificate_chain_file
379 */
380 std::error_code use_certificate_chain(std::string_view chain);
381
382 /** Load a certificate chain from a file.
383
384 Loads the entity certificate followed by intermediate CA certificates
385 from a PEM file. The file should contain concatenated PEM certificates
386 ordered from leaf to root (excluding the root).
387
388 @param filename Path to the certificate chain file.
389
390 @return Success, or an error if the file could not be read or parsed.
391
392 @par Example
393 @code
394 // Load certificate chain (cert + intermediates)
395 ctx.use_certificate_chain_file( "fullchain.pem" );
396 @endcode
397
398 @see use_certificate_chain
399 */
400 std::error_code use_certificate_chain_file(std::string_view filename);
401
402 /** Load the private key from a memory buffer.
403
404 Sets the private key corresponding to the entity certificate.
405 The key must match the certificate loaded via `use_certificate()`
406 or `use_certificate_chain()`.
407
408 If the key is encrypted, set a password callback via
409 `set_password_callback()` before calling this function.
410
411 @param private_key The private key data.
412
413 @param format The encoding format of the key data.
414
415 @return Success, or an error if the key could not be parsed,
416 is encrypted without a password callback, or doesn't match
417 the certificate.
418
419 @see use_private_key_file
420 @see set_password_callback
421 */
422 std::error_code
423 use_private_key(std::string_view private_key, tls_file_format format);
424
425 /** Load the private key from a file.
426
427 Sets the private key corresponding to the entity certificate.
428 The key must match the certificate loaded via `use_certificate_file()`
429 or `use_certificate_chain_file()`.
430
431 If the key file is encrypted, set a password callback via
432 `set_password_callback()` before calling this function.
433
434 @param filename Path to the private key file.
435
436 @param format The encoding format of the file.
437
438 @return Success, or an error if the file could not be read,
439 the key is invalid, or it doesn't match the certificate.
440
441 @par Example
442 @code
443 ctx.use_private_key_file( "server.key", tls_file_format::pem );
444 @endcode
445
446 @see use_private_key
447 @see set_password_callback
448 */
449 std::error_code
450 use_private_key_file(std::string_view filename, tls_file_format format);
451
452 /** Load credentials from a PKCS#12 bundle in memory.
453
454 PKCS#12 (also known as PFX) is a binary format that bundles a
455 certificate, private key, and optionally intermediate certificates
456 into a single password-protected file.
457
458 @param data The PKCS#12 bundle data.
459
460 @param passphrase The password protecting the bundle.
461
462 @return Success. The bundle is recorded and decoded into the
463 certificate, private key, and chain when the native context is
464 first built; a malformed bundle or wrong passphrase surfaces as
465 a handshake failure.
466
467 @note Intermediate certificates inside the bundle are loaded and
468 sent during the handshake on both backends.
469
470 @see use_pkcs12_file
471 */
472 std::error_code
473 use_pkcs12(std::string_view data, std::string_view passphrase);
474
475 /** Load credentials from a PKCS#12 file.
476
477 PKCS#12 (also known as PFX) is a binary format that bundles a
478 certificate, private key, and optionally intermediate certificates
479 into a single password-protected file. This is common on Windows
480 and for certificates exported from browsers.
481
482 @param filename Path to the PKCS#12 file.
483
484 @param passphrase The password protecting the file.
485
486 @return Success, or an error if the file could not be read. The
487 bundle is decoded when the native context is first built; a
488 malformed bundle or wrong passphrase surfaces as a handshake
489 failure.
490
491 @note Intermediate certificates inside the bundle are loaded and
492 sent during the handshake on both backends.
493
494 @par Example
495 @code
496 ctx.use_pkcs12_file( "credentials.pfx", "secret" );
497 @endcode
498
499 @see use_pkcs12
500 */
501 std::error_code
502 use_pkcs12_file(std::string_view filename, std::string_view passphrase);
503
504 //
505 // Trust Anchors
506 //
507
508 /** Add a certificate authority for peer verification.
509
510 Adds a single CA certificate to the trust store used for verifying
511 peer certificates. Call this multiple times to add multiple CAs,
512 or use `load_verify_file()` for a bundle.
513
514 @param ca The CA certificate data in PEM format.
515
516 @return Success, or an error if the certificate could not be parsed.
517
518 @see load_verify_file
519 @see set_default_verify_paths
520 */
521 std::error_code add_certificate_authority(std::string_view ca);
522
523 /** Load CA certificates from a file.
524
525 Loads one or more CA certificates from a PEM file. The file may
526 contain multiple concatenated PEM certificates.
527
528 @param filename Path to a PEM file containing CA certificates.
529
530 @return Success, or an error if the file could not be read or parsed.
531
532 @par Example
533 @code
534 // Load a custom CA bundle
535 ctx.load_verify_file( "/etc/ssl/certs/ca-certificates.crt" );
536 @endcode
537
538 @see add_certificate_authority
539 @see add_verify_path
540 */
541 std::error_code load_verify_file(std::string_view filename);
542
543 /** Add a directory of CA certificates for verification.
544
545 Adds a directory of CA certificates to the trust store. The
546 directory is applied when the native context is first built from
547 this context.
548
549 The expected directory layout depends on the backend. OpenSSL
550 performs on-demand lookups and requires each certificate file to
551 be named by its subject-name hash (as generated by
552 `openssl rehash` or `c_rehash`); WolfSSL loads every certificate
553 file in the directory.
554
555 @param path Path to the directory of CA certificates.
556
557 @return Success. The path is recorded and applied when the native
558 context is built; a directory that cannot be read at that time
559 is skipped rather than reported here.
560
561 @par Example
562 @code
563 ctx.add_verify_path( "/etc/ssl/certs" );
564 @endcode
565
566 @see load_verify_file
567 @see set_default_verify_paths
568 */
569 std::error_code add_verify_path(std::string_view path);
570
571 /** Use the system default CA certificate store.
572
573 Configures the context to use the operating system's default
574 trust store for peer certificate verification. This is the
575 recommended approach for HTTPS clients connecting to public
576 servers.
577
578 The system store is loaded when the native context is first built
579 from this context. For a verified-safe client, combine this with
580 `set_verify_mode( tls_verify_mode::peer )` and, when connecting by
581 name, `tls_stream::set_hostname()`.
582
583 @return Success. The request is recorded and applied when the
584 native context is built; if the system store cannot be loaded
585 at that time it is skipped rather than reported here, so a
586 context that must reject unverified peers should also use
587 `set_verify_mode( tls_verify_mode::peer )`.
588
589 @note The OpenSSL backend honors the `SSL_CERT_FILE` and
590 `SSL_CERT_DIR` environment variables. The WolfSSL backend
591 requires a build with `WOLFSSL_SYS_CA_CERTS`; without it the
592 system store is unavailable and this call has no effect.
593
594 @par Example
595 @code
596 // Trust the same CAs as the system
597 ctx.set_default_verify_paths();
598 ctx.set_verify_mode( tls_verify_mode::peer );
599 @endcode
600
601 @see load_verify_file
602 @see add_verify_path
603 @see set_verify_mode
604 */
605 std::error_code set_default_verify_paths();
606
607 //
608 // Protocol Configuration
609 //
610
611 /** Set the minimum TLS protocol version.
612
613 Connections will reject protocol versions older than this.
614 The default allows TLS 1.2 and newer.
615
616 @param v The minimum protocol version to accept.
617
618 @return Success, or an error if the version is not supported
619 by the backend.
620
621 @par Example
622 @code
623 // Require TLS 1.3 minimum
624 ctx.set_min_protocol_version( tls_version::tls_1_3 );
625 @endcode
626
627 @see set_max_protocol_version
628 */
629 std::error_code set_min_protocol_version(tls_version v);
630
631 /** Set the maximum TLS protocol version.
632
633 Connections will not negotiate protocol versions newer than this.
634 The default allows the newest supported version.
635
636 @param v The maximum protocol version to accept.
637
638 @return Success, or an error if the version is not supported
639 by the backend.
640
641 @note On WolfSSL the ceiling is applied by selecting a
642 version-specific method (no native set-max API exists); an
643 invalid window where the minimum exceeds the maximum yields a
644 context that fails the handshake.
645
646 @see set_min_protocol_version
647 */
648 std::error_code set_max_protocol_version(tls_version v);
649
650 /** Set the allowed cipher suites.
651
652 Configures which cipher suites may be used for connections.
653 The format is backend-specific but typically follows OpenSSL
654 cipher list syntax.
655
656 @param ciphers The cipher suite specification string.
657
658 @return Success, or an error if the cipher string is invalid.
659
660 @par Example
661 @code
662 // TLS 1.2 cipher suites (OpenSSL format)
663 ctx.set_ciphersuites( "ECDHE+AESGCM:ECDHE+CHACHA20" );
664 @endcode
665
666 @note This configures cipher suites for TLS 1.2 and below. For
667 TLS 1.3, use @ref set_ciphersuites_tls13.
668 */
669 std::error_code set_ciphersuites(std::string_view ciphers);
670
671 /** Set the allowed TLS 1.3 cipher suites.
672
673 TLS 1.3 uses a distinct, fixed set of cipher suites configured
674 separately from earlier versions. The format is a colon-separated
675 list of TLS 1.3 suite names.
676
677 @param ciphers The TLS 1.3 cipher suite list.
678
679 @return Success, or an error if the cipher string is invalid.
680
681 @par Example
682 @code
683 ctx.set_ciphersuites_tls13(
684 "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" );
685 @endcode
686
687 @note On the WolfSSL backend, TLS 1.2 and TLS 1.3 suites share a
688 single cipher list; this call and @ref set_ciphersuites are
689 merged into one list.
690
691 @see set_ciphersuites
692 */
693 std::error_code set_ciphersuites_tls13(std::string_view ciphers);
694
695 /** Set the ALPN protocol list.
696
697 Configures Application-Layer Protocol Negotiation (ALPN) for
698 the connection. ALPN is used to negotiate which application
699 protocol to use over the TLS connection (e.g., "h2" for HTTP/2,
700 "http/1.1" for HTTP/1.1).
701
702 The protocols are tried in preference order (first = highest).
703
704 @param protocols Ordered list of protocol identifiers.
705
706 @return Success, or an error if ALPN configuration fails.
707
708 @note Read the negotiated protocol after the handshake via
709 @ref tls_stream::alpn_protocol. On WolfSSL, ALPN requires a
710 build with `HAVE_ALPN`; without it, offering protocols fails
711 the handshake with `std::errc::function_not_supported` rather
712 than negotiate nothing silently.
713
714 @par Example
715 @code
716 // Prefer HTTP/2, fall back to HTTP/1.1
717 ctx.set_alpn( { "h2", "http/1.1" } );
718 @endcode
719 */
720 std::error_code set_alpn(std::initializer_list<std::string_view> protocols);
721
722 //
723 // Certificate Verification
724 //
725
726 /** Set the peer certificate verification mode.
727
728 Controls whether and how peer certificates are verified during
729 the TLS handshake.
730
731 @param mode The verification mode to use.
732
733 @return Success, or an error if the mode could not be set.
734
735 @par Example
736 @code
737 // Verify peer certificate (typical for clients)
738 ctx.set_verify_mode( tls_verify_mode::peer );
739
740 // Require client certificate (server-side mTLS)
741 ctx.set_verify_mode( tls_verify_mode::require_peer );
742 @endcode
743
744 @see tls_verify_mode
745 */
746 std::error_code set_verify_mode(tls_verify_mode mode);
747
748 /** Set the maximum certificate chain verification depth.
749
750 Limits how many intermediate certificates can appear between
751 the peer certificate and a trusted root. The default is
752 typically 100, which is sufficient for most certificate chains.
753
754 @param depth Maximum number of intermediate certificates allowed.
755
756 @return Success, or an error if the depth is invalid.
757 */
758 std::error_code set_verify_depth(int depth);
759
760 /** Set a custom certificate verification callback.
761
762 Installs a callback that is invoked during certificate chain
763 verification. The callback can perform additional validation
764 beyond the standard checks and can override verification
765 results.
766
767 The callback receives the built-in verification result so far and
768 a verify_context describing the certificate being verified. Return
769 `true` to accept the certificate, `false` to reject. Inspect the
770 certificate portably via `verify_context::certificate()` (its DER
771 encoding) — for example to pin a specific certificate.
772
773 @par Backend Support
774
775 The exact set of certificates the callback sees differs by backend:
776
777 - OpenSSL: the callback runs once per certificate in the chain,
778 including certificates that passed the built-in checks. It can
779 therefore both relax verification (return `true` for a
780 certificate the library rejected) and tighten it (return `false`
781 for a certificate the library accepted, e.g. pinning).
782 - WolfSSL built with `WOLFSSL_ALWAYS_VERIFY_CB` (implied by
783 `--enable-opensslextra`): same as OpenSSL.
784 - WolfSSL without that option: the library invokes the callback
785 only on verification *failure*, so it cannot be honored on a
786 successful handshake. To avoid silently ignoring a
787 verification-tightening callback (which would fail open), a
788 context that carries a callback instead **fails the handshake**
789 with `std::errc::function_not_supported` on such a build. Rebuild
790 WolfSSL with `WOLFSSL_ALWAYS_VERIFY_CB`, or omit the callback.
791
792 @tparam Callback A callable with signature
793 `bool( bool preverified, verify_context& ctx )`.
794
795 @param callback The verification callback.
796
797 @return Success. The callback is recorded here and applied during the
798 handshake. On a WolfSSL build that cannot honor it, the handshake
799 fails with `std::errc::function_not_supported` (see Backend
800 Support).
801
802 @par Example
803 @code
804 ctx.set_verify_mode( tls_verify_mode::peer );
805 ctx.set_verify_callback(
806 []( bool preverified, verify_context& ctx ) -> bool
807 {
808 if( ! preverified )
809 return false;
810 // Pin: accept only a certificate whose DER matches.
811 auto der = ctx.certificate();
812 return der.size() == expected_pin.size() &&
813 std::equal( der.begin(), der.end(), expected_pin.begin() );
814 });
815 @endcode
816
817 @see verify_context
818 @see set_verify_mode
819 */
820 template<typename Callback>
821 std::error_code set_verify_callback(Callback callback);
822
823 /** Set a callback for Server Name Indication (SNI).
824
825 For server connections, this callback is invoked during the TLS
826 handshake when a client sends an SNI extension. The callback
827 receives the requested hostname and can accept or reject the
828 connection.
829
830 @tparam Callback A callable with signature
831 `bool( std::string_view hostname )`.
832
833 @param callback The SNI callback. Return `true` to accept the
834 connection or `false` to reject it with an alert.
835
836 @par Example
837 @code
838 // Accept connections for specific domains only
839 ctx.set_servername_callback(
840 []( std::string_view hostname ) -> bool
841 {
842 return hostname == "api.example.com" ||
843 hostname == "www.example.com";
844 });
845 @endcode
846
847 @note For virtual hosting with different certificates per hostname,
848 create separate contexts and select the appropriate one before
849 creating the TLS stream.
850
851 @see tls_stream::set_hostname
852 */
853 template<typename Callback>
854 void set_servername_callback(Callback callback);
855
856 private:
857 void set_servername_callback_impl(
858 std::function<bool(std::string_view)> callback);
859
860 void set_password_callback_impl(
861 std::function<std::string(std::size_t, tls_password_purpose)> callback);
862
863 void set_verify_callback_impl(
864 std::function<bool(bool, verify_context&)> callback);
865
866 public:
867 //
868 // Revocation Checking
869 //
870
871 /** Add a Certificate Revocation List from memory.
872
873 Adds a CRL to the verification store for checking whether
874 certificates have been revoked. CRLs are typically fetched
875 from the URLs in a certificate's CRL Distribution Points
876 extension.
877
878 @param crl The CRL data in DER or PEM format.
879
880 @return Success, or an error if the CRL could not be parsed.
881
882 @note CRLs are consulted only when a revocation policy is set via
883 @ref set_revocation_policy. On WolfSSL, CRL checking requires a
884 build with `HAVE_CRL`; without it, supplying a CRL or a
885 revocation policy fails the handshake with
886 `std::errc::function_not_supported`.
887
888 @see add_crl_file
889 @see set_revocation_policy
890 */
891 std::error_code add_crl(std::string_view crl);
892
893 /** Add a Certificate Revocation List from a file.
894
895 Adds a CRL to the verification store for checking whether
896 certificates have been revoked.
897
898 @param filename Path to a CRL file (DER or PEM format).
899
900 @return Success, or an error if the file could not be read
901 or the CRL is invalid.
902
903 @note CRLs are consulted only when a revocation policy is set via
904 @ref set_revocation_policy (WolfSSL requires a `HAVE_CRL`
905 build).
906
907 @par Example
908 @code
909 ctx.add_crl_file( "issuer.crl" );
910 @endcode
911
912 @see add_crl
913 @see set_revocation_policy
914 */
915 std::error_code add_crl_file(std::string_view filename);
916
917 /** Set the certificate revocation checking policy.
918
919 Controls how certificate revocation status is checked during
920 verification via CRLs.
921
922 @param policy The revocation checking policy.
923
924 @par Example
925 @code
926 // Require successful revocation check
927 ctx.set_revocation_policy( tls_revocation_policy::hard_fail );
928
929 // Check but allow unknown status
930 ctx.set_revocation_policy( tls_revocation_policy::soft_fail );
931 @endcode
932
933 @note Revocation is checked via CRLs supplied with @ref add_crl /
934 @ref add_crl_file. `soft_fail` accepts a certificate whose
935 status cannot be determined (missing/expired CRL) but rejects
936 one that is actually revoked; `hard_fail` also rejects unknown
937 status. OCSP-based revocation is not available (see the TLS
938 guide). On WolfSSL a non-disabled policy requires a `HAVE_CRL`
939 build, else the handshake fails with
940 `std::errc::function_not_supported`.
941
942 @see tls_revocation_policy
943 @see add_crl
944 */
945 void set_revocation_policy(tls_revocation_policy policy);
946
947 //
948 // Password Handling
949 //
950
951 /** Set the password callback for encrypted keys.
952
953 Installs a callback that provides passwords for encrypted
954 private keys and PKCS#12 files. The callback is invoked when
955 loading encrypted key material.
956
957 @tparam Callback A callable with signature
958 `std::string( std::size_t max_length, password_purpose purpose )`.
959
960 @param callback The password callback. It receives the maximum
961 password length and the purpose (reading or writing), and
962 returns the password string.
963
964 @par Example
965 @code
966 ctx.set_password_callback(
967 []( std::size_t max_len, tls_password_purpose purpose )
968 {
969 // In practice, prompt user or read from secure storage
970 return std::string( "my-key-password" );
971 });
972
973 // Now load encrypted key
974 ctx.use_private_key_file( "encrypted.key", tls_file_format::pem );
975 @endcode
976
977 @see tls_password_purpose
978 */
979 template<typename Callback>
980 void set_password_callback(Callback callback);
981 };
982 #ifdef _MSC_VER
983 #pragma warning(pop)
984 #endif
985
986 template<typename Callback>
987 void
988 1x tls_context::set_servername_callback(Callback callback)
989 {
990 1x set_servername_callback_impl(std::move(callback));
991 1x }
992
993 template<typename Callback>
994 void
995 1x tls_context::set_password_callback(Callback callback)
996 {
997 1x set_password_callback_impl(std::move(callback));
998 1x }
999
1000 template<typename Callback>
1001 std::error_code
1002 tls_context::set_verify_callback(Callback callback)
1003 {
1004 set_verify_callback_impl(std::move(callback));
1005 return {};
1006 }
1007
1008 } // namespace boost::corosio
1009
1010 #endif
1011