100.00% Lines (11/11) 100.00% Functions (7/7)
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   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/corosio 7   // Official repository: https://github.com/cppalliance/corosio
8   // 8   //
9   9  
10   #ifndef BOOST_COROSIO_TLS_CONTEXT_HPP 10   #ifndef BOOST_COROSIO_TLS_CONTEXT_HPP
11   #define BOOST_COROSIO_TLS_CONTEXT_HPP 11   #define BOOST_COROSIO_TLS_CONTEXT_HPP
12   12  
13   #include <boost/corosio/detail/config.hpp> 13   #include <boost/corosio/detail/config.hpp>
14   14  
15   #include <functional> 15   #include <functional>
16   #include <system_error> 16   #include <system_error>
17   #include <memory> 17   #include <memory>
18   #include <string_view> 18   #include <string_view>
19   19  
20   namespace boost::corosio { 20   namespace boost::corosio {
21   21  
22   // 22   //
23   // Enumerations 23   // Enumerations
24   // 24   //
25   25  
26   /** TLS handshake role. 26   /** TLS handshake role.
27   27  
28   Specifies whether to perform the TLS handshake as a client or server. 28   Specifies whether to perform the TLS handshake as a client or server.
29   29  
30   @see stream::handshake 30   @see stream::handshake
31   */ 31   */
32   enum class tls_role 32   enum class tls_role
33   { 33   {
34   /// Perform handshake as the connecting client. 34   /// Perform handshake as the connecting client.
35   client, 35   client,
36   36  
37   /// Perform handshake as the accepting server. 37   /// Perform handshake as the accepting server.
38   server 38   server
39   }; 39   };
40   40  
41   /** TLS protocol version. 41   /** TLS protocol version.
42   42  
43   Specifies the minimum or maximum TLS protocol version to use 43   Specifies the minimum or maximum TLS protocol version to use
44   for connections. Only modern, secure versions are supported. 44   for connections. Only modern, secure versions are supported.
45   45  
46   @see tls_context::set_min_protocol_version 46   @see tls_context::set_min_protocol_version
47   @see tls_context::set_max_protocol_version 47   @see tls_context::set_max_protocol_version
48   */ 48   */
49   enum class tls_version 49   enum class tls_version
50   { 50   {
51   /// TLS 1.2 (RFC 5246). 51   /// TLS 1.2 (RFC 5246).
52   tls_1_2, 52   tls_1_2,
53   53  
54   /// TLS 1.3 (RFC 8446). 54   /// TLS 1.3 (RFC 8446).
55   tls_1_3 55   tls_1_3
56   }; 56   };
57   57  
58   /** Certificate and key file format. 58   /** Certificate and key file format.
59   59  
60   Specifies the encoding format for certificate and key data. 60   Specifies the encoding format for certificate and key data.
61   61  
62   @see tls_context::use_certificate 62   @see tls_context::use_certificate
63   @see tls_context::use_private_key 63   @see tls_context::use_private_key
64   */ 64   */
65   enum class tls_file_format 65   enum class tls_file_format
66   { 66   {
67   /// PEM format (Base64-encoded with header/footer lines). 67   /// PEM format (Base64-encoded with header/footer lines).
68   pem, 68   pem,
69   69  
70   /// DER format (raw ASN.1 binary encoding). 70   /// DER format (raw ASN.1 binary encoding).
71   der 71   der
72   }; 72   };
73   73  
74   /** Peer certificate verification mode. 74   /** Peer certificate verification mode.
75   75  
76   Controls how the TLS implementation verifies the peer's 76   Controls how the TLS implementation verifies the peer's
77   certificate during the handshake. 77   certificate during the handshake.
78   78  
79   @see tls_context::set_verify_mode 79   @see tls_context::set_verify_mode
80   */ 80   */
81   enum class tls_verify_mode 81   enum class tls_verify_mode
82   { 82   {
83   /// Do not request or verify the peer certificate. 83   /// Do not request or verify the peer certificate.
84   none, 84   none,
85   85  
86   /// Request and verify the peer certificate if presented. 86   /// Request and verify the peer certificate if presented.
87   peer, 87   peer,
88   88  
89   /// Require and verify the peer certificate (fail if not presented). 89   /// Require and verify the peer certificate (fail if not presented).
90   require_peer 90   require_peer
91   }; 91   };
92   92  
93   /** Certificate revocation checking policy. 93   /** Certificate revocation checking policy.
94   94  
95   Controls how certificate revocation status is checked during 95   Controls how certificate revocation status is checked during
96   verification. 96   verification.
97   97  
98   @see tls_context::set_revocation_policy 98   @see tls_context::set_revocation_policy
99   */ 99   */
100   enum class tls_revocation_policy 100   enum class tls_revocation_policy
101   { 101   {
102   /// Do not check revocation status. 102   /// Do not check revocation status.
103   disabled, 103   disabled,
104   104  
105   /// Check revocation but allow connection if status is unknown. 105   /// Check revocation but allow connection if status is unknown.
106   soft_fail, 106   soft_fail,
107   107  
108   /// Require successful revocation check (fail if status is unknown). 108   /// Require successful revocation check (fail if status is unknown).
109   hard_fail 109   hard_fail
110   }; 110   };
111   111  
112   /** Purpose for password callback invocation. 112   /** Purpose for password callback invocation.
113   113  
114   Indicates whether the password is needed for reading (decrypting) 114   Indicates whether the password is needed for reading (decrypting)
115   or writing (encrypting) key material. 115   or writing (encrypting) key material.
116   116  
117   @see tls_context::set_password_callback 117   @see tls_context::set_password_callback
118   */ 118   */
119   enum class tls_password_purpose 119   enum class tls_password_purpose
120   { 120   {
121   /// Password needed to decrypt/read protected key material. 121   /// Password needed to decrypt/read protected key material.
122   for_reading, 122   for_reading,
123   123  
124   /// Password needed to encrypt/write protected key material. 124   /// Password needed to encrypt/write protected key material.
125   for_writing 125   for_writing
126   }; 126   };
127   127  
128   class tls_context; 128   class tls_context;
129   129  
130   namespace detail { 130   namespace detail {
131   struct tls_context_data; 131   struct tls_context_data;
132   tls_context_data const& get_tls_context_data(tls_context const&) noexcept; 132   tls_context_data const& get_tls_context_data(tls_context const&) noexcept;
133   } // namespace detail 133   } // namespace detail
134   134  
135   /** A portable TLS context for certificate and settings storage. 135   /** A portable TLS context for certificate and settings storage.
136   136  
137   The `tls_context` class provides a backend-agnostic interface for 137   The `tls_context` class provides a backend-agnostic interface for
138   configuring TLS connections. It stores credentials (certificates and 138   configuring TLS connections. It stores credentials (certificates and
139   private keys), trust anchors, protocol settings, and verification 139   private keys), trust anchors, protocol settings, and verification
140   options that are used when establishing TLS connections. 140   options that are used when establishing TLS connections.
141   141  
142   This class is a shared handle to an opaque implementation. Copies 142   This class is a shared handle to an opaque implementation. Copies
143   share the same underlying state. This allows contexts to be passed 143   share the same underlying state. This allows contexts to be passed
144   by value and shared across multiple TLS streams. 144   by value and shared across multiple TLS streams.
145   145  
146   This class abstracts the configuration phase of TLS across multiple 146   This class abstracts the configuration phase of TLS across multiple
147   backend implementations (OpenSSL, WolfSSL, mbedTLS, Schannel, etc.), 147   backend implementations (OpenSSL, WolfSSL, mbedTLS, Schannel, etc.),
148   allowing portable code that works regardless of which TLS library 148   allowing portable code that works regardless of which TLS library
149   is linked. 149   is linked.
150   150  
151   @par Modification After Stream Creation 151   @par Modification After Stream Creation
152   152  
153   Modifying a context after a TLS stream has been created from it 153   Modifying a context after a TLS stream has been created from it
154   results in undefined behavior. The context's configuration is 154   results in undefined behavior. The context's configuration is
155   captured when the first stream is constructed, and subsequent 155   captured when the first stream is constructed, and subsequent
156   modifications are not reflected in existing or new streams 156   modifications are not reflected in existing or new streams
157   sharing the context. 157   sharing the context.
158   158  
159   If different configurations are needed, create separate context 159   If different configurations are needed, create separate context
160   objects. 160   objects.
161   161  
162   @par Thread Safety 162   @par Thread Safety
163   163  
164   Distinct objects: Safe. 164   Distinct objects: Safe.
165   165  
166   Shared objects: Unsafe. A context must not be modified while 166   Shared objects: Unsafe. A context must not be modified while
167   any thread is creating streams from it. 167   any thread is creating streams from it.
168   168  
169   @par Example 169   @par Example
170   @code 170   @code
171   // Create a client context with system trust anchors 171   // Create a client context with system trust anchors
172   corosio::tls_context ctx; 172   corosio::tls_context ctx;
173   ctx.set_default_verify_paths(); 173   ctx.set_default_verify_paths();
174   ctx.set_verify_mode( corosio::tls_verify_mode::peer ); 174   ctx.set_verify_mode( corosio::tls_verify_mode::peer );
175   ctx.set_hostname( "example.com" ); 175   ctx.set_hostname( "example.com" );
176   176  
177   // Use with a TLS stream 177   // Use with a TLS stream
178   corosio::openssl_stream secure( sock, ctx ); 178   corosio::openssl_stream secure( sock, ctx );
179   co_await secure.handshake( corosio::tls_stream::client ); 179   co_await secure.handshake( corosio::tls_stream::client );
180   @endcode 180   @endcode
181   181  
182   @see tls_role 182   @see tls_role
183   */ 183   */
184   #ifdef _MSC_VER 184   #ifdef _MSC_VER
185   #pragma warning(push) 185   #pragma warning(push)
186   #pragma warning(disable : 4251) // shared_ptr needs dll-interface 186   #pragma warning(disable : 4251) // shared_ptr needs dll-interface
187   #endif 187   #endif
188   class BOOST_COROSIO_DECL tls_context 188   class BOOST_COROSIO_DECL tls_context
189   { 189   {
190   struct impl; 190   struct impl;
191   std::shared_ptr<impl> impl_; 191   std::shared_ptr<impl> impl_;
192   192  
193   friend detail::tls_context_data const& 193   friend detail::tls_context_data const&
194   detail::get_tls_context_data(tls_context const&) noexcept; 194   detail::get_tls_context_data(tls_context const&) noexcept;
195   195  
196   public: 196   public:
197   /** Construct a default TLS context. 197   /** Construct a default TLS context.
198   198  
199   Creates a context with default settings suitable for TLS 1.2 199   Creates a context with default settings suitable for TLS 1.2
200   and TLS 1.3 connections. No certificates or trust anchors are 200   and TLS 1.3 connections. No certificates or trust anchors are
201   loaded; call the appropriate methods to configure credentials 201   loaded; call the appropriate methods to configure credentials
202   and verification. 202   and verification.
203   203  
204   @par Example 204   @par Example
205   @code 205   @code
206   corosio::tls_context ctx; 206   corosio::tls_context ctx;
207   @endcode 207   @endcode
208   */ 208   */
209   tls_context(); 209   tls_context();
210   210  
211   /** Copy constructor. 211   /** Copy constructor.
212   212  
213   Creates a new handle that shares ownership of the underlying 213   Creates a new handle that shares ownership of the underlying
214   TLS context state with `other`. 214   TLS context state with `other`.
215   215  
216   @param other The context to copy from. 216   @param other The context to copy from.
217   */ 217   */
HITCBC 218   1 tls_context(tls_context const& other) = default; 218   1 tls_context(tls_context const& other) = default;
219   219  
220   /** Copy assignment operator. 220   /** Copy assignment operator.
221   221  
222   Releases the current context's shared ownership and acquires 222   Releases the current context's shared ownership and acquires
223   shared ownership of `other`'s underlying state. 223   shared ownership of `other`'s underlying state.
224   224  
225   @param other The context to copy from. 225   @param other The context to copy from.
226   226  
227   @return Reference to this context. 227   @return Reference to this context.
228   */ 228   */
HITCBC 229   1 tls_context& operator=(tls_context const& other) = default; 229   1 tls_context& operator=(tls_context const& other) = default;
230   230  
231   /** Move constructor. 231   /** Move constructor.
232   232  
233   Transfers ownership of the TLS context from another instance. 233   Transfers ownership of the TLS context from another instance.
234   After the move, `other` is in a valid but empty state. 234   After the move, `other` is in a valid but empty state.
235   235  
236   @param other The context to move from. 236   @param other The context to move from.
237   */ 237   */
HITCBC 238   1 tls_context(tls_context&& other) noexcept = default; 238   1 tls_context(tls_context&& other) noexcept = default;
239   239  
240   /** Move assignment operator. 240   /** Move assignment operator.
241   241  
242   Releases the current context's shared ownership and transfers 242   Releases the current context's shared ownership and transfers
243   ownership from another instance. After the move, `other` is 243   ownership from another instance. After the move, `other` is
244   in a valid but empty state. 244   in a valid but empty state.
245   245  
246   @param other The context to move from. 246   @param other The context to move from.
247   247  
248   @return Reference to this context. 248   @return Reference to this context.
249   */ 249   */
HITCBC 250   1 tls_context& operator=(tls_context&& other) noexcept = default; 250   1 tls_context& operator=(tls_context&& other) noexcept = default;
251   251  
252   /** Destructor. 252   /** Destructor.
253   253  
254   Releases this handle's shared ownership of the underlying 254   Releases this handle's shared ownership of the underlying
255   context. The context state is destroyed when the last handle 255   context. The context state is destroyed when the last handle
256   is released. 256   is released.
257   */ 257   */
HITCBC 258   36 ~tls_context() = default; 258   36 ~tls_context() = default;
259   259  
260   // 260   //
261   // Credential Loading 261   // Credential Loading
262   // 262   //
263   263  
264   /** Load the entity certificate from a memory buffer. 264   /** Load the entity certificate from a memory buffer.
265   265  
266   Sets the certificate that identifies this endpoint to the peer. 266   Sets the certificate that identifies this endpoint to the peer.
267   For servers, this is the server certificate. For clients using 267   For servers, this is the server certificate. For clients using
268   mutual TLS, this is the client certificate. 268   mutual TLS, this is the client certificate.
269   269  
270   The certificate must match the private key loaded via 270   The certificate must match the private key loaded via
271   `use_private_key()` or `use_private_key_file()`. 271   `use_private_key()` or `use_private_key_file()`.
272   272  
273   @param certificate The certificate data. 273   @param certificate The certificate data.
274   274  
275   @param format The encoding format of the certificate data. 275   @param format The encoding format of the certificate data.
276   276  
277   @return Success, or an error if the certificate could not be parsed 277   @return Success, or an error if the certificate could not be parsed
278   or is invalid. 278   or is invalid.
279   279  
280   @see use_certificate_file 280   @see use_certificate_file
281   @see use_private_key 281   @see use_private_key
282   */ 282   */
283   std::error_code 283   std::error_code
284   use_certificate(std::string_view certificate, tls_file_format format); 284   use_certificate(std::string_view certificate, tls_file_format format);
285   285  
286   /** Load the entity certificate from a file. 286   /** Load the entity certificate from a file.
287   287  
288   Sets the certificate that identifies this endpoint to the peer. 288   Sets the certificate that identifies this endpoint to the peer.
289   For servers, this is the server certificate. For clients using 289   For servers, this is the server certificate. For clients using
290   mutual TLS, this is the client certificate. 290   mutual TLS, this is the client certificate.
291   291  
292   @param filename Path to the certificate file. 292   @param filename Path to the certificate file.
293   293  
294   @param format The encoding format of the file. 294   @param format The encoding format of the file.
295   295  
296   @return Success, or an error if the file could not be read or the 296   @return Success, or an error if the file could not be read or the
297   certificate is invalid. 297   certificate is invalid.
298   298  
299   @par Example 299   @par Example
300   @code 300   @code
301   ctx.use_certificate_file( "server.crt", tls_file_format::pem ); 301   ctx.use_certificate_file( "server.crt", tls_file_format::pem );
302   @endcode 302   @endcode
303   303  
304   @see use_certificate 304   @see use_certificate
305   @see use_private_key_file 305   @see use_private_key_file
306   */ 306   */
307   std::error_code 307   std::error_code
308   use_certificate_file(std::string_view filename, tls_file_format format); 308   use_certificate_file(std::string_view filename, tls_file_format format);
309   309  
310   /** Load a certificate chain from a memory buffer. 310   /** Load a certificate chain from a memory buffer.
311   311  
312   Loads the entity certificate followed by intermediate CA certificates. 312   Loads the entity certificate followed by intermediate CA certificates.
313   The chain should be ordered from leaf to root (excluding the root). 313   The chain should be ordered from leaf to root (excluding the root).
314   This is the typical format for PEM certificate bundles. 314   This is the typical format for PEM certificate bundles.
315   315  
316   @param chain The certificate chain data in PEM format (concatenated 316   @param chain The certificate chain data in PEM format (concatenated
317   certificates). 317   certificates).
318   318  
319   @return Success, or an error if the chain could not be parsed. 319   @return Success, or an error if the chain could not be parsed.
320   320  
321   @see use_certificate_chain_file 321   @see use_certificate_chain_file
322   */ 322   */
323   std::error_code use_certificate_chain(std::string_view chain); 323   std::error_code use_certificate_chain(std::string_view chain);
324   324  
325   /** Load a certificate chain from a file. 325   /** Load a certificate chain from a file.
326   326  
327   Loads the entity certificate followed by intermediate CA certificates 327   Loads the entity certificate followed by intermediate CA certificates
328   from a PEM file. The file should contain concatenated PEM certificates 328   from a PEM file. The file should contain concatenated PEM certificates
329   ordered from leaf to root (excluding the root). 329   ordered from leaf to root (excluding the root).
330   330  
331   @param filename Path to the certificate chain file. 331   @param filename Path to the certificate chain file.
332   332  
333   @return Success, or an error if the file could not be read or parsed. 333   @return Success, or an error if the file could not be read or parsed.
334   334  
335   @par Example 335   @par Example
336   @code 336   @code
337   // Load certificate chain (cert + intermediates) 337   // Load certificate chain (cert + intermediates)
338   ctx.use_certificate_chain_file( "fullchain.pem" ); 338   ctx.use_certificate_chain_file( "fullchain.pem" );
339   @endcode 339   @endcode
340   340  
341   @see use_certificate_chain 341   @see use_certificate_chain
342   */ 342   */
343   std::error_code use_certificate_chain_file(std::string_view filename); 343   std::error_code use_certificate_chain_file(std::string_view filename);
344   344  
345   /** Load the private key from a memory buffer. 345   /** Load the private key from a memory buffer.
346   346  
347   Sets the private key corresponding to the entity certificate. 347   Sets the private key corresponding to the entity certificate.
348   The key must match the certificate loaded via `use_certificate()` 348   The key must match the certificate loaded via `use_certificate()`
349   or `use_certificate_chain()`. 349   or `use_certificate_chain()`.
350   350  
351   If the key is encrypted, set a password callback via 351   If the key is encrypted, set a password callback via
352   `set_password_callback()` before calling this function. 352   `set_password_callback()` before calling this function.
353   353  
354   @param private_key The private key data. 354   @param private_key The private key data.
355   355  
356   @param format The encoding format of the key data. 356   @param format The encoding format of the key data.
357   357  
358   @return Success, or an error if the key could not be parsed, 358   @return Success, or an error if the key could not be parsed,
359   is encrypted without a password callback, or doesn't match 359   is encrypted without a password callback, or doesn't match
360   the certificate. 360   the certificate.
361   361  
362   @see use_private_key_file 362   @see use_private_key_file
363   @see set_password_callback 363   @see set_password_callback
364   */ 364   */
365   std::error_code 365   std::error_code
366   use_private_key(std::string_view private_key, tls_file_format format); 366   use_private_key(std::string_view private_key, tls_file_format format);
367   367  
368   /** Load the private key from a file. 368   /** Load the private key from a file.
369   369  
370   Sets the private key corresponding to the entity certificate. 370   Sets the private key corresponding to the entity certificate.
371   The key must match the certificate loaded via `use_certificate_file()` 371   The key must match the certificate loaded via `use_certificate_file()`
372   or `use_certificate_chain_file()`. 372   or `use_certificate_chain_file()`.
373   373  
374   If the key file is encrypted, set a password callback via 374   If the key file is encrypted, set a password callback via
375   `set_password_callback()` before calling this function. 375   `set_password_callback()` before calling this function.
376   376  
377   @param filename Path to the private key file. 377   @param filename Path to the private key file.
378   378  
379   @param format The encoding format of the file. 379   @param format The encoding format of the file.
380   380  
381   @return Success, or an error if the file could not be read, 381   @return Success, or an error if the file could not be read,
382   the key is invalid, or it doesn't match the certificate. 382   the key is invalid, or it doesn't match the certificate.
383   383  
384   @par Example 384   @par Example
385   @code 385   @code
386   ctx.use_private_key_file( "server.key", tls_file_format::pem ); 386   ctx.use_private_key_file( "server.key", tls_file_format::pem );
387   @endcode 387   @endcode
388   388  
389   @see use_private_key 389   @see use_private_key
390   @see set_password_callback 390   @see set_password_callback
391   */ 391   */
392   std::error_code 392   std::error_code
393   use_private_key_file(std::string_view filename, tls_file_format format); 393   use_private_key_file(std::string_view filename, tls_file_format format);
394   394  
395   /** Load credentials from a PKCS#12 bundle in memory. 395   /** Load credentials from a PKCS#12 bundle in memory.
396   396  
397   PKCS#12 (also known as PFX) is a binary format that bundles a 397   PKCS#12 (also known as PFX) is a binary format that bundles a
398   certificate, private key, and optionally intermediate certificates 398   certificate, private key, and optionally intermediate certificates
399   into a single password-protected file. 399   into a single password-protected file.
400   400  
401   @param data The PKCS#12 bundle data. 401   @param data The PKCS#12 bundle data.
402   402  
403   @param passphrase The password protecting the bundle. 403   @param passphrase The password protecting the bundle.
404   404  
405   @return Success, or an error if the bundle could not be parsed 405   @return Success, or an error if the bundle could not be parsed
406   or the passphrase is incorrect. 406   or the passphrase is incorrect.
407   407  
408   @see use_pkcs12_file 408   @see use_pkcs12_file
409   */ 409   */
410   std::error_code 410   std::error_code
411   use_pkcs12(std::string_view data, std::string_view passphrase); 411   use_pkcs12(std::string_view data, std::string_view passphrase);
412   412  
413   /** Load credentials from a PKCS#12 file. 413   /** Load credentials from a PKCS#12 file.
414   414  
415   PKCS#12 (also known as PFX) is a binary format that bundles a 415   PKCS#12 (also known as PFX) is a binary format that bundles a
416   certificate, private key, and optionally intermediate certificates 416   certificate, private key, and optionally intermediate certificates
417   into a single password-protected file. This is common on Windows 417   into a single password-protected file. This is common on Windows
418   and for certificates exported from browsers. 418   and for certificates exported from browsers.
419   419  
420   @param filename Path to the PKCS#12 file. 420   @param filename Path to the PKCS#12 file.
421   421  
422   @param passphrase The password protecting the file. 422   @param passphrase The password protecting the file.
423   423  
424   @return Success, or an error if the file could not be read, 424   @return Success, or an error if the file could not be read,
425   parsed, or the passphrase is incorrect. 425   parsed, or the passphrase is incorrect.
426   426  
427   @par Example 427   @par Example
428   @code 428   @code
429   ctx.use_pkcs12_file( "credentials.pfx", "secret" ); 429   ctx.use_pkcs12_file( "credentials.pfx", "secret" );
430   @endcode 430   @endcode
431   431  
432   @see use_pkcs12 432   @see use_pkcs12
433   */ 433   */
434   std::error_code 434   std::error_code
435   use_pkcs12_file(std::string_view filename, std::string_view passphrase); 435   use_pkcs12_file(std::string_view filename, std::string_view passphrase);
436   436  
437   // 437   //
438   // Trust Anchors 438   // Trust Anchors
439   // 439   //
440   440  
441   /** Add a certificate authority for peer verification. 441   /** Add a certificate authority for peer verification.
442   442  
443   Adds a single CA certificate to the trust store used for verifying 443   Adds a single CA certificate to the trust store used for verifying
444   peer certificates. Call this multiple times to add multiple CAs, 444   peer certificates. Call this multiple times to add multiple CAs,
445   or use `load_verify_file()` for a bundle. 445   or use `load_verify_file()` for a bundle.
446   446  
447   @param ca The CA certificate data in PEM format. 447   @param ca The CA certificate data in PEM format.
448   448  
449   @return Success, or an error if the certificate could not be parsed. 449   @return Success, or an error if the certificate could not be parsed.
450   450  
451   @see load_verify_file 451   @see load_verify_file
452   @see set_default_verify_paths 452   @see set_default_verify_paths
453   */ 453   */
454   std::error_code add_certificate_authority(std::string_view ca); 454   std::error_code add_certificate_authority(std::string_view ca);
455   455  
456   /** Load CA certificates from a file. 456   /** Load CA certificates from a file.
457   457  
458   Loads one or more CA certificates from a PEM file. The file may 458   Loads one or more CA certificates from a PEM file. The file may
459   contain multiple concatenated PEM certificates. 459   contain multiple concatenated PEM certificates.
460   460  
461   @param filename Path to a PEM file containing CA certificates. 461   @param filename Path to a PEM file containing CA certificates.
462   462  
463   @return Success, or an error if the file could not be read or parsed. 463   @return Success, or an error if the file could not be read or parsed.
464   464  
465   @par Example 465   @par Example
466   @code 466   @code
467   // Load a custom CA bundle 467   // Load a custom CA bundle
468   ctx.load_verify_file( "/etc/ssl/certs/ca-certificates.crt" ); 468   ctx.load_verify_file( "/etc/ssl/certs/ca-certificates.crt" );
469   @endcode 469   @endcode
470   470  
471   @see add_certificate_authority 471   @see add_certificate_authority
472   @see add_verify_path 472   @see add_verify_path
473   */ 473   */
474   std::error_code load_verify_file(std::string_view filename); 474   std::error_code load_verify_file(std::string_view filename);
475   475  
476   /** Add a directory of CA certificates for verification. 476   /** Add a directory of CA certificates for verification.
477   477  
478   Adds a directory containing CA certificate files. Each file must 478   Adds a directory containing CA certificate files. Each file must
479   contain a single certificate in PEM format, named using the 479   contain a single certificate in PEM format, named using the
480   subject name hash (as generated by `openssl rehash` or 480   subject name hash (as generated by `openssl rehash` or
481   `c_rehash`). 481   `c_rehash`).
482   482  
483   @param path Path to the directory containing hashed CA certificates. 483   @param path Path to the directory containing hashed CA certificates.
484   484  
485   @return Success, or an error if the directory is invalid. 485   @return Success, or an error if the directory is invalid.
486   486  
487   @par Example 487   @par Example
488   @code 488   @code
489   ctx.add_verify_path( "/etc/ssl/certs" ); 489   ctx.add_verify_path( "/etc/ssl/certs" );
490   @endcode 490   @endcode
491   491  
492   @see load_verify_file 492   @see load_verify_file
493   @see set_default_verify_paths 493   @see set_default_verify_paths
494   */ 494   */
495   std::error_code add_verify_path(std::string_view path); 495   std::error_code add_verify_path(std::string_view path);
496   496  
497   /** Use the system default CA certificate store. 497   /** Use the system default CA certificate store.
498   498  
499   Configures the context to use the operating system's default 499   Configures the context to use the operating system's default
500   trust store for peer certificate verification. This is the 500   trust store for peer certificate verification. This is the
501   recommended approach for HTTPS clients connecting to public 501   recommended approach for HTTPS clients connecting to public
502   servers. 502   servers.
503   503  
504   On different platforms this uses: 504   On different platforms this uses:
505   - Linux: `/etc/ssl/certs` or distribution-specific paths 505   - Linux: `/etc/ssl/certs` or distribution-specific paths
506   - macOS: System Keychain 506   - macOS: System Keychain
507   - Windows: Windows Certificate Store 507   - Windows: Windows Certificate Store
508   508  
509   @return Success, or an error if the system store could not be loaded. 509   @return Success, or an error if the system store could not be loaded.
510   510  
511   @par Example 511   @par Example
512   @code 512   @code
513   // Trust the same CAs as the system 513   // Trust the same CAs as the system
514   ctx.set_default_verify_paths(); 514   ctx.set_default_verify_paths();
515   @endcode 515   @endcode
516   516  
517   @see load_verify_file 517   @see load_verify_file
518   @see add_verify_path 518   @see add_verify_path
519   */ 519   */
520   std::error_code set_default_verify_paths(); 520   std::error_code set_default_verify_paths();
521   521  
522   // 522   //
523   // Protocol Configuration 523   // Protocol Configuration
524   // 524   //
525   525  
526   /** Set the minimum TLS protocol version. 526   /** Set the minimum TLS protocol version.
527   527  
528   Connections will reject protocol versions older than this. 528   Connections will reject protocol versions older than this.
529   The default allows TLS 1.2 and newer. 529   The default allows TLS 1.2 and newer.
530   530  
531   @param v The minimum protocol version to accept. 531   @param v The minimum protocol version to accept.
532   532  
533   @return Success, or an error if the version is not supported 533   @return Success, or an error if the version is not supported
534   by the backend. 534   by the backend.
535   535  
536   @par Example 536   @par Example
537   @code 537   @code
538   // Require TLS 1.3 minimum 538   // Require TLS 1.3 minimum
539   ctx.set_min_protocol_version( tls_version::tls_1_3 ); 539   ctx.set_min_protocol_version( tls_version::tls_1_3 );
540   @endcode 540   @endcode
541   541  
542   @see set_max_protocol_version 542   @see set_max_protocol_version
543   */ 543   */
544   std::error_code set_min_protocol_version(tls_version v); 544   std::error_code set_min_protocol_version(tls_version v);
545   545  
546   /** Set the maximum TLS protocol version. 546   /** Set the maximum TLS protocol version.
547   547  
548   Connections will not negotiate protocol versions newer than this. 548   Connections will not negotiate protocol versions newer than this.
549   The default allows the newest supported version. 549   The default allows the newest supported version.
550   550  
551   @param v The maximum protocol version to accept. 551   @param v The maximum protocol version to accept.
552   552  
553   @return Success, or an error if the version is not supported 553   @return Success, or an error if the version is not supported
554   by the backend. 554   by the backend.
555   555  
556   @see set_min_protocol_version 556   @see set_min_protocol_version
557   */ 557   */
558   std::error_code set_max_protocol_version(tls_version v); 558   std::error_code set_max_protocol_version(tls_version v);
559   559  
560   /** Set the allowed cipher suites. 560   /** Set the allowed cipher suites.
561   561  
562   Configures which cipher suites may be used for connections. 562   Configures which cipher suites may be used for connections.
563   The format is backend-specific but typically follows OpenSSL 563   The format is backend-specific but typically follows OpenSSL
564   cipher list syntax. 564   cipher list syntax.
565   565  
566   @param ciphers The cipher suite specification string. 566   @param ciphers The cipher suite specification string.
567   567  
568   @return Success, or an error if the cipher string is invalid. 568   @return Success, or an error if the cipher string is invalid.
569   569  
570   @par Example 570   @par Example
571   @code 571   @code
572   // TLS 1.2 cipher suites (OpenSSL format) 572   // TLS 1.2 cipher suites (OpenSSL format)
573   ctx.set_ciphersuites( "ECDHE+AESGCM:ECDHE+CHACHA20" ); 573   ctx.set_ciphersuites( "ECDHE+AESGCM:ECDHE+CHACHA20" );
574   @endcode 574   @endcode
575   575  
576   @note For TLS 1.3, use `set_ciphersuites_tls13()` on backends 576   @note For TLS 1.3, use `set_ciphersuites_tls13()` on backends
577   that distinguish between TLS 1.2 and 1.3 cipher configuration. 577   that distinguish between TLS 1.2 and 1.3 cipher configuration.
578   */ 578   */
579   std::error_code set_ciphersuites(std::string_view ciphers); 579   std::error_code set_ciphersuites(std::string_view ciphers);
580   580  
581   /** Set the ALPN protocol list. 581   /** Set the ALPN protocol list.
582   582  
583   Configures Application-Layer Protocol Negotiation (ALPN) for 583   Configures Application-Layer Protocol Negotiation (ALPN) for
584   the connection. ALPN is used to negotiate which application 584   the connection. ALPN is used to negotiate which application
585   protocol to use over the TLS connection (e.g., "h2" for HTTP/2, 585   protocol to use over the TLS connection (e.g., "h2" for HTTP/2,
586   "http/1.1" for HTTP/1.1). 586   "http/1.1" for HTTP/1.1).
587   587  
588   The protocols are tried in preference order (first = highest). 588   The protocols are tried in preference order (first = highest).
589   589  
590   @param protocols Ordered list of protocol identifiers. 590   @param protocols Ordered list of protocol identifiers.
591   591  
592   @return Success, or an error if ALPN configuration fails. 592   @return Success, or an error if ALPN configuration fails.
593   593  
594   @par Example 594   @par Example
595   @code 595   @code
596   // Prefer HTTP/2, fall back to HTTP/1.1 596   // Prefer HTTP/2, fall back to HTTP/1.1
597   ctx.set_alpn( { "h2", "http/1.1" } ); 597   ctx.set_alpn( { "h2", "http/1.1" } );
598   @endcode 598   @endcode
599   */ 599   */
600   std::error_code set_alpn(std::initializer_list<std::string_view> protocols); 600   std::error_code set_alpn(std::initializer_list<std::string_view> protocols);
601   601  
602   // 602   //
603   // Certificate Verification 603   // Certificate Verification
604   // 604   //
605   605  
606   /** Set the peer certificate verification mode. 606   /** Set the peer certificate verification mode.
607   607  
608   Controls whether and how peer certificates are verified during 608   Controls whether and how peer certificates are verified during
609   the TLS handshake. 609   the TLS handshake.
610   610  
611   @param mode The verification mode to use. 611   @param mode The verification mode to use.
612   612  
613   @return Success, or an error if the mode could not be set. 613   @return Success, or an error if the mode could not be set.
614   614  
615   @par Example 615   @par Example
616   @code 616   @code
617   // Verify peer certificate (typical for clients) 617   // Verify peer certificate (typical for clients)
618   ctx.set_verify_mode( tls_verify_mode::peer ); 618   ctx.set_verify_mode( tls_verify_mode::peer );
619   619  
620   // Require client certificate (server-side mTLS) 620   // Require client certificate (server-side mTLS)
621   ctx.set_verify_mode( tls_verify_mode::require_peer ); 621   ctx.set_verify_mode( tls_verify_mode::require_peer );
622   @endcode 622   @endcode
623   623  
624   @see tls_verify_mode 624   @see tls_verify_mode
625   */ 625   */
626   std::error_code set_verify_mode(tls_verify_mode mode); 626   std::error_code set_verify_mode(tls_verify_mode mode);
627   627  
628   /** Set the maximum certificate chain verification depth. 628   /** Set the maximum certificate chain verification depth.
629   629  
630   Limits how many intermediate certificates can appear between 630   Limits how many intermediate certificates can appear between
631   the peer certificate and a trusted root. The default is 631   the peer certificate and a trusted root. The default is
632   typically 100, which is sufficient for most certificate chains. 632   typically 100, which is sufficient for most certificate chains.
633   633  
634   @param depth Maximum number of intermediate certificates allowed. 634   @param depth Maximum number of intermediate certificates allowed.
635   635  
636   @return Success, or an error if the depth is invalid. 636   @return Success, or an error if the depth is invalid.
637   */ 637   */
638   std::error_code set_verify_depth(int depth); 638   std::error_code set_verify_depth(int depth);
639   639  
640   /** Set a custom certificate verification callback. 640   /** Set a custom certificate verification callback.
641   641  
642   Installs a callback that is invoked during certificate chain 642   Installs a callback that is invoked during certificate chain
643   verification. The callback can perform additional validation 643   verification. The callback can perform additional validation
644   beyond the standard checks and can override verification 644   beyond the standard checks and can override verification
645   results. 645   results.
646   646  
647   The callback receives the verification result so far and 647   The callback receives the verification result so far and
648   information about the certificate being verified. Return 648   information about the certificate being verified. Return
649   `true` to accept the certificate, `false` to reject. 649   `true` to accept the certificate, `false` to reject.
650   650  
651   @tparam Callback A callable with signature 651   @tparam Callback A callable with signature
652   `bool( bool preverified, verify_context& ctx )`. 652   `bool( bool preverified, verify_context& ctx )`.
653   653  
654   @param callback The verification callback. 654   @param callback The verification callback.
655   655  
656   @return Success, or an error if the callback could not be set. 656   @return Success, or an error if the callback could not be set.
657   657  
658   @note The `verify_context` type provides access to the 658   @note The `verify_context` type provides access to the
659   certificate and chain information. Its exact interface 659   certificate and chain information. Its exact interface
660   depends on the TLS backend. 660   depends on the TLS backend.
661   */ 661   */
662   template<typename Callback> 662   template<typename Callback>
663   std::error_code set_verify_callback(Callback callback); 663   std::error_code set_verify_callback(Callback callback);
664   664  
665   /** Set the expected server hostname for verification. 665   /** Set the expected server hostname for verification.
666   666  
667   For client connections, sets the hostname that the server 667   For client connections, sets the hostname that the server
668   certificate must match. This enables: 668   certificate must match. This enables:
669   669  
670   1. SNI (Server Name Indication) — tells the server which 670   1. SNI (Server Name Indication) — tells the server which
671   certificate to present (for virtual hosting) 671   certificate to present (for virtual hosting)
672   2. Hostname verification — validates the certificate's 672   2. Hostname verification — validates the certificate's
673   Subject Alternative Name or Common Name matches 673   Subject Alternative Name or Common Name matches
674   674  
675   @param hostname The expected server hostname. 675   @param hostname The expected server hostname.
676   676  
677   @par Example 677   @par Example
678   @code 678   @code
679   ctx.set_hostname( "api.example.com" ); 679   ctx.set_hostname( "api.example.com" );
680   @endcode 680   @endcode
681   681  
682   @note This is typically required for HTTPS clients to ensure 682   @note This is typically required for HTTPS clients to ensure
683   they're connecting to the intended server. 683   they're connecting to the intended server.
684   */ 684   */
685   void set_hostname(std::string_view hostname); 685   void set_hostname(std::string_view hostname);
686   686  
687   /** Set a callback for Server Name Indication (SNI). 687   /** Set a callback for Server Name Indication (SNI).
688   688  
689   For server connections, this callback is invoked during the TLS 689   For server connections, this callback is invoked during the TLS
690   handshake when a client sends an SNI extension. The callback 690   handshake when a client sends an SNI extension. The callback
691   receives the requested hostname and can accept or reject the 691   receives the requested hostname and can accept or reject the
692   connection. 692   connection.
693   693  
694   @tparam Callback A callable with signature 694   @tparam Callback A callable with signature
695   `bool( std::string_view hostname )`. 695   `bool( std::string_view hostname )`.
696   696  
697   @param callback The SNI callback. Return `true` to accept the 697   @param callback The SNI callback. Return `true` to accept the
698   connection or `false` to reject it with an alert. 698   connection or `false` to reject it with an alert.
699   699  
700   @par Example 700   @par Example
701   @code 701   @code
702   // Accept connections for specific domains only 702   // Accept connections for specific domains only
703   ctx.set_servername_callback( 703   ctx.set_servername_callback(
704   []( std::string_view hostname ) -> bool 704   []( std::string_view hostname ) -> bool
705   { 705   {
706   return hostname == "api.example.com" || 706   return hostname == "api.example.com" ||
707   hostname == "www.example.com"; 707   hostname == "www.example.com";
708   }); 708   });
709   @endcode 709   @endcode
710   710  
711   @note For virtual hosting with different certificates per hostname, 711   @note For virtual hosting with different certificates per hostname,
712   create separate contexts and select the appropriate one before 712   create separate contexts and select the appropriate one before
713   creating the TLS stream. 713   creating the TLS stream.
714   714  
715   @see set_hostname 715   @see set_hostname
716   */ 716   */
717   template<typename Callback> 717   template<typename Callback>
718   void set_servername_callback(Callback callback); 718   void set_servername_callback(Callback callback);
719   719  
720   private: 720   private:
721   void set_servername_callback_impl( 721   void set_servername_callback_impl(
722   std::function<bool(std::string_view)> callback); 722   std::function<bool(std::string_view)> callback);
723   723  
724   void set_password_callback_impl( 724   void set_password_callback_impl(
725   std::function<std::string(std::size_t, tls_password_purpose)> callback); 725   std::function<std::string(std::size_t, tls_password_purpose)> callback);
726   726  
727   public: 727   public:
728   // 728   //
729   // Revocation Checking 729   // Revocation Checking
730   // 730   //
731   731  
732   /** Add a Certificate Revocation List from memory. 732   /** Add a Certificate Revocation List from memory.
733   733  
734   Adds a CRL to the verification store for checking whether 734   Adds a CRL to the verification store for checking whether
735   certificates have been revoked. CRLs are typically fetched 735   certificates have been revoked. CRLs are typically fetched
736   from the URLs in a certificate's CRL Distribution Points 736   from the URLs in a certificate's CRL Distribution Points
737   extension. 737   extension.
738   738  
739   @param crl The CRL data in DER or PEM format. 739   @param crl The CRL data in DER or PEM format.
740   740  
741   @return Success, or an error if the CRL could not be parsed. 741   @return Success, or an error if the CRL could not be parsed.
742   742  
743   @see add_crl_file 743   @see add_crl_file
744   @see set_revocation_policy 744   @see set_revocation_policy
745   */ 745   */
746   std::error_code add_crl(std::string_view crl); 746   std::error_code add_crl(std::string_view crl);
747   747  
748   /** Add a Certificate Revocation List from a file. 748   /** Add a Certificate Revocation List from a file.
749   749  
750   Adds a CRL to the verification store for checking whether 750   Adds a CRL to the verification store for checking whether
751   certificates have been revoked. 751   certificates have been revoked.
752   752  
753   @param filename Path to a CRL file (DER or PEM format). 753   @param filename Path to a CRL file (DER or PEM format).
754   754  
755   @return Success, or an error if the file could not be read 755   @return Success, or an error if the file could not be read
756   or the CRL is invalid. 756   or the CRL is invalid.
757   757  
758   @par Example 758   @par Example
759   @code 759   @code
760   ctx.add_crl_file( "issuer.crl" ); 760   ctx.add_crl_file( "issuer.crl" );
761   @endcode 761   @endcode
762   762  
763   @see add_crl 763   @see add_crl
764   @see set_revocation_policy 764   @see set_revocation_policy
765   */ 765   */
766   std::error_code add_crl_file(std::string_view filename); 766   std::error_code add_crl_file(std::string_view filename);
767   767  
768   /** Set the OCSP staple response for server-side stapling. 768   /** Set the OCSP staple response for server-side stapling.
769   769  
770   For servers, provides a pre-fetched OCSP response to send 770   For servers, provides a pre-fetched OCSP response to send
771   to clients during the handshake. This proves the server's 771   to clients during the handshake. This proves the server's
772   certificate hasn't been revoked without requiring the client 772   certificate hasn't been revoked without requiring the client
773   to contact the OCSP responder. 773   to contact the OCSP responder.
774   774  
775   The OCSP response must be periodically refreshed (typically 775   The OCSP response must be periodically refreshed (typically
776   every few hours to days) before it expires. 776   every few hours to days) before it expires.
777   777  
778   @param response The DER-encoded OCSP response. 778   @param response The DER-encoded OCSP response.
779   779  
780   @return Success, or an error if the response is invalid. 780   @return Success, or an error if the response is invalid.
781   781  
782   @note This is a server-side operation. Clients use 782   @note This is a server-side operation. Clients use
783   `set_require_ocsp_staple()` to require stapled responses. 783   `set_require_ocsp_staple()` to require stapled responses.
784   */ 784   */
785   std::error_code set_ocsp_staple(std::string_view response); 785   std::error_code set_ocsp_staple(std::string_view response);
786   786  
787   /** Require OCSP stapling from the server. 787   /** Require OCSP stapling from the server.
788   788  
789   For clients, requires the server to provide a stapled OCSP 789   For clients, requires the server to provide a stapled OCSP
790   response proving its certificate hasn't been revoked. If 790   response proving its certificate hasn't been revoked. If
791   the server doesn't provide a stapled response, the handshake 791   the server doesn't provide a stapled response, the handshake
792   fails. 792   fails.
793   793  
794   @param require Whether to require OCSP stapling. 794   @param require Whether to require OCSP stapling.
795   795  
796   @note Not all servers support OCSP stapling. Enable this only 796   @note Not all servers support OCSP stapling. Enable this only
797   when connecting to servers known to support it. 797   when connecting to servers known to support it.
798   */ 798   */
799   void set_require_ocsp_staple(bool require); 799   void set_require_ocsp_staple(bool require);
800   800  
801   /** Set the certificate revocation checking policy. 801   /** Set the certificate revocation checking policy.
802   802  
803   Controls how certificate revocation status is checked during 803   Controls how certificate revocation status is checked during
804   verification. This affects both CRL and OCSP checking. 804   verification. This affects both CRL and OCSP checking.
805   805  
806   @param policy The revocation checking policy. 806   @param policy The revocation checking policy.
807   807  
808   @par Example 808   @par Example
809   @code 809   @code
810   // Require successful revocation check 810   // Require successful revocation check
811   ctx.set_revocation_policy( tls_revocation_policy::hard_fail ); 811   ctx.set_revocation_policy( tls_revocation_policy::hard_fail );
812   812  
813   // Check but allow unknown status 813   // Check but allow unknown status
814   ctx.set_revocation_policy( tls_revocation_policy::soft_fail ); 814   ctx.set_revocation_policy( tls_revocation_policy::soft_fail );
815   @endcode 815   @endcode
816   816  
817   @see tls_revocation_policy 817   @see tls_revocation_policy
818   @see add_crl 818   @see add_crl
819   */ 819   */
820   void set_revocation_policy(tls_revocation_policy policy); 820   void set_revocation_policy(tls_revocation_policy policy);
821   821  
822   // 822   //
823   // Password Handling 823   // Password Handling
824   // 824   //
825   825  
826   /** Set the password callback for encrypted keys. 826   /** Set the password callback for encrypted keys.
827   827  
828   Installs a callback that provides passwords for encrypted 828   Installs a callback that provides passwords for encrypted
829   private keys and PKCS#12 files. The callback is invoked when 829   private keys and PKCS#12 files. The callback is invoked when
830   loading encrypted key material. 830   loading encrypted key material.
831   831  
832   @tparam Callback A callable with signature 832   @tparam Callback A callable with signature
833   `std::string( std::size_t max_length, password_purpose purpose )`. 833   `std::string( std::size_t max_length, password_purpose purpose )`.
834   834  
835   @param callback The password callback. It receives the maximum 835   @param callback The password callback. It receives the maximum
836   password length and the purpose (reading or writing), and 836   password length and the purpose (reading or writing), and
837   returns the password string. 837   returns the password string.
838   838  
839   @par Example 839   @par Example
840   @code 840   @code
841   ctx.set_password_callback( 841   ctx.set_password_callback(
842   []( std::size_t max_len, tls_password_purpose purpose ) 842   []( std::size_t max_len, tls_password_purpose purpose )
843   { 843   {
844   // In practice, prompt user or read from secure storage 844   // In practice, prompt user or read from secure storage
845   return std::string( "my-key-password" ); 845   return std::string( "my-key-password" );
846   }); 846   });
847   847  
848   // Now load encrypted key 848   // Now load encrypted key
849   ctx.use_private_key_file( "encrypted.key", tls_file_format::pem ); 849   ctx.use_private_key_file( "encrypted.key", tls_file_format::pem );
850   @endcode 850   @endcode
851   851  
852   @see tls_password_purpose 852   @see tls_password_purpose
853   */ 853   */
854   template<typename Callback> 854   template<typename Callback>
855   void set_password_callback(Callback callback); 855   void set_password_callback(Callback callback);
856   }; 856   };
857   #ifdef _MSC_VER 857   #ifdef _MSC_VER
858   #pragma warning(pop) 858   #pragma warning(pop)
859   #endif 859   #endif
860   860  
861   template<typename Callback> 861   template<typename Callback>
862   void 862   void
HITCBC 863   1 tls_context::set_servername_callback(Callback callback) 863   1 tls_context::set_servername_callback(Callback callback)
864   { 864   {
HITCBC 865   1 set_servername_callback_impl(std::move(callback)); 865   1 set_servername_callback_impl(std::move(callback));
HITCBC 866   1 } 866   1 }
867   867  
868   template<typename Callback> 868   template<typename Callback>
869   void 869   void
HITCBC 870   1 tls_context::set_password_callback(Callback callback) 870   1 tls_context::set_password_callback(Callback callback)
871   { 871   {
HITCBC 872   1 set_password_callback_impl(std::move(callback)); 872   1 set_password_callback_impl(std::move(callback));
HITCBC 873   1 } 873   1 }
874   874  
875   } // namespace boost::corosio 875   } // namespace boost::corosio
876   876  
877   #endif 877   #endif