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