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