Botan  2.11.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 ec This parameter is unused.
140  */
141  void set_verify_callback(Context::Verify_Callback callback, boost::system::error_code& ec)
142  {
143  BOTAN_UNUSED(ec);
144  m_context.set_verify_callback(std::move(callback));
145  }
146 
147  //! @throws Not_Implemented
148  void set_verify_depth(int depth)
149  {
150  BOTAN_UNUSED(depth);
151  throw Not_Implemented("set_verify_depth is not implemented");
152  }
153 
154  /**
155  * Not Implemented.
156  * @param ec Will be set to `Botan::ErrorType::NotImplemented`
157  */
158  void set_verify_depth(int depth, boost::system::error_code& ec)
159  {
160  BOTAN_UNUSED(depth);
162  }
163 
164  //! @throws Not_Implemented
165  template <typename verify_mode>
166  void set_verify_mode(verify_mode v)
167  {
168  BOTAN_UNUSED(v);
169  throw Not_Implemented("set_verify_mode is not implemented");
170  }
171 
172  /**
173  * Not Implemented.
174  * @param ec Will be set to `Botan::ErrorType::NotImplemented`
175  */
176  template <typename verify_mode>
177  void set_verify_mode(verify_mode v, boost::system::error_code& ec)
178  {
179  BOTAN_UNUSED(v);
181  }
182 
183  //! @}
184  //! \name handshake methods
185  //! @{
186 
187  /**
188  * @brief Performs SSL handshaking.
189  *
190  * The function call will block until handshaking is complete or an error occurs.
191  *
192  * @param type The type of handshaking to be performed, i.e. as a client or as a server.
193  * @throws boost::system::system_error if error occured, or if the chosen Connection_Side is not available
194  */
196  {
197  boost::system::error_code ec;
198  handshake(side, ec);
199  boost::asio::detail::throw_error(ec, "handshake");
200  }
201 
202  /**
203  * @brief Performs SSL handshaking.
204  *
205  * The function call will block until handshaking is complete or an error occurs.
206  *
207  * @param type The type of handshaking to be performed, i.e. as a client or as a server.
208  * @param ec Set to indicate what error occurred, if any.
209  */
210  void handshake(Connection_Side side, boost::system::error_code& ec)
211  {
212  setup_native_handle(side, ec);
213 
214  // send client hello, which was written to the send buffer on client instantiation
216 
217  while(!native_handle()->is_active() && !ec)
218  {
219  boost::asio::const_buffer read_buffer{input_buffer().data(), m_nextLayer.read_some(input_buffer(), ec)};
220  if(ec)
221  { return; }
222 
223  try
224  {
225  native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), read_buffer.size());
226  }
227  catch(const TLS_Exception& e)
228  {
229  ec = e.type();
230  }
231  catch(const Botan::Exception& e)
232  {
233  ec = e.error_type();
234  }
235  catch(const std::exception&)
236  {
238  }
239 
241  }
242  }
243 
244  /**
245  * @brief Starts an asynchronous SSL handshake.
246  *
247  * This function call always returns immediately.
248  *
249  * @param type The type of handshaking to be performed, i.e. as a client or as a server.
250  * @param handler The handler to be called when the handshake operation completes.
251  * The equivalent function signature of the handler must be: void(boost::system::error_code)
252  * @throws NotImplemented if Connection_Side is not CLIENT
253  */
254  template <typename HandshakeHandler>
255  BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
256  void(boost::system::error_code))
257  async_handshake(Connection_Side side, HandshakeHandler&& handler)
258  {
259  BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
260 
261  boost::system::error_code ec;
262  setup_native_handle(side, ec);
263  // If ec is set by setup_native_handle, the AsyncHandshakeOperation created below will do nothing but call the
264  // handler with the error_code set appropriately - no need to early return here.
265 
266  boost::asio::async_completion<HandshakeHandler, void(boost::system::error_code)> init(handler);
267 
269  op{std::move(init.completion_handler), *this, ec};
270 
271  return init.result.get();
272  }
273 
274  //! @throws Not_Implemented
275  template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
276  BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
277  void(boost::system::error_code, std::size_t))
278  async_handshake(Connection_Side side, const ConstBufferSequence& buffers,
279  BufferedHandshakeHandler&& handler)
280  {
281  BOTAN_UNUSED(side, buffers, handler);
282  BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(BufferedHandshakeHandler, handler) type_check;
283  throw Not_Implemented("buffered async handshake is not implemented");
284  }
285 
286  //! @}
287  //! \name shutdown methods
288  //! @{
289 
290  /**
291  * @brief Shut down SSL on the stream.
292  *
293  * This function is used to shut down SSL on the stream. The function call will block until SSL has been shut down
294  * or an error occurs. Note that this will not close the lowest layer.
295  *
296  * @param ec Set to indicate what error occured, if any.
297  */
298  void shutdown(boost::system::error_code& ec)
299  {
300  try
301  {
302  native_handle()->close();
303  }
304  catch(const TLS_Exception& e)
305  {
306  ec = e.type();
307  }
308  catch(const Botan::Exception& e)
309  {
310  ec = e.error_type();
311  }
312  catch(const std::exception&)
313  {
315  }
316 
317  if(!ec)
319  }
320 
321  /**
322  * @brief Shut down SSL on the stream.
323  *
324  * This function is used to shut down SSL on the stream. The function call will block until SSL has been shut down
325  * or an error occurs. Note that this will not close the lowest layer.
326  *
327  * @throws boost::system::system_error if error occured
328  */
329  void shutdown()
330  {
331  boost::system::error_code ec;
332  shutdown(ec);
333  boost::asio::detail::throw_error(ec, "shutdown");
334  }
335 
336  /**
337  * @brief Asynchronously shut down SSL on the stream.
338  *
339  * This function call always returns immediately.
340  *
341  * @param handler The handler to be called when the handshake operation completes.
342  * The equivalent function signature of the handler must be: void(boost::system::error_code)
343  */
344  template <typename ShutdownHandler>
345  void async_shutdown(ShutdownHandler&& handler)
346  {
347  BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check;
349  throw Not_Implemented("async shutdown is not implemented");
350  // TODO: Implement a subclass of AsyncBase that calls native_handle()->close() and writes pending data from
351  // the core to the network, e.g. using AsyncWriteOperation.
352  }
353 
354  //! @}
355  //! \name I/O methods
356  //! @{
357 
358  /**
359  * @brief Read some data from the stream.
360  *
361  * The function call will block until one or more bytes of data has been read successfully, or until an error
362  * occurs.
363  *
364  * @param buffers The buffers into which the data will be read.
365  * @param ec Set to indicate what error occured, if any.
366  * @return The number of bytes read. Returns 0 if an error occurred.
367  */
368  template <typename MutableBufferSequence>
369  std::size_t read_some(const MutableBufferSequence& buffers,
370  boost::system::error_code& ec)
371  {
372  if(has_received_data())
373  { return copy_received_data(buffers); }
374 
375  boost::asio::const_buffer read_buffer{input_buffer().data(), m_nextLayer.read_some(input_buffer(), ec)};
376  if(ec)
377  { return 0; }
378 
379  try
380  {
381  native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), read_buffer.size());
382  }
383  catch(const TLS_Exception& e)
384  {
385  ec = e.type();
386  }
387  catch(const Botan::Exception& e)
388  {
389  ec = e.error_type();
390  }
391  catch(const std::exception&)
392  {
394  }
395 
396  return !ec ? copy_received_data(buffers) : 0;
397  }
398 
399  /**
400  * @brief Read some data from the stream.
401  *
402  * The function call will block until one or more bytes of data has been read successfully, or until an error
403  * occurs.
404  *
405  * @param buffers The buffers into which the data will be read.
406  * @return The number of bytes read. Returns 0 if an error occurred.
407  * @throws boost::system::system_error if error occured
408  */
409  template <typename MutableBufferSequence>
410  std::size_t read_some(const MutableBufferSequence& buffers)
411  {
412  boost::system::error_code ec;
413  auto const n = read_some(buffers, ec);
414  boost::asio::detail::throw_error(ec, "read_some");
415  return n;
416  }
417 
418  /**
419  * @brief Write some data to the stream.
420  *
421  * The function call will block until one or more bytes of data has been written successfully, or until an error
422  * occurs.
423  *
424  * @param buffers The data to be written.
425  * @param ec Set to indicate what error occurred, if any.
426  * @return The number of bytes processed from the input buffers.
427  */
428  template <typename ConstBufferSequence>
429  std::size_t write_some(const ConstBufferSequence& buffers,
430  boost::system::error_code& ec)
431  {
434  return !ec ? boost::asio::buffer_size(buffers) : 0;
435  }
436 
437  /**
438  * @brief Write some data to the stream.
439  *
440  * The function call will block until one or more bytes of data has been written successfully, or until an error
441  * occurs.
442  *
443  * @param buffers The data to be written.
444  * @return The number of bytes written.
445  * @throws boost::system::system_error if error occured
446  */
447  template <typename ConstBufferSequence>
448  std::size_t write_some(const ConstBufferSequence& buffers)
449  {
450  boost::system::error_code ec;
451  auto const n = write_some(buffers, ec);
452  boost::asio::detail::throw_error(ec, "write_some");
453  return n;
454  }
455 
456  /**
457  * @brief Start an asynchronous write. The function call always returns immediately.
458  *
459  * @param buffers The data to be written.
460  * @param handler The handler to be called when the write operation completes. Copies will be made of the handler
461  * as required. The equivalent function signature of the handler must be:
462  * void(boost::system::error_code, std::size_t)
463  */
464  template <typename ConstBufferSequence, typename WriteHandler>
465  BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
466  void(boost::system::error_code, std::size_t))
467  async_write_some(const ConstBufferSequence& buffers, WriteHandler&& handler)
468  {
469  BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
470 
471  boost::asio::async_completion<WriteHandler, void(boost::system::error_code, std::size_t)> init(handler);
472 
473  boost::system::error_code ec;
475  if(ec)
476  {
477  // we cannot be sure how many bytes were committed here so clear the send_buffer and let the
478  // AsyncWriteOperation call the handler with the error_code set
481  op{std::move(init.completion_handler), *this, std::size_t(0), ec};
482  return init.result.get();
483  }
484 
486  op{std::move(init.completion_handler), *this, boost::asio::buffer_size(buffers)};
487 
488  return init.result.get();
489  }
490 
491  /**
492  * @brief Start an asynchronous read. The function call always returns immediately.
493  *
494  * @param buffers The buffers into which the data will be read. Although the buffers object may be copied as
495  * necessary, ownership of the underlying buffers is retained by the caller, which must guarantee
496  * that they remain valid until the handler is called.
497  * @param handler The handler to be called when the read operation completes. The equivalent function signature of
498  * the handler must be:
499  * void(boost::system::error_code, std::size_t)
500  */
501  template <typename MutableBufferSequence, typename ReadHandler>
502  BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
503  void(boost::system::error_code, std::size_t))
504  async_read_some(const MutableBufferSequence& buffers, ReadHandler&& handler)
505  {
506  BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
507 
508  boost::asio::async_completion<ReadHandler, void(boost::system::error_code, std::size_t)> init(handler);
509 
511  op{std::move(init.completion_handler), *this, buffers};
512  return init.result.get();
513  }
514 
515  //! @}
516 
517  protected:
518  template <class H, class S, class M, class A> friend class detail::AsyncReadOperation;
519  template <class H, class S, class A> friend class detail::AsyncWriteOperation;
520  template <class H, class S, class A> friend class detail::AsyncHandshakeOperation;
521 
522  /**
523  * @brief Helper class that implements Botan::TLS::Callbacks
524  *
525  * This class is provided to the stream's native_handle (Botan::TLS::Channel) and implements the callback
526  * functions triggered by the native_handle.
527  *
528  * @param receive_buffer reference to the buffer where decrypted data should be placed
529  * @param send_buffer reference to the buffer where encrypted data should be placed
530  */
532  {
533  public:
534  StreamCore(boost::beast::flat_buffer& receive_buffer, boost::beast::flat_buffer& send_buffer, Context& context)
535  : m_receive_buffer(receive_buffer), m_send_buffer(send_buffer), m_tls_context(context) {}
536 
537  virtual ~StreamCore() = default;
538 
539  void tls_emit_data(const uint8_t data[], std::size_t size) override
540  {
541  m_send_buffer.commit(
542  boost::asio::buffer_copy(m_send_buffer.prepare(size), boost::asio::buffer(data, size))
543  );
544  }
545 
546  void tls_record_received(uint64_t, const uint8_t data[], std::size_t size) override
547  {
548  m_receive_buffer.commit(
549  boost::asio::buffer_copy(m_receive_buffer.prepare(size), boost::asio::const_buffer(data, size))
550  );
551  }
552 
553  void tls_alert(Botan::TLS::Alert alert) override
554  {
555  BOTAN_UNUSED(alert);
556  }
557 
558  std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override
559  {
560  return std::chrono::milliseconds(1000);
561  }
562 
564  {
565  // TODO: it should be possible to configure this in the using application (via callback?)
566  return true;
567  }
568 
570  const std::vector<X509_Certificate>& cert_chain,
571  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
572  const std::vector<Certificate_Store*>& trusted_roots,
573  Usage_Type usage,
574  const std::string& hostname,
575  const TLS::Policy& policy) override
576  {
578  {
579  m_tls_context.get_verify_callback()(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
580  }
581  else
582  {
583  Callbacks::tls_verify_cert_chain(cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
584  }
585  }
586 
587  boost::beast::flat_buffer& m_receive_buffer;
588  boost::beast::flat_buffer& m_send_buffer;
590  };
591 
592  const boost::asio::mutable_buffer& input_buffer() { return m_input_buffer; }
593  boost::asio::const_buffer send_buffer() const { return m_send_buffer.data(); }
594 
595  //! @brief Check if decrypted data is available in the receive buffer
596  bool has_received_data() const { return m_receive_buffer.size() > 0; }
597 
598  //! @brief Copy decrypted data into the user-provided buffer
599  template <typename MutableBufferSequence>
600  std::size_t copy_received_data(MutableBufferSequence buffers)
601  {
602  // Note: It would be nice to avoid this buffer copy. This could be achieved by equipping the StreamCore with
603  // the user's desired target buffer once a read is started, and reading directly into that buffer in tls_record
604  // received. However, we need to deal with the case that the receive buffer provided by the caller is smaller
605  // than the decrypted record, so this optimization might not be worth the additional complexity.
606  const auto copiedBytes = boost::asio::buffer_copy(buffers, m_receive_buffer.data());
607  m_receive_buffer.consume(copiedBytes);
608  return copiedBytes;
609  }
610 
611  //! @brief Check if encrypted data is available in the send buffer
612  bool has_data_to_send() const { return m_send_buffer.size() > 0; }
613 
614  //! @brief Mark bytes in the send buffer as consumed, removing them from the buffer
615  void consume_send_buffer(std::size_t bytesConsumed) { m_send_buffer.consume(bytesConsumed); }
616 
617  // This is a helper construct to allow mocking the native_handle in test code. It is activated by explicitly
618  // specifying a (mocked) channel type template parameter when constructing the stream and does not attempt to
619  // instantiate the native_handle.
620  // Note: once we have C++17 we can achieve this much more elegantly using constexpr if.
621  template<class T = ChannelT>
622  typename std::enable_if<!std::is_same<Channel, T>::value>::type
623  setup_native_handle(Connection_Side, boost::system::error_code&) {}
624 
625  /**
626  * @brief Create the native handle.
627  *
628  * Depending on the desired connection side, this function will create a Botan::TLS::Client or a
629  * Botan::TLS::Server.
630  *
631  * @param side The desired connection side (client or server)
632  * @param ec Set to NotImplemented when side is SERVER - currently only CLIENT is implemented
633  */
634  template<class T = ChannelT>
635  typename std::enable_if<std::is_same<Channel, T>::value>::type
636  setup_native_handle(Connection_Side side, boost::system::error_code& ec)
637  {
638  if(side == CLIENT)
639  {
640  m_native_handle = std::unique_ptr<Client>(
641  new Client(m_core,
647  }
648  else
649  {
650  // TODO: First steps in order to support the server side of this stream would be to instantiate a
651  // Botan::TLS::Server instance as the stream's native_handle and implement the handshake appropriately.
653  }
654  }
655 
656  size_t send_pending_encrypted_data(boost::system::error_code& ec)
657  {
658  if(ec)
659  { return 0; }
660 
661  auto writtenBytes = boost::asio::write(m_nextLayer, send_buffer(), ec);
662  consume_send_buffer(writtenBytes);
663  return writtenBytes;
664  }
665 
666  template <typename ConstBufferSequence>
667  void tls_encrypt(const ConstBufferSequence& buffers, boost::system::error_code& ec)
668  {
669  // NOTE: This is not asynchronous: it encrypts the data synchronously.
670  // The data encrypted by native_handle()->send() is synchronously stored in the send_buffer of m_core,
671  // but is not actually written to the wire, yet.
672  for(auto it = boost::asio::buffer_sequence_begin(buffers);
673  !ec && it != boost::asio::buffer_sequence_end(buffers);
674  it++)
675  {
676  const boost::asio::const_buffer buffer = *it;
677  try
678  {
679  native_handle()->send(static_cast<const uint8_t*>(buffer.data()), buffer.size());
680  }
681  catch(const TLS_Exception& e)
682  {
683  ec = e.type();
684  }
685  catch(const Botan::Exception& e)
686  {
687  ec = e.error_type();
688  }
689  catch(const std::exception&)
690  {
692  }
693  }
694  }
695 
697  StreamLayer m_nextLayer;
698 
699  boost::beast::flat_buffer m_receive_buffer;
700  boost::beast::flat_buffer m_send_buffer;
701 
703  std::unique_ptr<ChannelT> m_native_handle;
704 
705  // Buffer space used to read input intended for the core
706  std::vector<uint8_t> m_input_buffer_space;
707  const boost::asio::mutable_buffer m_input_buffer;
708  };
709 
710 } // namespace TLS
711 } // namespace Botan
712 
713 #endif // BOOST_VERSION
714 #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:569
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:298
size_t send_pending_encrypted_data(boost::system::error_code &ec)
Definition: asio_stream.h:656
std::enable_if<!std::is_same< Channel, T >::value >::type setup_native_handle(Connection_Side, boost::system::error_code &)
Definition: asio_stream.h:623
void set_verify_mode(verify_mode v, boost::system::error_code &ec)
Definition: asio_stream.h:177
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:278
StreamCore(boost::beast::flat_buffer &receive_buffer, boost::beast::flat_buffer &send_buffer, Context &context)
Definition: asio_stream.h:534
const boost::asio::mutable_buffer m_input_buffer
Definition: asio_stream.h:707
Helper class that implements Botan::TLS::Callbacks.
Definition: asio_stream.h:531
virtual ErrorType error_type() const noexcept
Definition: exceptn.h:99
boost::system::error_code ec
Definition: asio_stream.h:261
void set_verify_depth(int depth)
Definition: asio_stream.h:148
detail::AsyncHandshakeOperation< typename std::decay< HandshakeHandler >::type, Stream > op
Definition: asio_stream.h:269
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:636
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:1136
setup_native_handle(side, ec)
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:697
std::size_t write_some(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Write some data to the stream.
Definition: asio_stream.h:429
MechanismType type
std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override
Definition: asio_stream.h:558
void async_shutdown(ShutdownHandler &&handler)
Asynchronously shut down SSL on the stream.
Definition: asio_stream.h:345
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:546
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:612
void handshake(Connection_Side side, boost::system::error_code &ec)
Performs SSL handshaking.
Definition: asio_stream.h:210
Stream & operator=(Stream &&other)=default
boost::asio::const_buffer send_buffer() const
Definition: asio_stream.h:593
void tls_emit_data(const uint8_t data[], std::size_t size) override
Definition: asio_stream.h:539
StreamCore m_core
Definition: asio_stream.h:702
Context & m_context
Definition: asio_stream.h:696
Server_Information m_server_info
Definition: asio_context.h:112
virtual ~Stream()=default
const boost::asio::mutable_buffer & input_buffer()
Definition: asio_stream.h:592
std::size_t write_some(const ConstBufferSequence &buffers)
Write some data to the stream.
Definition: asio_stream.h:448
std::size_t read_some(const MutableBufferSequence &buffers, boost::system::error_code &ec)
Read some data from the stream.
Definition: asio_stream.h:369
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:588
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:600
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:563
executor_type get_executor() noexcept
Definition: asio_stream.h:108
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)
HandshakeHandler && handler
Definition: asio_stream.h:258
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:596
boost::beast::flat_buffer m_send_buffer
Definition: asio_stream.h:700
Definition: alg_id.cpp:13
std::size_t read_some(const MutableBufferSequence &buffers)
Read some data from the stream.
Definition: asio_stream.h:410
void set_verify_depth(int depth, boost::system::error_code &ec)
Definition: asio_stream.h:158
#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:667
boost::beast::flat_buffer & m_receive_buffer
Definition: asio_stream.h:587
void handshake(Connection_Side side)
Performs SSL handshaking.
Definition: asio_stream.h:195
boost::asio::async_completion< HandshakeHandler, void(boost::system::error_code)> init(handler)
tls_encrypt(buffers, ec)
virtual ~StreamCore()=default
void shutdown()
Shut down SSL on the stream.
Definition: asio_stream.h:329
void tls_alert(Botan::TLS::Alert alert) override
Definition: asio_stream.h:553
void set_verify_mode(verify_mode v)
Definition: asio_stream.h:166
std::vector< uint8_t > m_input_buffer_space
Definition: asio_stream.h:706
Stream(Context &context, Args &&... args)
Construct a new Stream.
Definition: asio_stream.h:64
Session_Manager & m_session_manager
Definition: asio_context.h:109
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code)) async_handshake(Connection_Side side
Starts an asynchronous SSL handshake.
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:615
std::unique_ptr< ChannelT > m_native_handle
Definition: asio_stream.h:703
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:141
const next_layer_type & next_layer() const
Definition: asio_stream.h:110
boost::beast::flat_buffer m_receive_buffer
Definition: asio_stream.h:699
Stream(Arg &&arg, Context &context)
Construct a new Stream.
Definition: asio_stream.h:83