diff options
-rw-r--r-- | doc/manual/tls.rst | 144 | ||||
-rw-r--r-- | src/cli/tls_client.cpp | 38 | ||||
-rw-r--r-- | src/cli/tls_proxy.cpp | 17 | ||||
-rw-r--r-- | src/cli/tls_server.cpp | 12 | ||||
-rw-r--r-- | src/lib/tls/info.txt | 1 | ||||
-rw-r--r-- | src/lib/tls/tls_blocking.cpp | 8 | ||||
-rw-r--r-- | src/lib/tls/tls_blocking.h | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_callbacks.h | 106 | ||||
-rw-r--r-- | src/lib/tls/tls_channel.cpp | 31 | ||||
-rw-r--r-- | src/lib/tls/tls_channel.h | 23 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 9 | ||||
-rw-r--r-- | src/lib/tls/tls_client.h | 57 | ||||
-rw-r--r-- | src/lib/tls/tls_handshake_state.cpp | 10 | ||||
-rw-r--r-- | src/lib/tls/tls_handshake_state.h | 14 | ||||
-rw-r--r-- | src/lib/tls/tls_record.h | 4 | ||||
-rw-r--r-- | src/lib/tls/tls_server.cpp | 36 | ||||
-rw-r--r-- | src/lib/tls/tls_server.h | 23 | ||||
-rw-r--r-- | src/lib/tls/tls_server_handshake_state.h | 48 | ||||
-rw-r--r-- | src/tests/unit_tls.cpp | 93 |
19 files changed, 376 insertions, 300 deletions
diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst index a10a4280c..7210fc092 100644 --- a/doc/manual/tls.rst +++ b/doc/manual/tls.rst @@ -22,44 +22,52 @@ instance, by reading from a network socket) it passes that information to TLS using :cpp:func:`TLS::Channel::received_data`. If the data passed in results in some change in the state, such as a handshake completing, or some data or an alert being received from the other -side, then a user provided callback will be invoked. If the reader is -familiar with OpenSSL's BIO layer, it might be analagous to saying the -only way of interacting with Botan's TLS is via a `BIO_mem` I/O +side, then the appropriate user provided callback will be invoked. + +If the reader is familiar with OpenSSL's BIO layer, it might be analagous +to saying the only way of interacting with Botan's TLS is via a `BIO_mem` I/O abstraction. This makes the library completely agnostic to how you write your network layer, be it blocking sockets, libevent, asio, a -message queue, etc. +message queue, lwIP on RTOS, some carrier pidgeons, etc. -The callbacks for TLS have the signatures +Starting in 1.11.31, the application callbacks are encapsulated as the class +``TLS::Callbacks`` with the following members. The first four (``tls_emit_data``, +``tls_record_received``, ``tls_alert``, and ``tls_session_established``) are +mandatory for using TLS, all others are optional and provide additional +information about the connection. - .. cpp:function:: void output_fn(const byte data[], size_t data_len) + .. cpp:function:: void tls_emit_data(const byte data[], size_t data_len) - TLS requests that all bytes of *data* be queued up to send to the - counterparty. After this function returns, *data* will be - overwritten, so a copy of the input must be made if the callback + The TLS stack requests that all bytes of *data* be queued up to send to the + counterparty. After this function returns, the buffer containing *data* will + be overwritten, so a copy of the input must be made if the callback cannot send the data immediately. - .. cpp:function:: void data_cb(const byte data[], size_t data_len) + The write can be deferred but for TLS all writes must occur *in order*. + For DTLS this is not strictly required, but is still recommended. + + .. cpp:function:: void tls_record_received(uint64_t rec_no, const byte data[], size_t data_len) + + Called once for each application_data record which is received, with the + matching (TLS level) record sequence number. - Called whenever application data is received from the other side - of the connection, in which case *data* and *data_len* specify - the data received. This array will be overwritten sometime after - the callback returns, so again a copy should be made if need be. + Currently empty records are ignored and do not instigate a callback, + but this may change in a future release. - .. cpp:function:: void alert_cb(Alert alert, const byte data[], size_t data_len) + As with ``tls_emit_data``, the array will be overwritten sometime after + the callback returns, so a copy should be made if needed. - Called when an alert is received. Normally, data is null and - data_len is 0, as most alerts have no associated data. However, - if TLS heartbeats (see :rfc:`6520`) were negotiated, and we - initiated a heartbeat, then if/when the other party responds, - ``alert_cb`` will be called with whatever data was included in - the heartbeat response (if any) along with a psuedo-alert value - of ``HEARTBEAT_PAYLOAD``. + .. cpp:function:: void tls_alert(Alert alert) - .. cpp:function:: bool handshake_cb(const TLS::Session& session) + Called when an alert is received from the peer. Note that alerts + received before the handshake is complete are not authenticated and + could have been inserted by a MITM attacker. + + .. cpp:function:: bool tls_session_established(const TLS::Session& session) Called whenever a negotiation completes. This can happen more - than once on any connection. The *session* parameter provides - information about the session which was established. + than once on any connection, if renegotiation occurs. The *session* parameter + provides information about the session which was just established. If this function returns false, the session will not be cached for later resumption. @@ -68,8 +76,22 @@ The callbacks for TLS have the signatures exception which will send a close message to the counterparty and reset the connection state. -You can of course use tools like ``std::bind`` to bind additional -parameters to your callback functions. + .. cpp:function:: void tls_inspect_handshake_msg(const Handshake_Message&) + + This callback is optional, and can be used to inspect all handshake messages + while the session establishment occurs. + + .. cpp:function:: void tls_log_debug(const char*) + + This callback is for exerimental purposes and currently unused. It may be + removed or modified in a future release. + +Versions from 1.11.0 to 1.11.30 did not have ``TLS::Callbacks` and instead +used independent std::functions to pass the various callback functions. +This interface is currently still included but is deprecated and will be removed +in a future release. For the documentation for this interface, please check +the docs in 1.11.30. This version of the manual only documents the new interface +added in 1.11.31. TLS Channels ---------------------------------------- @@ -80,16 +102,6 @@ available: .. cpp:class:: TLS::Channel - .. cpp:type:: std::function<void (const byte[], size_t)> output_fn - - .. cpp:type:: std::function<void (const byte[], size_t)> data_cb - - .. cpp:type:: std::function<void (Alert, const byte[], size_t)> alert_cb - - .. cpp:type:: std::function<bool (const Session&)> handshake_cb - - Typedefs used in the code for the functions described above - .. cpp:function:: size_t received_data(const byte buf[], size_t buf_size) .. cpp:function:: size_t received_data(const std::vector<byte>& buf) @@ -194,10 +206,7 @@ TLS Clients .. cpp:class:: TLS::Client .. cpp:function:: Client( \ - output_fn out, \ - data_cb app_data_cb, \ - alert_cb alert_cb, \ - handshake_cb hs_cb, \ + Callbacks& callbacks, Session_Manager& session_manager, \ Credentials_Manager& creds, \ const Policy& policy, \ @@ -211,29 +220,8 @@ TLS Clients Initialize a new TLS client. The constructor will immediately initiate a new session. - The *output_fn* callback will be called with output that - should be sent to the counterparty. For instance this will be - called immediately from the constructor after the client hello - message is constructed. An implementation of *output_fn* is - allowed to defer the write (for instance if writing when the - callback occurs would block), but should eventually write the data - to the counterparty *in order*. - - The *data_cb* will be called with data sent by the counterparty - after it has been processed. The byte array and size_t represent - the plaintext value and size. - - The *alert_cb* will be called when a protocol alert is received, - commonly with a close alert during connection teardown. - - The *handshake_cb* function is called when a handshake - (either initial or renegotiation) is completed. The return value of - the callback specifies if the session should be cached for later - resumption. If the function for some reason desires to prevent the - connection from completing, it should throw an exception - (preferably a TLS::Exception, which can provide more specific alert - information to the counterparty). The :cpp:class:`TLS::Session` - provides information about the session that was just established. + The *callbacks* parameter specifies the various application callbacks + which pertain to this particular client connection. The *session_manager* is an interface for storing TLS sessions, which allows for session resumption upon reconnecting to a server. @@ -285,10 +273,7 @@ TLS Servers .. cpp:class:: TLS::Server .. cpp:function:: Server( \ - output_fn output, \ - data_cb data_cb, \ - alert_cb alert_cb, \ - handshake_cb handshake_cb, \ + Callbacks& callbacks, Session_Manager& session_manager, \ Credentials_Manager& creds, \ const Policy& policy, \ @@ -298,11 +283,11 @@ TLS Servers size_t reserved_io_buffer_size = 16*1024 \ ) -The first 8 arguments as well as the final argument +The first 5 arguments as well as the final argument *reserved_io_buffer_size*, are treated similiarly to the :ref:`client <tls_client>`. -The (optional) argument, *proto_chooser*, is a function called if the +The (optional) argument, *next_proto*, is a function called if the client sent the ALPN extension to negotiate an application protocol. In that case, the function should choose a protocol to use and return it. Alternately it can throw an exception to abort the @@ -312,7 +297,7 @@ should be of type `NO_APPLICATION_PROTOCOL`. The optional argument *is_datagram* specifies if this is a TLS or DTLS server; unlike clients, which know what type of protocol (TLS vs DTLS) they are negotiating from the start via the *offer_version*, servers -would not until they actually received a hello without this parameter. +would not until they actually received a client hello. Code for a TLS server using asio is in `src/cli/tls_proxy.cpp`. @@ -516,7 +501,7 @@ policy settings from a file. Values without an explicit mode use old-style CBC with HMAC encryption. Default value: "AES-256/GCM", "AES-128/GCM", "ChaCha20Poly1305", - "AES-256/CCM", "AES-128/CCM", "AES-256/CCM-8", "AES-128/CCM-8", + "AES-256/CCM", "AES-128/CCM", "AES-256/CCM(8)", "AES-128/CCM(8)", "AES-256", "AES-128" Also allowed: "Camellia-256/GCM", "Camellia-128/GCM", @@ -529,15 +514,18 @@ policy settings from a file. .. note:: - The current ChaCha20Poly1305 ciphersuites are non-standard but - as of 2015 were implemented and deployed by Google and - elsewhere. Support will be changed to using IETF standard - ChaCha20Poly1305 ciphersuites when those are defined. + Before 1.11.30 only the non-standard ChaCha20Poly1305 ciphersuite + was implemented. The RFC 7905 ciphersuites are supported in 1.11.30 + onwards. .. note:: Support for the broken RC4 cipher was removed in 1.11.17 + .. note:: + + SEED and 3DES are deprecated and will be removed in a future release. + .. cpp:function:: std::vector<std::string> allowed_macs() const Returns the list of algorithms we are willing to use for @@ -577,6 +565,10 @@ policy settings from a file. Also allowed (disabled by default): "" (meaning anonymous) + .. note:: + + DSA authentication is deprecated and will be removed in a future release. + .. cpp:function:: std::vector<std::string> allowed_ecc_curves() const Return a list of ECC curves we are willing to use, in order of preference. diff --git a/src/cli/tls_client.cpp b/src/cli/tls_client.cpp index e2fc1f027..082daf4ac 100644 --- a/src/cli/tls_client.cpp +++ b/src/cli/tls_client.cpp @@ -36,7 +36,7 @@ namespace Botan_CLI { -class TLS_Client final : public Command +class TLS_Client final : public Command, public Botan::TLS::Callbacks { public: TLS_Client() : Command("tls_client host --port=443 --print-certs --policy= " @@ -99,15 +99,10 @@ class TLS_Client final : public Command const std::vector<std::string> protocols_to_offer = Botan::split_on("next-protocols", ','); - int sockfd = connect_to_host(host, port, use_tcp); + m_sockfd = connect_to_host(host, port, use_tcp); using namespace std::placeholders; - auto socket_write = - use_tcp ? - std::bind(stream_socket_write, sockfd, _1, _2) : - std::bind(dgram_socket_write, sockfd, _1, _2); - auto version = policy->latest_supported_version(!use_tcp); if(flag_set("tls1.0")) @@ -119,11 +114,7 @@ class TLS_Client final : public Command version = Botan::TLS::Protocol_Version::TLS_V11; } - Botan::TLS::Client client(Botan::TLS::Callbacks( - socket_write, - std::bind(&TLS_Client::process_data, this, _1, _2), - std::bind(&TLS_Client::alert_received, this, _1), - std::bind(&TLS_Client::handshake_complete, this, _1)), + Botan::TLS::Client client(*this, *session_mgr, creds, *policy, @@ -138,7 +129,7 @@ class TLS_Client final : public Command { fd_set readfds; FD_ZERO(&readfds); - FD_SET(sockfd, &readfds); + FD_SET(m_sockfd, &readfds); if(client.is_active()) { @@ -154,13 +145,13 @@ class TLS_Client final : public Command struct timeval timeout = { 1, 0 }; - ::select(sockfd + 1, &readfds, nullptr, nullptr, &timeout); + ::select(m_sockfd + 1, &readfds, nullptr, nullptr, &timeout); - if(FD_ISSET(sockfd, &readfds)) + if(FD_ISSET(m_sockfd, &readfds)) { uint8_t buf[4*1024] = { 0 }; - ssize_t got = ::read(sockfd, buf, sizeof(buf)); + ssize_t got = ::read(m_sockfd, buf, sizeof(buf)); if(got == 0) { @@ -218,7 +209,7 @@ class TLS_Client final : public Command } } - ::close(sockfd); + ::close(m_sockfd); } private: @@ -258,7 +249,7 @@ class TLS_Client final : public Command return fd; } - bool handshake_complete(const Botan::TLS::Session& session) + bool tls_session_established(const Botan::TLS::Session& session) override { output() << "Handshake complete, " << session.version().to_string() << " using " << session.ciphersuite().to_string() << "\n"; @@ -292,13 +283,13 @@ class TLS_Client final : public Command throw CLI_Error("Socket write failed errno=" + std::to_string(errno)); } - static void stream_socket_write(int sockfd, const uint8_t buf[], size_t length) + void tls_emit_data(const uint8_t buf[], size_t length) override { size_t offset = 0; while(length) { - ssize_t sent = ::send(sockfd, (const char*)buf + offset, + ssize_t sent = ::send(m_sockfd, (const char*)buf + offset, length, MSG_NOSIGNAL); if(sent == -1) @@ -314,16 +305,19 @@ class TLS_Client final : public Command } } - void alert_received(Botan::TLS::Alert alert) + void tls_alert(Botan::TLS::Alert alert) { output() << "Alert: " << alert.type_string() << "\n"; } - void process_data(const uint8_t buf[], size_t buf_size) + void tls_record_received(uint64_t seq_no, const uint8_t buf[], size_t buf_size) { for(size_t i = 0; i != buf_size; ++i) output() << buf[i]; } + + private: + int m_sockfd; }; BOTAN_REGISTER_COMMAND("tls_client", TLS_Client); diff --git a/src/cli/tls_proxy.cpp b/src/cli/tls_proxy.cpp index d52a67631..5140654de 100644 --- a/src/cli/tls_proxy.cpp +++ b/src/cli/tls_proxy.cpp @@ -60,7 +60,7 @@ void log_text_message(const char* where, const uint8_t buf[], size_t buf_len) //std::cout << where << ' ' << std::string(c, c + buf_len) << std::endl; } -class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_session> +class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_session>, public Botan::TLS::Callbacks { public: enum { readbuf_size = 4 * 1024 }; @@ -112,10 +112,7 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio m_server_endpoints(endpoints), m_client_socket(io), m_server_socket(io), - m_tls(Botan::TLS::Callbacks(boost::bind(&tls_proxy_session::tls_proxy_write_to_client, this, _1, _2), - boost::bind(&tls_proxy_session::tls_client_write_to_proxy, this, _1, _2), - boost::bind(&tls_proxy_session::tls_alert_cb, this, _1), - boost::bind(&tls_proxy_session::tls_handshake_complete, this, _1)), + m_tls(*this, session_manager, credentials, policy, @@ -168,7 +165,7 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio { m_client_socket.close(); } - tls_proxy_write_to_client(nullptr, 0); // initiate another write if needed + tls_emit_data(nullptr, 0); // initiate another write if needed } void handle_server_write_completion(const boost::system::error_code& error) @@ -184,13 +181,13 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio proxy_write_to_server(nullptr, 0); // initiate another write if needed } - void tls_client_write_to_proxy(const uint8_t buf[], size_t buf_len) + void tls_record_received(uint64_t /*rec_no*/, const uint8_t buf[], size_t buf_len) override { // Immediately bounce message to server proxy_write_to_server(buf, buf_len); } - void tls_proxy_write_to_client(const uint8_t buf[], size_t buf_len) + void tls_emit_data(const uint8_t buf[], size_t buf_len) override { if(buf_len > 0) m_p2c_pending.insert(m_p2c_pending.end(), buf, buf + buf_len); @@ -269,7 +266,7 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio boost::asio::placeholders::bytes_transferred))); } - bool tls_handshake_complete(const Botan::TLS::Session& session) + bool tls_session_established(const Botan::TLS::Session& session) override { //std::cout << "Handshake from client complete" << std::endl; @@ -293,7 +290,7 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio return true; } - void tls_alert_cb(Botan::TLS::Alert alert) + void tls_alert(Botan::TLS::Alert alert) override { if(alert.type() == Botan::TLS::Alert::CLOSE_NOTIFY) { diff --git a/src/cli/tls_server.cpp b/src/cli/tls_server.cpp index dffd30f66..2496f5508 100644 --- a/src/cli/tls_server.cpp +++ b/src/cli/tls_server.cpp @@ -1,7 +1,6 @@ /* * TLS echo server using BSD sockets * (C) 2014 Jack Lloyd -* 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -107,11 +106,10 @@ class TLS_Server final : public Command } }; - Botan::TLS::Server server(Botan::TLS::Callbacks( - socket_write, - proc_fn, - std::bind(&TLS_Server::alert_received, this, _1), - std::bind(&TLS_Server::handshake_complete, this, _1)), + Botan::TLS::Server server(socket_write, + proc_fn, + std::bind(&TLS_Server::alert_received, this, _1, _2, _3), + std::bind(&TLS_Server::handshake_complete, this, _1), session_manager, creds, policy, @@ -238,7 +236,7 @@ class TLS_Server final : public Command } } - void alert_received(Botan::TLS::Alert alert) + void alert_received(Botan::TLS::Alert alert, const uint8_t[], size_t) { std::cout << "Alert: " << alert.type_string() << std::endl; } diff --git a/src/lib/tls/info.txt b/src/lib/tls/info.txt index b62adc17f..208c4ebb2 100644 --- a/src/lib/tls/info.txt +++ b/src/lib/tls/info.txt @@ -30,7 +30,6 @@ tls_messages.h tls_reader.h tls_record.h tls_seq_numbers.h -tls_server_handshake_state.h tls_session_key.h </header:internal> diff --git a/src/lib/tls/tls_blocking.cpp b/src/lib/tls/tls_blocking.cpp index 3910d242c..34ebc6c91 100644 --- a/src/lib/tls/tls_blocking.cpp +++ b/src/lib/tls/tls_blocking.cpp @@ -24,12 +24,13 @@ Blocking_Client::Blocking_Client(read_fn reader, const Protocol_Version& offer_version, const std::vector<std::string>& next) : m_read(reader), - m_channel(TLS::Callbacks( + m_callbacks(new TLS::Compat_Callbacks( writer, std::bind(&Blocking_Client::data_cb, this, _1, _2), - std::bind(&Blocking_Client::alert_cb, this, _1), + std::function<void (Alert)>(std::bind(&Blocking_Client::alert_cb, this, _1)), std::bind(&Blocking_Client::handshake_cb, this, _1) - ), + )), + m_channel(*m_callbacks.get(), session_manager, creds, policy, @@ -38,6 +39,7 @@ Blocking_Client::Blocking_Client(read_fn reader, offer_version, next) { + printf("hi\n"); } bool Blocking_Client::handshake_cb(const Session& session) diff --git a/src/lib/tls/tls_blocking.h b/src/lib/tls/tls_blocking.h index cba44b524..0f2986710 100644 --- a/src/lib/tls/tls_blocking.h +++ b/src/lib/tls/tls_blocking.h @@ -33,6 +33,7 @@ class BOTAN_DLL Blocking_Client typedef std::function<size_t (byte[], size_t)> read_fn; typedef std::function<void (const byte[], size_t)> write_fn; + BOTAN_DEPRECATED("Use the regular TLS::Client interface") Blocking_Client(read_fn reader, write_fn writer, Session_Manager& session_manager, @@ -93,6 +94,7 @@ class BOTAN_DLL Blocking_Client void alert_cb(const Alert& alert); read_fn m_read; + std::unique_ptr<Compat_Callbacks> m_callbacks; TLS::Client m_channel; secure_vector<byte> m_plaintext; }; diff --git a/src/lib/tls/tls_callbacks.h b/src/lib/tls/tls_callbacks.h index 216c58ce2..db1b70693 100644 --- a/src/lib/tls/tls_callbacks.h +++ b/src/lib/tls/tls_callbacks.h @@ -1,6 +1,7 @@ /* * TLS Callbacks * (C) 2016 Matthias Gierlings +* 2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -14,33 +15,76 @@ namespace Botan { namespace TLS { -class Handshake_State; class Handshake_Message; /** -* Virtual Interface for TLS-Channel related callback handling. The default -* implementations involving std::function are only provided for compatibility -* purposes. New implementations should override the virtual member methods -* out_fn(), app_data(), alert(), handshake() and handshake_msg() instead. -* +* Encapsulates the callbacks that a TLS channel will make which are due to +* channel specific operations. */ class BOTAN_DLL Callbacks { public: + virtual ~Callbacks() {} + + /** + * Mandatory callback: output function + * The channel will call this with data which needs to be sent to the peer + * (eg, over a socket or some other form of IPC). The array will be overwritten + * when the function returns so a copy must be made if the data cannot be + * sent immediately. + */ + virtual void tls_emit_data(const uint8_t data[], size_t size) = 0; + + /** + * Mandatory callback: process application data + * Called when application data record is received from the peer. + * Again the array is overwritten immediately after the function returns. + * seq_no is the underlying TLS/DTLS record sequence number. + */ + virtual void tls_record_received(u64bit seq_no, const uint8_t data[], size_t size) = 0; + + /** + * Mandary callback: alert received + * Called when an alert is received from the peer + * If fatal, the connection is closing. If not fatal, the connection may + * still be closing (depending on the error and the peer). + */ + virtual void tls_alert(Alert alert) = 0; + + /** + * Mandatory callback: session established + * Called when a session is established. Throw an exception to abort + * the connection. Return false to prevent the session from being cached. + * Return true to cache the session in the configured session manager. + */ + virtual bool tls_session_established(const Session& session) = 0; + + /** + * Optional callback: inspect handshake message + */ + virtual void tls_inspect_handshake_msg(const Handshake_Message&) {} + + /** + * Optional callback: debug logging. (not currently used) + */ + virtual bool tls_log_debug(const char*) { return false; } + }; + +/** +* TLS::Callbacks using std::function for compatability with the old API signatures. +* This type is only provided for backward compatibility. +* New implementations should derive from TLS::Callbacks instead. +*/ +class BOTAN_DLL Compat_Callbacks final : public Callbacks + { + public: typedef std::function<void (const byte[], size_t)> output_fn; typedef std::function<void (const byte[], size_t)> data_cb; - typedef std::function<void (Alert)> alert_cb; + typedef std::function<void (Alert, const byte[], size_t)> alert_cb; typedef std::function<bool (const Session&)> handshake_cb; typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; /** - * DEPRECATED: This constructor is only provided for backward - * compatibility. New implementations should override the - * virtual member methods out_fn(), app_data(), alert(), - * handshake() and handshake_msg() and use the default constructor - * Callbacks(). - * - * Encapsulates a set of callback functions required by a TLS Channel. * @param output_fn is called with data for the outbound socket * * @param app_data_cb is called when new application data is received @@ -49,48 +93,50 @@ class BOTAN_DLL Callbacks * * @param handshake_cb is called when a handshake is completed */ - BOTAN_DEPRECATED("Use TLS::Callbacks() (virtual interface).") - Callbacks(output_fn out, data_cb app_data_cb, alert_cb alert_cb, - handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) + BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") + Compat_Callbacks(output_fn out, data_cb app_data_cb, alert_cb alert_cb, + handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) : m_output_function(out), m_app_data_cb(app_data_cb), - m_alert_cb(alert_cb), m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} + m_alert_cb(std::bind(alert_cb, std::placeholders::_1, nullptr, 0)), + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} - Callbacks() - : m_output_function(nullptr), m_app_data_cb(nullptr), - m_alert_cb(nullptr), m_hs_cb(nullptr), m_hs_msg_cb(nullptr) {} - - - virtual ~Callbacks() {} + BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") + Compat_Callbacks(output_fn out, data_cb app_data_cb, + std::function<void (Alert)> alert_cb, + handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) + : m_output_function(out), m_app_data_cb(app_data_cb), + m_alert_cb(alert_cb), + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} - virtual void out_fn(const byte data[], size_t size) const + void tls_emit_data(const byte data[], size_t size) override { BOTAN_ASSERT(m_output_function != nullptr, "Invalid TLS output function callback."); m_output_function(data, size); } - virtual void app_data(const byte data[], size_t size) const + void tls_record_received(u64bit /*seq_no*/, const byte data[], size_t size) override { BOTAN_ASSERT(m_app_data_cb != nullptr, "Invalid TLS app data callback."); m_app_data_cb(data, size); } - virtual void alert(Alert alert) const + void tls_alert(Alert alert) override { BOTAN_ASSERT(m_alert_cb != nullptr, "Invalid TLS alert callback."); m_alert_cb(alert); } - virtual bool handshake(const Session& session) const + bool tls_session_established(const Session& session) override { BOTAN_ASSERT(m_hs_cb != nullptr, "Invalid TLS handshake callback."); return m_hs_cb(session); } - virtual void handshake_msg(const Handshake_Message& hmsg) const + void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override { // The handshake message callback is optional so we can // not assume it has been set. @@ -100,7 +146,7 @@ class BOTAN_DLL Callbacks private: const output_fn m_output_function; const data_cb m_app_data_cb; - const alert_cb m_alert_cb; + const std::function<void (Alert)> m_alert_cb; const handshake_cb m_hs_cb; const handshake_msg_cb m_hs_msg_cb; }; diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp index b78796536..5f882af64 100644 --- a/src/lib/tls/tls_channel.cpp +++ b/src/lib/tls/tls_channel.cpp @@ -1,6 +1,6 @@ /* * TLS Channels -* (C) 2011,2012,2014,2015 Jack Lloyd +* (C) 2011,2012,2014,2015,2016 Jack Lloyd * 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) @@ -21,7 +21,7 @@ namespace TLS { size_t TLS::Channel::IO_BUF_DEFAULT_SIZE = 10*1024; -Channel::Channel(const Callbacks& callbacks, +Channel::Channel(Callbacks& callbacks, Session_Manager& session_manager, RandomNumberGenerator& rng, const Policy& policy, @@ -47,7 +47,8 @@ Channel::Channel(output_fn out, bool is_datagram, size_t io_buf_sz) : m_is_datagram(is_datagram), - m_callbacks(Callbacks(out, app_data_cb, alert_cb, hs_cb, hs_msg_cb)), + m_compat_callbacks(new Compat_Callbacks(out, app_data_cb, alert_cb, hs_cb, hs_msg_cb)), + m_callbacks(*m_compat_callbacks.get()), m_session_manager(session_manager), m_policy(policy), m_rng(rng) @@ -319,15 +320,15 @@ size_t Channel::received_data(const byte input[], size_t input_size) if(record_type == HANDSHAKE || record_type == CHANGE_CIPHER_SPEC) { - process_handshake_ccs(record_data, record_sequence, record_type, record_version); + process_handshake_ccs(record_data, record_sequence, record_type, record_version); } else if(record_type == APPLICATION_DATA) { - process_application_data(record_data); + process_application_data(record_sequence, record_data); } else if(record_type == ALERT) { - process_alert(record_data); + process_alert(record_data); } else if(record_type != NO_RECORD) throw Unexpected_Message("Unexpected record type " + @@ -359,10 +360,10 @@ size_t Channel::received_data(const byte input[], size_t input_size) } } -void Channel::process_handshake_ccs(secure_vector<byte>& record, - u64bit& record_sequence, - Record_Type& record_type, - Protocol_Version& record_version) +void Channel::process_handshake_ccs(const secure_vector<byte>& record, + u64bit record_sequence, + Record_Type record_type, + Protocol_Version record_version) { if(!m_pending_state) { @@ -422,7 +423,7 @@ void Channel::process_handshake_ccs(secure_vector<byte>& record, } } -void Channel::process_application_data(secure_vector<byte>& record) +void Channel::process_application_data(u64bit seq_no, const secure_vector<byte>& record) { if(!active_state()) throw Unexpected_Message("Application data before handshake done"); @@ -433,17 +434,17 @@ void Channel::process_application_data(secure_vector<byte>& record) * following record. Avoid spurious callbacks. */ if(record.size() > 0) - m_callbacks.app_data(record.data(), record.size()); + callbacks().tls_record_received(seq_no, record.data(), record.size()); } -void Channel::process_alert(secure_vector<byte>& record) +void Channel::process_alert(const secure_vector<byte>& record) { Alert alert_msg(record); if(alert_msg.type() == Alert::NO_RENEGOTIATION) m_pending_state.reset(); - m_callbacks.alert(alert_msg); + callbacks().tls_alert(alert_msg); if(alert_msg.is_fatal()) { @@ -478,7 +479,7 @@ void Channel::write_record(Connection_Cipher_State* cipher_state, u16bit epoch, cipher_state, m_rng); - m_callbacks.out_fn(m_writebuf.data(), m_writebuf.size()); + callbacks().tls_emit_data(m_writebuf.data(), m_writebuf.size()); } void Channel::send_record_array(u16bit epoch, byte type, const byte input[], size_t length) diff --git a/src/lib/tls/tls_channel.h b/src/lib/tls/tls_channel.h index 7c59e1d6f..073af760f 100644 --- a/src/lib/tls/tls_channel.h +++ b/src/lib/tls/tls_channel.h @@ -36,12 +36,12 @@ class BOTAN_DLL Channel public: typedef std::function<void (const byte[], size_t)> output_fn; typedef std::function<void (const byte[], size_t)> data_cb; - typedef std::function<void (Alert)> alert_cb; + typedef std::function<void (Alert, const byte[], size_t)> alert_cb; typedef std::function<bool (const Session&)> handshake_cb; typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; static size_t IO_BUF_DEFAULT_SIZE; - Channel(const Callbacks& callbacks, + Channel(Callbacks& callbacks, Session_Manager& session_manager, RandomNumberGenerator& rng, const Policy& policy, @@ -215,9 +215,9 @@ class BOTAN_DLL Channel const Policy& policy() const { return m_policy; } - bool save_session(const Session& session) const { return m_callbacks.handshake(session); } + bool save_session(const Session& session) const { return callbacks().tls_session_established(session); } - Callbacks get_callbacks() const { return m_callbacks; } + Callbacks& callbacks() const { return m_callbacks; } private: void init(size_t io_buf_sze); @@ -245,19 +245,20 @@ class BOTAN_DLL Channel const Handshake_State* pending_state() const { return m_pending_state.get(); } /* methods to handle incoming traffic through Channel::receive_data. */ - void process_handshake_ccs(secure_vector<byte>& record, - u64bit& record_sequence, - Record_Type& record_type, - Protocol_Version& record_version); + void process_handshake_ccs(const secure_vector<byte>& record, + u64bit record_sequence, + Record_Type record_type, + Protocol_Version record_version); - void process_application_data(secure_vector<byte>& record); + void process_application_data(u64bit req_no, const secure_vector<byte>& record); - void process_alert(secure_vector<byte>& record); + void process_alert(const secure_vector<byte>& record); bool m_is_datagram; /* callbacks */ - Callbacks m_callbacks; + std::unique_ptr<Compat_Callbacks> m_compat_callbacks; + Callbacks& m_callbacks; /* external state */ Session_Manager& m_session_manager; diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index ab7beddbd..f77521c03 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -24,7 +24,7 @@ class Client_Handshake_State : public Handshake_State public: // using Handshake_State::Handshake_State; - Client_Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State(io, cb) {} + Client_Handshake_State(Handshake_IO* io, Callbacks& cb) : Handshake_State(io, cb) {} const Public_Key& get_server_public_Key() const { @@ -43,7 +43,7 @@ class Client_Handshake_State : public Handshake_State /* * TLS Client Constructor */ -Client::Client(const Callbacks& callbacks, +Client::Client(Callbacks& callbacks, Session_Manager& session_manager, Credentials_Manager& creds, const Policy& policy, @@ -112,10 +112,7 @@ void Client::init(const Protocol_Version& protocol_version, Handshake_State* Client::new_handshake_state(Handshake_IO* io) { - return new Client_Handshake_State(io, - std::bind(&TLS::Callbacks::handshake_msg, - get_callbacks(), - std::placeholders::_1)); + return new Client_Handshake_State(io, callbacks()); } std::vector<X509_Certificate> diff --git a/src/lib/tls/tls_client.h b/src/lib/tls/tls_client.h index 6452294cd..09af053af 100644 --- a/src/lib/tls/tls_client.h +++ b/src/lib/tls/tls_client.h @@ -23,6 +23,7 @@ namespace TLS { class BOTAN_DLL Client final : public Channel { public: + /** * Set up a new TLS client session * @@ -48,7 +49,51 @@ class BOTAN_DLL Client final : public Channel * be preallocated for the read and write buffers. Smaller * values just mean reallocations and copies are more likely. */ + Client(Callbacks& callbacks, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const Server_Information& server_info = Server_Information(), + const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(), + const std::vector<std::string>& next_protocols = {}, + size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE + ); + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new code. + * + * Set up a new TLS client session + * + * @param output_fn is called with data for the outbound socket + * + * @param app_data_cb is called when new application data is received + * + * @param alert_cb is called when a TLS alert is received + * + * @param handshake_cb is called when a handshake is completed + * + * @param session_manager manages session state + * + * @param creds manages application/user credentials + * + * @param policy specifies other connection policy information + * + * @param rng a random number generator + * + * @param server_info is identifying information about the TLS server + * + * @param offer_version specifies which version we will offer + * to the TLS server. + * + * @param next_protocols specifies protocols to advertise with ALPN + * + * @param reserved_io_buffer_size This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. + */ + BOTAN_DEPRECATED("Use TLS::Client(TLS::Callbacks ...)") Client(output_fn out, data_cb app_data_cb, alert_cb alert_cb, @@ -82,18 +127,6 @@ class BOTAN_DLL Client final : public Channel const std::vector<std::string>& next_protocols = {} ); - - Client(const Callbacks& callbacks, - Session_Manager& session_manager, - Credentials_Manager& creds, - const Policy& policy, - RandomNumberGenerator& rng, - const Server_Information& server_info = Server_Information(), - const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(), - const std::vector<std::string>& next_protocols = {}, - size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE - ); - const std::string& application_protocol() const { return m_application_protocol; } private: void init(const Protocol_Version& protocol_version, diff --git a/src/lib/tls/tls_handshake_state.cpp b/src/lib/tls/tls_handshake_state.cpp index afc32ba87..71cacdabd 100644 --- a/src/lib/tls/tls_handshake_state.cpp +++ b/src/lib/tls/tls_handshake_state.cpp @@ -8,6 +8,7 @@ #include <botan/internal/tls_handshake_state.h> #include <botan/internal/tls_messages.h> #include <botan/internal/tls_record.h> +#include <botan/tls_callbacks.h> namespace Botan { @@ -174,8 +175,8 @@ std::string handshake_mask_to_string(u32bit mask) /* * Initialize the SSL/TLS Handshake State */ -Handshake_State::Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : - m_msg_callback(cb), +Handshake_State::Handshake_State(Handshake_IO* io, Callbacks& cb) : + m_callbacks(cb), m_handshake_io(io), m_version(m_handshake_io->initial_record_version()) { @@ -183,6 +184,11 @@ Handshake_State::Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State::~Handshake_State() {} +void Handshake_State::note_message(const Handshake_Message& msg) + { + m_callbacks.tls_inspect_handshake_msg(msg); + } + void Handshake_State::hello_verify_request(const Hello_Verify_Request& hello_verify) { note_message(hello_verify); diff --git a/src/lib/tls/tls_handshake_state.h b/src/lib/tls/tls_handshake_state.h index 2943a8637..bdec10d14 100644 --- a/src/lib/tls/tls_handshake_state.h +++ b/src/lib/tls/tls_handshake_state.h @@ -24,6 +24,7 @@ class KDF; namespace TLS { +class Callbacks; class Policy; class Hello_Verify_Request; @@ -45,9 +46,7 @@ class Finished; class Handshake_State { public: - typedef std::function<void (const Handshake_Message&)> handshake_msg_cb; - - Handshake_State(Handshake_IO* io, handshake_msg_cb cb); + Handshake_State(Handshake_IO* io, Callbacks& callbacks); virtual ~Handshake_State(); @@ -164,15 +163,10 @@ class Handshake_State const Handshake_Hash& hash() const { return m_handshake_hash; } - void note_message(const Handshake_Message& msg) - { - if(m_msg_callback) - m_msg_callback(msg); - } - + void note_message(const Handshake_Message& msg); private: - handshake_msg_cb m_msg_callback; + Callbacks& m_callbacks; std::unique_ptr<Handshake_IO> m_handshake_io; diff --git a/src/lib/tls/tls_record.h b/src/lib/tls/tls_record.h index 53e447af6..c16b919b5 100644 --- a/src/lib/tls/tls_record.h +++ b/src/lib/tls/tls_record.h @@ -102,10 +102,6 @@ class Record m_type(type), m_size(data.size()) {}; secure_vector<byte>& get_data() { return m_data; } - void set_data(secure_vector<byte> data) - { - m_data.swap(data); - } Protocol_Version* get_protocol_version() { return m_protocol_version; } diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 96af3cc90..5eccec2a7 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -8,7 +8,6 @@ #include <botan/tls_server.h> #include <botan/internal/tls_handshake_state.h> -#include <botan/internal/tls_server_handshake_state.h> #include <botan/internal/tls_messages.h> #include <botan/internal/stl_util.h> #include <botan/tls_magic.h> @@ -17,9 +16,34 @@ namespace Botan { namespace TLS { -namespace { +class Server_Handshake_State : public Handshake_State + { + public: + Server_Handshake_State(Handshake_IO* io, Callbacks& cb) + : Handshake_State(io, cb) {} + + Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key; } + void set_server_rsa_kex_key(Private_Key* key) + { m_server_rsa_kex_key = key; } + + bool allow_session_resumption() const + { return m_allow_session_resumption; } + void set_allow_session_resumption(bool allow_session_resumption) + { m_allow_session_resumption = allow_session_resumption; } + + private: + // Used by the server only, in case of RSA key exchange. Not owned + Private_Key* m_server_rsa_kex_key = nullptr; + /* + * Used by the server to know if resumption should be allowed on + * a server-initiated renegotiation + */ + bool m_allow_session_resumption = true; + }; + +namespace { bool check_for_resume(Session& session_info, Session_Manager& session_manager, @@ -213,7 +237,7 @@ get_server_certs(const std::string& hostname, /* * TLS Server Constructor */ -Server::Server(const Callbacks& callbacks, +Server::Server(Callbacks& callbacks, Session_Manager& session_manager, Credentials_Manager& creds, const Policy& policy, @@ -268,11 +292,7 @@ Server::Server(output_fn output, Handshake_State* Server::new_handshake_state(Handshake_IO* io) { - std::unique_ptr<Handshake_State> state( - new Server_Handshake_State(io, - std::bind(&TLS::Callbacks::handshake_msg, - get_callbacks(), - std::placeholders::_1))); + std::unique_ptr<Handshake_State> state(new Server_Handshake_State(io, callbacks())); state->set_expected_next(CLIENT_HELLO); return state.release(); diff --git a/src/lib/tls/tls_server.h b/src/lib/tls/tls_server.h index c0960a66e..508dde440 100644 --- a/src/lib/tls/tls_server.h +++ b/src/lib/tls/tls_server.h @@ -30,8 +30,29 @@ class BOTAN_DLL Server final : public Channel /** * Server initialization + * + * @param callbacks contains a set of callback function references + * required by the TLS client. + * + * @param session_manager manages session state + * + * @param creds manages application/user credentials + * + * @param policy specifies other connection policy information + * + * @param rng a random number generator + * + * @param next_proto is called with client's ALPN protocol list + * and returns chosen protocol. + * + * @param is_datagram set to true if this server should expect DTLS + * connections. Otherwise TLS connections are expected. + * + * @param reserved_io_buffer_size This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. */ - Server(const Callbacks& callbacks, + Server(Callbacks& callbacks, Session_Manager& session_manager, Credentials_Manager& creds, const Policy& policy, diff --git a/src/lib/tls/tls_server_handshake_state.h b/src/lib/tls/tls_server_handshake_state.h deleted file mode 100644 index c65cade96..000000000 --- a/src/lib/tls/tls_server_handshake_state.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -* TLS Server -* (C) 2004-2011,2012,2016 Jack Lloyd -* 2016 Matthias Gierlings -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_TLS_SERVER_HANDSHAKE_STATE_H__ -#define BOTAN_TLS_SERVER_HANDSHAKE_STATE_H__ - -#include <botan/internal/tls_handshake_state.h> -namespace Botan { - -namespace TLS { - -class Server_Handshake_State : public Handshake_State - { - public: - Server_Handshake_State(Handshake_IO* io, handshake_msg_cb cb) - : Handshake_State(io, cb) {} - - Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key; } - void set_server_rsa_kex_key(Private_Key* key) - { m_server_rsa_kex_key = key; } - - bool allow_session_resumption() const - { return m_allow_session_resumption; } - void set_allow_session_resumption(bool allow_session_resumption) - { m_allow_session_resumption = allow_session_resumption; } - - - private: - // Used by the server only, in case of RSA key exchange. Not owned - Private_Key* m_server_rsa_kex_key = nullptr; - - /* - * Used by the server to know if resumption should be allowed on - * a server-initiated renegotiation - */ - bool m_allow_session_resumption = true; - }; - -} - -} - -#endif diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index 150ed2794..2797e7d21 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -166,6 +166,10 @@ void print_alert(Botan::TLS::Alert) { } +void alert_cb_with_data(Botan::TLS::Alert, const byte[], size_t) + { + } + Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, Botan::Credentials_Manager& creds, Botan::TLS::Policy& policy) @@ -219,27 +223,31 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, { std::vector<byte> c2s_traffic, s2c_traffic, client_recv, server_recv, client_sent, server_sent; + std::unique_ptr<Botan::TLS::Callbacks> server_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(s2c_traffic), + queue_inserter(server_recv), + std::function<void (Botan::TLS::Alert, const byte[], size_t)>(alert_cb_with_data), + handshake_complete)); + // TLS::Server object constructed by new constructor using virtual callback interface. std::unique_ptr<Botan::TLS::Server> server( - new Botan::TLS::Server(Botan::TLS::Callbacks( - queue_inserter(s2c_traffic), - queue_inserter(server_recv), - print_alert, - handshake_complete), - server_sessions, - creds, - policy, - rng, - next_protocol_chooser, - false)); + new Botan::TLS::Server(*server_cb, + server_sessions, + creds, + policy, + rng, + next_protocol_chooser, + false)); + + std::unique_ptr<Botan::TLS::Callbacks> client_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(c2s_traffic), + queue_inserter(client_recv), + std::function<void (Botan::TLS::Alert, const byte[], size_t)>(alert_cb_with_data), + handshake_complete)); // TLS::Client object constructed by new constructor using virtual callback interface. std::unique_ptr<Botan::TLS::Client> client( - new Botan::TLS::Client(Botan::TLS::Callbacks( - queue_inserter(c2s_traffic), - queue_inserter(client_recv), - print_alert, - handshake_complete), + new Botan::TLS::Client(*client_cb, client_sessions, creds, policy, @@ -255,11 +263,18 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, { if(ctor_sel == 1) { + c2s_traffic.clear(); + s2c_traffic.clear(); + server_recv.clear(); + client_recv.clear(); + client_sent.clear(); + server_sent.clear(); + // TLS::Server object constructed by legacy constructor. - server = std::unique_ptr<Botan::TLS::Server>( + server.reset( new Botan::TLS::Server(queue_inserter(s2c_traffic), queue_inserter(server_recv), - print_alert, + alert_cb_with_data, handshake_complete, server_sessions, creds, @@ -269,10 +284,10 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, false)); // TLS::Client object constructed by legacy constructor. - std::unique_ptr<Botan::TLS::Client> client( + client.reset( new Botan::TLS::Client(queue_inserter(c2s_traffic), queue_inserter(client_recv), - print_alert, + alert_cb_with_data, handshake_complete, client_sessions, creds, @@ -485,13 +500,21 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, { std::vector<byte> c2s_traffic, s2c_traffic, client_recv, server_recv, client_sent, server_sent; + std::unique_ptr<Botan::TLS::Callbacks> server_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(s2c_traffic), + queue_inserter(server_recv), + std::function<void (Botan::TLS::Alert)>(print_alert), + handshake_complete)); + + std::unique_ptr<Botan::TLS::Callbacks> client_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(c2s_traffic), + queue_inserter(client_recv), + std::function<void (Botan::TLS::Alert)>(print_alert), + handshake_complete)); + // TLS::Server object constructed by new constructor using virtual callback interface. std::unique_ptr<Botan::TLS::Server> server( - new Botan::TLS::Server(Botan::TLS::Callbacks( - queue_inserter(s2c_traffic), - queue_inserter(server_recv), - print_alert, - handshake_complete), + new Botan::TLS::Server(*server_cb, server_sessions, creds, policy, @@ -501,11 +524,7 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, // TLS::Client object constructed by new constructor using virtual callback interface. std::unique_ptr<Botan::TLS::Client> client( - new Botan::TLS::Client(Botan::TLS::Callbacks( - queue_inserter(c2s_traffic), - queue_inserter(client_recv), - print_alert, - handshake_complete), + new Botan::TLS::Client(*client_cb, client_sessions, creds, policy, @@ -521,11 +540,17 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, { if(ctor_sel == 1) { + c2s_traffic.clear(); + s2c_traffic.clear(); + server_recv.clear(); + client_recv.clear(); + client_sent.clear(); + server_sent.clear(); // TLS::Server object constructed by legacy constructor. - server = std::unique_ptr<Botan::TLS::Server>( + server.reset( new Botan::TLS::Server(queue_inserter(s2c_traffic), queue_inserter(server_recv), - print_alert, + alert_cb_with_data, handshake_complete, server_sessions, creds, @@ -535,10 +560,10 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, true)); // TLS::Client object constructed by legacy constructor. - std::unique_ptr<Botan::TLS::Client> client( + client.reset( new Botan::TLS::Client(queue_inserter(c2s_traffic), queue_inserter(client_recv), - print_alert, + alert_cb_with_data, handshake_complete, client_sessions, creds, |