Botan  2.13.0
Crypto and TLS for C++11
asio_stream.h
Go to the documentation of this file.
1 /*
2 * TLS ASIO Stream
3 * (C) 2018-2019 Jack Lloyd
4 * 2018-2019 Hannes Rantzsch, Tim Oesterreich, Rene Meusel
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #ifndef BOTAN_ASIO_STREAM_H_
10 #define BOTAN_ASIO_STREAM_H_
11 
12 #include <botan/build.h>
13 
14 // first version to be compatible with Networking TS (N4656) and boost::beast
15 #include <boost/version.hpp>
16 #if BOOST_VERSION >= 106600
17 
18 #include <botan/asio_async_ops.h>
19 #include <botan/asio_context.h>
20 #include <botan/asio_error.h>
21 
22 #include <botan/tls_callbacks.h>
23 #include <botan/tls_channel.h>
24 #include <botan/tls_client.h>
25 #include <botan/tls_magic.h>
26 
27 // We need to define BOOST_ASIO_DISABLE_SERIAL_PORT before any asio imports. Otherwise asio will include <termios.h>,
28 // which interferes with Botan's amalgamation by defining macros like 'B0' and 'FF1'.
29 #define BOOST_ASIO_DISABLE_SERIAL_PORT
30 #include <boost/asio.hpp>
31 #include <boost/beast/core/flat_buffer.hpp>
32 
33 #include <algorithm>
34 #include <memory>
35 #include <type_traits>
36 
37 namespace Botan {
38 namespace TLS {
39 
40 /**
41  * @brief boost::asio compatible SSL/TLS stream
42  *
43  * Currently only the TLS::Client specialization is implemented.
44  *
45  * @tparam StreamLayer type of the next layer, usually a network socket
46  * @tparam ChannelT type of the native_handle, defaults to Botan::TLS::Channel, only needed for testing purposes
47  */
48 template <class StreamLayer, class ChannelT = Channel>
49 class Stream
50  {
51  public:
52  //! \name construction
53  //! @{
54 
55  /**
56  * @brief Construct a new Stream
57  *
58  * @param context The context parameter is used to set up the underlying native handle. Using code is
59  * responsible for lifetime management of the context and must ensure that it is available for the
60  * lifetime of the stream.
61  * @param args Arguments to be forwarded to the construction of the next layer.
62  */
63  template <typename... Args>
64  explicit Stream(Context& context, Args&& ... args)
65  : m_context(context)
66  , m_nextLayer(std::forward<Args>(args)...)
70  {}
71 
72  /**
73  * @brief Construct a new Stream
74  *
75  * Convenience overload for boost::asio::ssl::stream compatibility.
76  *
77  * @param arg This argument is forwarded to the construction of the next layer.
78  * @param context The context parameter is used to set up the underlying native handle. Using code is
79  * responsible for lifetime management of the context and must ensure that is available for the
80  * lifetime of the stream.
81  */
82  template <typename Arg>
83  explicit Stream(Arg&& arg, Context& context)
84  : m_context(context)
85  , m_nextLayer(std::forward<Arg>(arg))
89  {}
90 
91  virtual ~Stream() = default;
92 
93  Stream(Stream&& other) = default;
94  Stream& operator=(Stream&& other) = default;
95 
96  Stream(const Stream& other) = delete;
97  Stream& operator=(const Stream& other) = delete;
98 
99  //! @}
100  //! \name boost::asio accessor methods
101  //! @{
102 
104  using lowest_layer_type = typename next_layer_type::lowest_layer_type;
105  using executor_type = typename next_layer_type::executor_type;
107 
108  executor_type get_executor() noexcept { return m_nextLayer.get_executor(); }
109 
110  const next_layer_type& next_layer() const { return m_nextLayer; }
112 
113  lowest_layer_type& lowest_layer() { return m_nextLayer.lowest_layer(); }
114  const lowest_layer_type& lowest_layer() const { return m_nextLayer.lowest_layer(); }
115 
117 
118  //! @}
119  //! \name configuration and callback setters
120  //! @{
121 
122  /**
123  * @brief Override the tls_verify_cert_chain callback
124  *
125  * This changes the verify_callback in the stream's TLS::Context, and hence the tls_verify_cert_chain callback
126  * used in the handshake.
127  * Using this function is equivalent to setting the callback via @see Botan::TLS::Context::set_verify_callback
128  *
129  * @note This function should only be called before initiating the TLS handshake
130  */
132  {
133  m_context.set_verify_callback(std::move(callback));
134  }
135 
136  /**
137  * @brief Compatibility overload of @ref set_verify_callback
138  *
139  * @param callback the callback implementation
140  * @param ec This parameter is unused.
141  */
142  void set_verify_callback(Context::Verify_Callback callback, boost::system::error_code& ec)
143  {
144  BOTAN_UNUSED(ec);
145  m_context.set_verify_callback(std::move(callback));
146  }
147 
148  //! @throws Not_Implemented
149  void set_verify_depth(int depth)
150  {
151  BOTAN_UNUSED(depth);
152  throw Not_Implemented("set_verify_depth is not implemented");
153  }
154 
155  /**
156  * Not Implemented.
157  * @param depth the desired verification depth
158  * @param ec Will be set to `Botan::ErrorType::NotImplemented`
159  */
160  void set_verify_depth(int depth, boost::system::error_code& ec)
161  {
162  BOTAN_UNUSED(depth);
164  }
165 
166  //! @throws Not_Implemented
167  template <typename verify_mode>
168  void set_verify_mode(verify_mode v)
169  {
170  BOTAN_UNUSED(v);
171  throw Not_Implemented("set_verify_mode is not implemented");
172  }
173 
174  /**
175  * Not Implemented.
176  * @param v the desired verify mode
177  * @param ec Will be set to `Botan::ErrorType::NotImplemented`
178  */
179  template <typename verify_mode>
180  void set_verify_mode(verify_mode v, boost::system::error_code& ec)
181  {
182  BOTAN_UNUSED(v);
184  }
185 
186  //! @}
187  //! \name handshake methods
188  //! @{
189 
190  /**
191  * @brief Performs SSL handshaking.
192  *
193  * The function call will block until handshaking is complete or an error occurs.
194  *
195  * @param side The type of handshaking to be performed, i.e. as a client or as a server.
196  * @throws boost::system::system_error if error occured, or if the chosen Connection_Side is not available
197  */
199  {
200  boost::system::error_code ec;
201  handshake(side, ec);
202  boost::asio::detail::throw_error(ec, "handshake");
203  }
204 
205  /**
206  * @brief Performs SSL handshaking.
207  *
208  * The function call will block until handshaking is complete or an error occurs.
209  *
210  * @param side The type of handshaking to be performed, i.e. as a client or as a server.
211  * @param ec Set to indicate what error occurred, if any.
212  */
213  void handshake(Connection_Side side, boost::system::error_code& ec)
214  {
215  setup_native_handle(side, ec);
216 
217  // send client hello, which was written to the send buffer on client instantiation
219 
220  while(!native_handle()->is_active() && !ec)
221  {
222  boost::asio::const_buffer read_buffer{input_buffer().data(), m_nextLayer.read_some(input_buffer(), ec)};
223  if(ec)
224  { return; }
225 
226  try
227  {
228  native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), read_buffer.size());
229  }
230  catch(const TLS_Exception& e)
231  {
232  ec = e.type();
233  }
234  catch(const Botan::Exception& e)
235  {
236  ec = e.error_type();
237  }
238  catch(const std::exception&)
239  {
241  }
242 
244  }
245  }
246 
247  /**
248  * @brief Starts an asynchronous SSL handshake.
249  *
250  * This function call always returns immediately.
251  *
252  * @param side The type of handshaking to be performed, i.e. as a client or as a server.
253  * @param handler The handler to be called when the handshake operation completes.
254  * The equivalent function signature of the handler must be: void(boost::system::error_code)
255  * @throws NotImplemented if Connection_Side is not CLIENT
256  */
257  template <typename HandshakeHandler>
258  auto async_handshake(Connection_Side side, HandshakeHandler&& handler) ->
259  BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code))
260  {
261  BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
262 
263  boost::system::error_code ec;
264  setup_native_handle(side, ec);
265  // If ec is set by setup_native_handle, the AsyncHandshakeOperation created below will do nothing but call the
266  // handler with the error_code set appropriately - no need to early return here.
267 
268  boost::asio::async_completion<HandshakeHandler, void(boost::system::error_code)> init(handler);
269 
271  op{std::move(init.completion_handler), *this, ec};
272 
273  return init.result.get();
274  }
275 
276  //! @throws Not_Implemented
277  template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
278  BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
279  void(boost::system::error_code, std::size_t))
280  async_handshake(Connection_Side side, const ConstBufferSequence& buffers,
281  BufferedHandshakeHandler&& handler)
282  {
283  BOTAN_UNUSED(side, buffers, handler);
284  BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(BufferedHandshakeHandler, handler) type_check;
285  throw Not_Implemented("buffered async handshake is not implemented");
286  }
287 
288  //! @}
289  //! \name shutdown methods
290  //! @{
291 
292  /**
293  * @brief Shut down SSL on the stream.
294  *
295  * This function is used to shut down SSL on the stream. The function call will block until SSL has been shut down
296  * or an error occurs. Note that this will not close the lowest layer.
297  *
298  * @param ec Set to indicate what error occured, if any.
299  */
300  void shutdown(boost::system::error_code& ec)
301  {
302  try
303  {
304  native_handle()->close();
305  }
306  catch(const TLS_Exception& e)
307  {
308  ec = e.type();
309  }
310  catch(const Botan::Exception& e)
311  {
312  ec = e.error_type();
313  }
314  catch(const std::exception&)
315  {
317  }
318 
319  if(!ec)
321  }
322 
323  /**
324  * @brief Shut down SSL on the stream.
325  *
326  * This function is used to shut down SSL on the stream. The function call will block until SSL has been shut down
327  * or an error occurs. Note that this will not close the lowest layer.
328  *
329  * @throws boost::system::system_error if error occured
330  */
331  void shutdown()
332  {
333  boost::system::error_code ec;
334  shutdown(ec);
335  boost::asio::detail::throw_error(ec, "shutdown");
336  }
337 
338  /**
339  * @brief Asynchronously shut down SSL on the stream.
340  *
341  * This function call always returns immediately.
342  *
343  * @param handler The handler to be called when the handshake operation completes.
344  * The equivalent function signature of the handler must be: void(boost::system::error_code)
345  */
346  template <typename ShutdownHandler>
347  void async_shutdown(ShutdownHandler&& handler)
348  {
349  BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check;
351  throw Not_Implemented("async shutdown is not implemented");
352  // TODO: Implement a subclass of AsyncBase that calls native_handle()->close() and writes pending data from
353  // the core to the network, e.g. using AsyncWriteOperation.
354  }
355 
356  //! @}
357  //! \name I/O methods
358  //! @{
359 
360  /**
361  * @brief Read some data from the stream.
362  *
363  * The function call will block until one or more bytes of data has been read successfully, or until an error
364  * occurs.
365  *
366  * @param buffers The buffers into which the data will be read.
367  * @param ec Set to indicate what error occured, if any.
368  * @return The number of bytes read. Returns 0 if an error occurred.
369  */
370  template <typename MutableBufferSequence>
371  std::size_t read_some(const MutableBufferSequence& buffers,
372  boost::system::error_code& ec)
373  {
374  if(has_received_data())
375  { return copy_received_data(buffers); }
376 
377  boost::asio::const_buffer read_buffer{input_buffer().data(), m_nextLayer.read_some(input_buffer(), ec)};
378  if(ec)
379  { return 0; }
380 
381  try
382  {
383  native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), read_buffer.size());
384  }
385  catch(const TLS_Exception& e)
386  {
387  ec = e.type();
388  }
389  catch(const Botan::Exception& e)
390  {
391  ec = e.error_type();
392  }
393  catch(const std::exception&)
394  {
396  }
397 
398  return !ec ? copy_received_data(buffers) : 0;
399  }
400 
401  /**
402  * @brief Read some data from the stream.
403  *
404  * The function call will block until one or more bytes of data has been read successfully, or until an error
405  * occurs.
406  *
407  * @param buffers The buffers into which the data will be read.
408  * @return The number of bytes read. Returns 0 if an error occurred.
409  * @throws boost::system::system_error if error occured
410  */
411  template <typename MutableBufferSequence>
412  std::size_t read_some(const MutableBufferSequence& buffers)
413  {
414  boost::system::error_code ec;
415  auto const n = read_some(buffers, ec);
416  boost::asio::detail::throw_error(ec, "read_some");
417  return n;
418  }
419 
420  /**
421  * @brief Write some data to the stream.
422  *
423  * The function call will block until one or more bytes of data has been written successfully, or until an error
424  * occurs.
425  *
426  * @param buffers The data to be written.
427  * @param ec Set to indicate what error occurred, if any.
428  * @return The number of bytes processed from the input buffers.
429  */
430  template <typename ConstBufferSequence>
431  std::size_t write_some(const ConstBufferSequence& buffers,
432  boost::system::error_code& ec)
433  {
434  tls_encrypt(buffers, ec);
436  return !ec ? boost::asio::buffer_size(buffers) : 0;
437  }
438 
439  /**
440  * @brief Write some data to the stream.
441  *
442  * The function call will block until one or more bytes of data has been written successfully, or until an error
443  * occurs.
444  *
445  * @param buffers The data to be written.
446  * @return The number of bytes written.
447  * @throws boost::system::system_error if error occured
448  */
449  template <typename ConstBufferSequence>
450  std::size_t write_some(const ConstBufferSequence& buffers)
451  {
452  boost::system::error_code ec;
453  auto const n = write_some(buffers, ec);
454  boost::asio::detail::throw_error(ec, "write_some");
455  return n;
456  }
457 
458  /**
459  * @brief Start an asynchronous write. The function call always returns immediately.
460  *
461  * @param buffers The data to be written.
462  * @param handler The handler to be called when the write operation completes. Copies will be made of the handler
463  * as required. The equivalent function signature of the handler must be:
464  * void(boost::system::error_code, std::size_t)
465  */
466  template <typename ConstBufferSequence, typename WriteHandler>
467  auto async_write_some(const ConstBufferSequence& buffers, WriteHandler&& handler) ->
468  BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
469  void(boost::system::error_code, std::size_t))
470  {
471  BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
472 
473  boost::asio::async_completion<WriteHandler, void(boost::system::error_code, std::size_t)> init(handler);
474 
475  boost::system::error_code ec;
476  tls_encrypt(buffers, ec);
477  if(ec)
478  {
479  // we cannot be sure how many bytes were committed here so clear the send_buffer and let the
480  // AsyncWriteOperation call the handler with the error_code set
483  op{std::move(init.completion_handler), *this, std::size_t(0), ec};
484  return init.result.get();
485  }
486 
488  op{std::move(init.completion_handler), *this, boost::asio::buffer_size(buffers)};
489 
490  return init.result.get();
491  }
492 
493  /**
494  * @brief Start an asynchronous read. The function call always returns immediately.
495  *
496  * @param buffers The buffers into which the data will be read. Although the buffers object may be copied as
497  * necessary, ownership of the underlying buffers is retained by the caller, which must guarantee
498  * that they remain valid until the handler is called.
499  * @param handler The handler to be called when the read operation completes. The equivalent function signature of
500  * the handler must be:
501  * void(boost::system::error_code, std::size_t)
502  */
503  template <typename MutableBufferSequence, typename ReadHandler>
504  auto async_read_some(const MutableBufferSequence& buffers, ReadHandler&& handler) ->
505  BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
506  void(boost::system::error_code, std::size_t))
507  {
508  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
509 
510  boost::asio::async_completion<ReadHandler, void(boost::system::error_code, std::size_t)> init(handler);
511 
513  op{std::move(init.completion_handler), *this, buffers};
514  return init.result.get();
515  }
516 
517  //! @}
518 
519  protected:
520  template <class H, class S, class M, class A> friend class detail::AsyncReadOperation;
521  template <class H, class S, class A> friend class detail::AsyncWriteOperation;
522  template <class H, class S, class A> friend class detail::AsyncHandshakeOperation;
523 
524  /**
525  * @brief Helper class that implements Botan::TLS::Callbacks
526  *
527  * This class is provided to the stream's native_handle (Botan::TLS::Channel) and implements the callback
528  * functions triggered by the native_handle.
529  *
530  * @param receive_buffer reference to the buffer where decrypted data should be placed
531  * @param send_buffer reference to the buffer where encrypted data should be placed
532  */
534  {
535  public:
536  StreamCore(boost::beast::flat_buffer& receive_buffer, boost::beast::flat_buffer& send_buffer, Context& context)
537  : m_receive_buffer(receive_buffer), m_send_buffer(send_buffer), m_tls_context(context) {}
538 
539  virtual ~StreamCore() = default;
540 
541  void tls_emit_data(const uint8_t data[], std::size_t size) override
542  {
543  m_send_buffer.commit(
544  boost::asio::buffer_copy(m_send_buffer.prepare(size), boost::asio::buffer(data, size))
545  );
546  }
547 
548  void tls_record_received(uint64_t, const uint8_t data[], std::size_t size) override
549  {
550  m_receive_buffer.commit(
551  boost::asio::buffer_copy(m_receive_buffer.prepare(size), boost::asio::const_buffer(data, size))
552  );
553  }
554 
555  void tls_alert(Botan::TLS::Alert alert) override
556  {
557  BOTAN_UNUSED(alert);
558  }
559 
560  std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override
561  {
562  return std::chrono::milliseconds(1000);
563  }
564 
566  {
567  // TODO: it should be possible to configure this in the using application (via callback?)
568  return true;
569  }
570 
572  const std::vector<X509_Certificate>& cert_chain,
573  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
574  const std::vector<Certificate_Store*>& trusted_roots,
575  Usage_Type usage,
576  const std::string& hostname,
577  const TLS::Policy& policy) override
578  {
580  {
581  m_tls_context.get_verify_callback()(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
582  }
583  else
584  {
585  Callbacks::tls_verify_cert_chain(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
586  }
587  }
588 
589  boost::beast::flat_buffer& m_receive_buffer;
590  boost::beast::flat_buffer& m_send_buffer;
592  };
593 
594  const boost::asio::mutable_buffer& input_buffer() { return m_input_buffer; }
595  boost::asio::const_buffer send_buffer() const { return m_send_buffer.data(); }
596 
597  //! @brief Check if decrypted data is available in the receive buffer
598  bool has_received_data() const { return m_receive_buffer.size() > 0; }
599 
600  //! @brief Copy decrypted data into the user-provided buffer
601  template <typename MutableBufferSequence>
602  std::size_t copy_received_data(MutableBufferSequence buffers)
603  {
604  // Note: It would be nice to avoid this buffer copy. This could be achieved by equipping the StreamCore with
605  // the user's desired target buffer once a read is started, and reading directly into that buffer in tls_record
606  // received. However, we need to deal with the case that the receive buffer provided by the caller is smaller
607  // than the decrypted record, so this optimization might not be worth the additional complexity.
608  const auto copiedBytes = boost::asio::buffer_copy(buffers, m_receive_buffer.data());
609  m_receive_buffer.consume(copiedBytes);
610  return copiedBytes;
611  }
612 
613  //! @brief Check if encrypted data is available in the send buffer
614  bool has_data_to_send() const { return m_send_buffer.size() > 0; }
615 
616  //! @brief Mark bytes in the send buffer as consumed, removing them from the buffer
617  void consume_send_buffer(std::size_t bytesConsumed) { m_send_buffer.consume(bytesConsumed); }
618 
619  // This is a helper construct to allow mocking the native_handle in test code. It is activated by explicitly
620  // specifying a (mocked) channel type template parameter when constructing the stream and does not attempt to
621  // instantiate the native_handle.
622  // Note: once we have C++17 we can achieve this much more elegantly using constexpr if.
623  template<class T = ChannelT>
624  typename std::enable_if<!std::is_same<Channel, T>::value>::type
625  setup_native_handle(Connection_Side, boost::system::error_code&) {}
626 
627  /**
628  * @brief Create the native handle.
629  *
630  * Depending on the desired connection side, this function will create a Botan::TLS::Client or a
631  * Botan::TLS::Server.
632  *
633  * @param side The desired connection side (client or server)
634  * @param ec Set to NotImplemented when side is SERVER - currently only CLIENT is implemented
635  */
636  template<class T = ChannelT>
637  typename std::enable_if<std::is_same<Channel, T>::value>::type
638  setup_native_handle(Connection_Side side, boost::system::error_code& ec)
639  {
640  if(side == CLIENT)
641  {
642  m_native_handle = std::unique_ptr<Client>(
643  new Client(m_core,
649  }
650  else
651  {
652  // TODO: First steps in order to support the server side of this stream would be to instantiate a
653  // Botan::TLS::Server instance as the stream's native_handle and implement the handshake appropriately.
655  }
656  }
657 
658  size_t send_pending_encrypted_data(boost::system::error_code& ec)
659  {
660  if(ec)
661  { return 0; }
662 
663  auto writtenBytes = boost::asio::write(m_nextLayer, send_buffer(), ec);
664  consume_send_buffer(writtenBytes);
665  return writtenBytes;
666  }
667 
668  template <typename ConstBufferSequence>
669  void tls_encrypt(const ConstBufferSequence& buffers, boost::system::error_code& ec)
670  {
671  // NOTE: This is not asynchronous: it encrypts the data synchronously.
672  // The data encrypted by native_handle()->send() is synchronously stored in the send_buffer of m_core,
673  // but is not actually written to the wire, yet.
674  for(auto it = boost::asio::buffer_sequence_begin(buffers);
675  !ec && it != boost::asio::buffer_sequence_end(buffers);
676  it++)
677  {
678  const boost::asio::const_buffer buffer = *it;
679  try
680  {
681  native_handle()->send(static_cast<const uint8_t*>(buffer.data()), buffer.size());
682  }
683  catch(const TLS_Exception& e)
684  {
685  ec = e.type();
686  }
687  catch(const Botan::Exception& e)
688  {
689  ec = e.error_type();
690  }
691  catch(const std::exception&)
692  {
694  }
695  }
696  }
697 
699  StreamLayer m_nextLayer;
700 
701  boost::beast::flat_buffer m_receive_buffer;
702  boost::beast::flat_buffer m_send_buffer;
703 
705  std::unique_ptr<ChannelT> m_native_handle;
706 
707  // Buffer space used to read input intended for the core
708  std::vector<uint8_t> m_input_buffer_space;
709  const boost::asio::mutable_buffer m_input_buffer;
710  };
711 
712 } // namespace TLS
713 } // namespace Botan
714 
715 #endif // BOOST_VERSION
716 #endif // BOTAN_ASIO_STREAM_H_
void tls_verify_cert_chain(const std::vector< X509_Certificate > &cert_chain, const std::vector< std::shared_ptr< const OCSP::Response >> &ocsp_responses, const std::vector< Certificate_Store *> &trusted_roots, Usage_Type usage, const std::string &hostname, const TLS::Policy &policy) override
Definition: asio_stream.h:571
RandomNumberGenerator & m_rng
Definition: asio_context.h:108
void shutdown(boost::system::error_code &ec)
Shut down SSL on the stream.
Definition: asio_stream.h:300
size_t send_pending_encrypted_data(boost::system::error_code &ec)
Definition: asio_stream.h:658
std::enable_if<!std::is_same< Channel, T >::value >::type setup_native_handle(Connection_Side, boost::system::error_code &)
Definition: asio_stream.h:625
void set_verify_mode(verify_mode v, boost::system::error_code &ec)
Definition: asio_stream.h:180
void set_verify_callback(Verify_Callback callback)
Override the tls_verify_cert_chain callback.
Definition: asio_context.h:84
BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(BufferedHandshakeHandler, handler) type_check
const ConstBufferSequence & buffers
Definition: asio_stream.h:280
StreamCore(boost::beast::flat_buffer &receive_buffer, boost::beast::flat_buffer &send_buffer, Context &context)
Definition: asio_stream.h:536
const boost::asio::mutable_buffer m_input_buffer
Definition: asio_stream.h:709
Helper class that implements Botan::TLS::Callbacks.
Definition: asio_stream.h:533
virtual ErrorType error_type() const noexcept
Definition: exceptn.h:101
void set_verify_depth(int depth)
Definition: asio_stream.h:149
auto async_handshake(Connection_Side side, HandshakeHandler &&handler) ->
Starts an asynchronous SSL handshake.
Definition: asio_stream.h:258
std::enable_if< std::is_same< Channel, T >::value >::type setup_native_handle(Connection_Side side, boost::system::error_code &ec)
Create the native handle.
Definition: asio_stream.h:638
throw Not_Implemented("buffered async handshake is not implemented")
typename std::remove_reference< StreamLayer >::type next_layer_type
Definition: asio_stream.h:103
Definition: bigint.h:1135
void set_verify_callback(Context::Verify_Callback callback)
Override the tls_verify_cert_chain callback.
Definition: asio_stream.h:131
StreamLayer m_nextLayer
Definition: asio_stream.h:699
std::size_t write_some(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Write some data to the stream.
Definition: asio_stream.h:431
MechanismType type
auto async_read_some(const MutableBufferSequence &buffers, ReadHandler &&handler) -> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(boost::system::error_code, std::size_t))
Start an asynchronous read. The function call always returns immediately.
Definition: asio_stream.h:504
std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override
Definition: asio_stream.h:560
void async_shutdown(ShutdownHandler &&handler)
Asynchronously shut down SSL on the stream.
Definition: asio_stream.h:347
Credentials_Manager & m_credentials_manager
Definition: asio_context.h:107
void tls_record_received(uint64_t, const uint8_t data[], std::size_t size) override
Definition: asio_stream.h:548
typename next_layer_type::executor_type executor_type
Definition: asio_stream.h:105
bool has_data_to_send() const
Check if encrypted data is available in the send buffer.
Definition: asio_stream.h:614
void handshake(Connection_Side side, boost::system::error_code &ec)
Performs SSL handshaking.
Definition: asio_stream.h:213
Stream & operator=(Stream &&other)=default
boost::asio::const_buffer send_buffer() const
Definition: asio_stream.h:595
void tls_emit_data(const uint8_t data[], std::size_t size) override
Definition: asio_stream.h:541
StreamCore m_core
Definition: asio_stream.h:704
Context & m_context
Definition: asio_stream.h:698
Server_Information m_server_info
Definition: asio_context.h:112
virtual ~Stream()=default
const boost::asio::mutable_buffer & input_buffer()
Definition: asio_stream.h:594
std::size_t write_some(const ConstBufferSequence &buffers)
Write some data to the stream.
Definition: asio_stream.h:450
std::size_t read_some(const MutableBufferSequence &buffers, boost::system::error_code &ec)
Read some data from the stream.
Definition: asio_stream.h:371
next_layer_type & next_layer()
Definition: asio_stream.h:111
const lowest_layer_type & lowest_layer() const
Definition: asio_stream.h:114
boost::beast::flat_buffer & m_send_buffer
Definition: asio_stream.h:590
const ConstBufferSequence BufferedHandshakeHandler && handler
Definition: asio_stream.h:282
lowest_layer_type & lowest_layer()
Definition: asio_stream.h:113
std::size_t copy_received_data(MutableBufferSequence buffers)
Copy decrypted data into the user-provided buffer.
Definition: asio_stream.h:602
bool has_verify_callback() const
Definition: asio_context.h:89
native_handle_type native_handle()
Definition: asio_stream.h:116
bool tls_session_established(const Botan::TLS::Session &) override
Definition: asio_stream.h:565
executor_type get_executor() noexcept
Definition: asio_stream.h:108
auto async_write_some(const ConstBufferSequence &buffers, WriteHandler &&handler) -> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(boost::system::error_code, std::size_t))
Start an asynchronous write. The function call always returns immediately.
Definition: asio_stream.h:467
virtual void tls_verify_cert_chain(const std::vector< X509_Certificate > &cert_chain, const std::vector< std::shared_ptr< const OCSP::Response >> &ocsp_responses, const std::vector< Certificate_Store *> &trusted_roots, Usage_Type usage, const std::string &hostname, const TLS::Policy &policy)
boost::asio compatible SSL/TLS stream
Definition: asio_stream.h:49
bool has_received_data() const
Check if decrypted data is available in the receive buffer.
Definition: asio_stream.h:598
boost::beast::flat_buffer m_send_buffer
Definition: asio_stream.h:702
Definition: alg_id.cpp:13
std::size_t read_some(const MutableBufferSequence &buffers)
Read some data from the stream.
Definition: asio_stream.h:412
void set_verify_depth(int depth, boost::system::error_code &ec)
Definition: asio_stream.h:160
#define BOTAN_UNUSED(...)
Definition: assert.h:142
Alert::Type type() const
Definition: tls_exceptn.h:24
void tls_encrypt(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Definition: asio_stream.h:669
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void(boost::system::error_code, std::size_t)) async_handshake(Connection_Side side
boost::beast::flat_buffer & m_receive_buffer
Definition: asio_stream.h:589
void handshake(Connection_Side side)
Performs SSL handshaking.
Definition: asio_stream.h:198
int(* init)(CTX *)
virtual ~StreamCore()=default
void shutdown()
Shut down SSL on the stream.
Definition: asio_stream.h:331
void tls_alert(Botan::TLS::Alert alert) override
Definition: asio_stream.h:555
void set_verify_mode(verify_mode v)
Definition: asio_stream.h:168
std::vector< uint8_t > m_input_buffer_space
Definition: asio_stream.h:708
Stream(Context &context, Args &&... args)
Construct a new Stream.
Definition: asio_stream.h:64
Session_Manager & m_session_manager
Definition: asio_context.h:109
typename std::add_pointer< ChannelT >::type native_handle_type
Definition: asio_stream.h:106
typename next_layer_type::lowest_layer_type lowest_layer_type
Definition: asio_stream.h:104
const Verify_Callback & get_verify_callback() const
Definition: asio_context.h:94
void consume_send_buffer(std::size_t bytesConsumed)
Mark bytes in the send buffer as consumed, removing them from the buffer.
Definition: asio_stream.h:617
std::unique_ptr< ChannelT > m_native_handle
Definition: asio_stream.h:705
detail::fn_signature_helper< decltype(&Callbacks::tls_verify_cert_chain)>::type Verify_Callback
Definition: asio_context.h:54
Usage_Type
Definition: x509cert.h:25
void set_verify_callback(Context::Verify_Callback callback, boost::system::error_code &ec)
Compatibility overload of set_verify_callback.
Definition: asio_stream.h:142
const next_layer_type & next_layer() const
Definition: asio_stream.h:110
boost::beast::flat_buffer m_receive_buffer
Definition: asio_stream.h:701
Stream(Arg &&arg, Context &context)
Construct a new Stream.
Definition: asio_stream.h:83