Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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)...)
67 , m_core(m_receive_buffer, m_send_buffer, m_context)
68 , m_input_buffer_space(MAX_CIPHERTEXT_SIZE, '\0')
69 , m_input_buffer(m_input_buffer_space.data(), m_input_buffer_space.size())
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))
86 , m_core(m_receive_buffer, m_send_buffer, m_context)
87 , m_input_buffer_space(MAX_CIPHERTEXT_SIZE, '\0')
88 , m_input_buffer(m_input_buffer_space.data(), m_input_buffer_space.size())
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
103 using next_layer_type = typename std::remove_reference<StreamLayer>::type;
104 using lowest_layer_type = typename next_layer_type::lowest_layer_type;
105 using executor_type = typename next_layer_type::executor_type;
106 using native_handle_type = typename std::add_pointer<ChannelT>::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; }
111 next_layer_type& next_layer() { 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
116 native_handle_type native_handle() { return m_native_handle.get(); }
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 */
131 void set_verify_callback(Context::Verify_Callback callback)
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);
163 ec = Botan::ErrorType::NotImplemented;
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);
183 ec = Botan::ErrorType::NotImplemented;
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 */
198 void handshake(Connection_Side side)
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
218 send_pending_encrypted_data(ec);
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 {
240 ec = Botan::ErrorType::Unknown;
241 }
242
243 send_pending_encrypted_data(ec);
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
270 detail::AsyncHandshakeOperation<typename std::decay<HandshakeHandler>::type, Stream>
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 {
316 ec = Botan::ErrorType::Unknown;
317 }
318
319 if(!ec)
320 { send_pending_encrypted_data(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;
350 BOTAN_UNUSED(handler);
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 {
395 ec = Botan::ErrorType::Unknown;
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);
435 send_pending_encrypted_data(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
481 consume_send_buffer(m_send_buffer.size());
482 detail::AsyncWriteOperation<typename std::decay<WriteHandler>::type, Stream>
483 op{std::move(init.completion_handler), *this, std::size_t(0), ec};
484 return init.result.get();
485 }
486
487 detail::AsyncWriteOperation<typename std::decay<WriteHandler>::type, Stream>
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
512 detail::AsyncReadOperation<typename std::decay<ReadHandler>::type, Stream, MutableBufferSequence>
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 */
533 class StreamCore : public Botan::TLS::Callbacks
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
565 bool tls_session_established(const Botan::TLS::Session&) override
566 {
567 // TODO: it should be possible to configure this in the using application (via callback?)
568 return true;
569 }
570
571 void tls_verify_cert_chain(
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 {
579 if(m_tls_context.has_verify_callback())
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;
591 Context& m_tls_context;
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,
644 m_context.m_session_manager,
645 m_context.m_credentials_manager,
646 m_context.m_policy,
647 m_context.m_rng,
648 m_context.m_server_info));
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.
654 ec = Botan::ErrorType::NotImplemented;
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 {
693 ec = Botan::ErrorType::Unknown;
694 }
695 }
696 }
697
698 Context& m_context;
699 StreamLayer m_nextLayer;
700
701 boost::beast::flat_buffer m_receive_buffer;
702 boost::beast::flat_buffer m_send_buffer;
703
704 StreamCore m_core;
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_
Botan::TLS::Context::m_rng
RandomNumberGenerator & m_rng
Definition: asio_context.h:108
Botan::TLS::Stream::shutdown
void shutdown(boost::system::error_code &ec)
Shut down SSL on the stream.
Definition: asio_stream.h:300
Botan::TLS::Stream::send_pending_encrypted_data
size_t send_pending_encrypted_data(boost::system::error_code &ec)
Definition: asio_stream.h:658
Botan::TLS::Session
Definition: tls_session.h:27
Botan::ErrorType::NotImplemented
Botan::TLS::Stream::setup_native_handle
std::enable_if<!std::is_same< Channel, T >::value >::type setup_native_handle(Connection_Side, boost::system::error_code &)
Definition: asio_stream.h:625
Botan::Exception
Definition: exceptn.h:85
Botan::TLS::Stream::set_verify_mode
void set_verify_mode(verify_mode v, boost::system::error_code &ec)
Definition: asio_stream.h:180
Botan::TLS::Context::set_verify_callback
void set_verify_callback(Verify_Callback callback)
Override the tls_verify_cert_chain callback.
Definition: asio_context.h:84
Botan::TLS::detail::AsyncHandshakeOperation
Definition: asio_async_ops.h:267
Botan::TLS::Stream::next_layer
const next_layer_type & next_layer() const
Definition: asio_stream.h:110
Botan::TLS::Stream::BOOST_ASIO_HANDSHAKE_HANDLER_CHECK
BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(BufferedHandshakeHandler, handler) type_check
Botan::TLS::Stream::buffers
const ConstBufferSequence & buffers
Definition: asio_stream.h:280
Botan::TLS::Stream::StreamCore::StreamCore
StreamCore(boost::beast::flat_buffer &receive_buffer, boost::beast::flat_buffer &send_buffer, Context &context)
Definition: asio_stream.h:536
Botan::TLS::Stream::m_input_buffer
const boost::asio::mutable_buffer m_input_buffer
Definition: asio_stream.h:709
Botan::TLS::Stream::StreamCore
Helper class that implements Botan::TLS::Callbacks.
Definition: asio_stream.h:533
Botan::Exception::error_type
virtual ErrorType error_type() const noexcept
Definition: exceptn.h:101
Botan::TLS::Stream::set_verify_depth
void set_verify_depth(int depth)
Definition: asio_stream.h:149
Botan::TLS::Stream::async_handshake
auto async_handshake(Connection_Side side, HandshakeHandler &&handler) ->
Starts an asynchronous SSL handshake.
Definition: asio_stream.h:258
Botan::TLS::Stream::setup_native_handle
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
Botan::TLS::Stream::Not_Implemented
throw Not_Implemented("buffered async handshake is not implemented")
Botan::TLS::Stream::next_layer_type
typename std::remove_reference< StreamLayer >::type next_layer_type
Definition: asio_stream.h:103
std
Definition: bigint.h:1135
Botan::TLS::Stream::set_verify_callback
void set_verify_callback(Context::Verify_Callback callback)
Override the tls_verify_cert_chain callback.
Definition: asio_stream.h:131
Botan::TLS::Stream::m_nextLayer
StreamLayer m_nextLayer
Definition: asio_stream.h:699
Botan::TLS::Stream::write_some
std::size_t write_some(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Write some data to the stream.
Definition: asio_stream.h:431
Botan::TLS::Context
Definition: asio_context.h:44
type
MechanismType type
Definition: p11_mechanism.cpp:44
Botan::TLS::Stream::async_read_some
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
Botan::TLS::Callbacks::tls_verify_cert_chain
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)
Definition: tls_callbacks.cpp:53
Botan::TLS::Stream::StreamCore::tls_verify_cert_chain_ocsp_timeout
std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override
Definition: asio_stream.h:560
Botan::TLS::Stream::async_shutdown
void async_shutdown(ShutdownHandler &&handler)
Asynchronously shut down SSL on the stream.
Definition: asio_stream.h:347
Botan::TLS::Context::m_credentials_manager
Credentials_Manager & m_credentials_manager
Definition: asio_context.h:107
Botan::TLS::Stream::StreamCore::tls_record_received
void tls_record_received(uint64_t, const uint8_t data[], std::size_t size) override
Definition: asio_stream.h:548
Botan::TLS::Connection_Side
Connection_Side
Definition: tls_magic.h:32
Botan::TLS::Stream::executor_type
typename next_layer_type::executor_type executor_type
Definition: asio_stream.h:105
Botan::TLS::Callbacks
Definition: tls_callbacks.h:40
Botan::TLS::Stream::handshake
void handshake(Connection_Side side, boost::system::error_code &ec)
Performs SSL handshaking.
Definition: asio_stream.h:213
Botan::TLS::Stream::operator=
Stream & operator=(Stream &&other)=default
Botan::TLS::Stream::StreamCore::tls_emit_data
void tls_emit_data(const uint8_t data[], std::size_t size) override
Definition: asio_stream.h:541
Botan::TLS::Stream::m_core
StreamCore m_core
Definition: asio_stream.h:704
Botan::TLS::Stream::m_context
Context & m_context
Definition: asio_stream.h:698
Botan::TLS::Context::m_server_info
Server_Information m_server_info
Definition: asio_context.h:112
Botan::TLS::Stream::~Stream
virtual ~Stream()=default
Botan::TLS::Stream::input_buffer
const boost::asio::mutable_buffer & input_buffer()
Definition: asio_stream.h:594
Botan::TLS::Stream::write_some
std::size_t write_some(const ConstBufferSequence &buffers)
Write some data to the stream.
Definition: asio_stream.h:450
Botan::TLS::Stream::read_some
std::size_t read_some(const MutableBufferSequence &buffers, boost::system::error_code &ec)
Read some data from the stream.
Definition: asio_stream.h:371
Botan::TLS::Stream::next_layer
next_layer_type & next_layer()
Definition: asio_stream.h:111
Botan::TLS::Context::m_policy
Policy & m_policy
Definition: asio_context.h:110
Botan::TLS::Stream::StreamCore::m_send_buffer
boost::beast::flat_buffer & m_send_buffer
Definition: asio_stream.h:590
Botan::TLS::Stream::handler
const ConstBufferSequence BufferedHandshakeHandler && handler
Definition: asio_stream.h:282
Botan::TLS::MAX_CIPHERTEXT_SIZE
Definition: tls_magic.h:28
Botan::TLS::Stream::lowest_layer
lowest_layer_type & lowest_layer()
Definition: asio_stream.h:113
Botan::TLS::CLIENT
Definition: tls_magic.h:32
Botan::TLS::Stream::copy_received_data
std::size_t copy_received_data(MutableBufferSequence buffers)
Copy decrypted data into the user-provided buffer.
Definition: asio_stream.h:602
Botan::TLS::Stream::native_handle
native_handle_type native_handle()
Definition: asio_stream.h:116
Botan::TLS::Stream::StreamCore::tls_session_established
bool tls_session_established(const Botan::TLS::Session &) override
Definition: asio_stream.h:565
Botan::TLS::detail::AsyncReadOperation
Definition: asio_async_ops.h:111
Botan::TLS::Stream::get_executor
executor_type get_executor() noexcept
Definition: asio_stream.h:108
Botan::TLS::detail::AsyncWriteOperation
Definition: asio_async_ops.h:201
Botan::TLS::Stream::async_write_some
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
Botan::TLS::Stream
boost::asio compatible SSL/TLS stream
Definition: asio_stream.h:49
Botan::TLS::Stream::m_send_buffer
boost::beast::flat_buffer m_send_buffer
Definition: asio_stream.h:702
Botan::ErrorType::Unknown
Botan
Definition: alg_id.cpp:13
Botan::TLS::Stream::read_some
std::size_t read_some(const MutableBufferSequence &buffers)
Read some data from the stream.
Definition: asio_stream.h:412
Botan::TLS::Stream::set_verify_depth
void set_verify_depth(int depth, boost::system::error_code &ec)
Definition: asio_stream.h:160
Botan::TLS::Stream::send_buffer
boost::asio::const_buffer send_buffer() const
Definition: asio_stream.h:595
BOTAN_UNUSED
#define BOTAN_UNUSED(...)
Definition: assert.h:142
Botan::TLS::Stream::tls_encrypt
void tls_encrypt(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Definition: asio_stream.h:669
Botan::TLS::Stream::BOOST_ASIO_INITFN_RESULT_TYPE
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void(boost::system::error_code, std::size_t)) async_handshake(Connection_Side side
Botan::TLS::Stream::StreamCore::m_receive_buffer
boost::beast::flat_buffer & m_receive_buffer
Definition: asio_stream.h:589
Botan::TLS::Stream::handshake
void handshake(Connection_Side side)
Performs SSL handshaking.
Definition: asio_stream.h:198
Botan::TLS::Policy
Definition: tls_policy.h:28
Botan::TLS::Stream::lowest_layer
const lowest_layer_type & lowest_layer() const
Definition: asio_stream.h:114
Botan::TLS::Context::get_verify_callback
const Verify_Callback & get_verify_callback() const
Definition: asio_context.h:94
Botan::TLS::Stream::has_data_to_send
bool has_data_to_send() const
Check if encrypted data is available in the send buffer.
Definition: asio_stream.h:614
init
int(* init)(CTX *)
Definition: commoncrypto_hash.cpp:26
Botan::TLS::Context::has_verify_callback
bool has_verify_callback() const
Definition: asio_context.h:89
Botan::TLS::Stream::StreamCore::~StreamCore
virtual ~StreamCore()=default
Botan::TLS::Stream::shutdown
void shutdown()
Shut down SSL on the stream.
Definition: asio_stream.h:331
Botan::TLS::Stream::StreamCore::tls_alert
void tls_alert(Botan::TLS::Alert alert) override
Definition: asio_stream.h:555
Botan::TLS::Stream::set_verify_mode
void set_verify_mode(verify_mode v)
Definition: asio_stream.h:168
Botan::TLS::Stream::m_input_buffer_space
std::vector< uint8_t > m_input_buffer_space
Definition: asio_stream.h:708
Botan::TLS::Context::m_session_manager
Session_Manager & m_session_manager
Definition: asio_context.h:109
Botan::TLS::Stream::has_received_data
bool has_received_data() const
Check if decrypted data is available in the receive buffer.
Definition: asio_stream.h:598
Botan::TLS::Stream::native_handle_type
typename std::add_pointer< ChannelT >::type native_handle_type
Definition: asio_stream.h:106
Botan::TLS::Stream::lowest_layer_type
typename next_layer_type::lowest_layer_type lowest_layer_type
Definition: asio_stream.h:104
Botan::TLS::Alert
Definition: tls_alert.h:21
Botan::TLS::Stream::Stream
Stream(Context &context, Args &&...args)
Construct a new Stream.
Definition: asio_stream.h:64
Botan::TLS::Stream::consume_send_buffer
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
Botan::TLS::TLS_Exception::type
Alert::Type type() const
Definition: tls_exceptn.h:24
Botan::TLS::Stream::m_native_handle
std::unique_ptr< ChannelT > m_native_handle
Definition: asio_stream.h:705
Botan::TLS::Stream::StreamCore::tls_verify_cert_chain
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
Botan::TLS::Context::Verify_Callback
detail::fn_signature_helper< decltype(&Callbacks::tls_verify_cert_chain)>::type Verify_Callback
Definition: asio_context.h:54
Botan::Usage_Type
Usage_Type
Definition: x509cert.h:25
Botan::TLS::TLS_Exception
Definition: tls_exceptn.h:21
Botan::TLS::Stream::set_verify_callback
void set_verify_callback(Context::Verify_Callback callback, boost::system::error_code &ec)
Compatibility overload of set_verify_callback.
Definition: asio_stream.h:142
Botan::TLS::Stream::m_receive_buffer
boost::beast::flat_buffer m_receive_buffer
Definition: asio_stream.h:701
Botan::TLS::Client
Definition: tls_client.h:24
Botan::TLS::Stream::StreamCore::m_tls_context
Context & m_tls_context
Definition: asio_stream.h:591
Botan::TLS::Stream::Stream
Stream(Arg &&arg, Context &context)
Construct a new Stream.
Definition: asio_stream.h:83