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