include/boost/corosio/tls_context.hpp

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