diff options
-rw-r--r-- | doc/relnotes/1_11_4.rst | 23 | ||||
-rw-r--r-- | doc/relnotes/index.rst | 1 | ||||
-rw-r--r-- | doc/tls.rst | 28 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 25 | ||||
-rw-r--r-- | src/tls/tls_channel.h | 39 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 14 | ||||
-rw-r--r-- | src/tls/tls_client.h | 8 | ||||
-rw-r--r-- | src/tls/tls_policy.cpp | 7 | ||||
-rw-r--r-- | src/tls/tls_policy.h | 2 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 5 | ||||
-rw-r--r-- | src/tls/tls_server.h | 5 |
11 files changed, 106 insertions, 51 deletions
diff --git a/doc/relnotes/1_11_4.rst b/doc/relnotes/1_11_4.rst index 91a33ae58..b33798a13 100644 --- a/doc/relnotes/1_11_4.rst +++ b/doc/relnotes/1_11_4.rst @@ -9,14 +9,29 @@ Version 1.11.4, Not Yet Released in x86 builds, relying on runtime cpuid checking to prevent their use on CPUs that do not support those operations. +* The default TLS policy now only accepts TLS, to minimize surprise + for servers which might not expect to negotiate DTLS. Previously a + server would by default negotiate either protocol type (clients + would only accept the same protocol type as they + offered). Applications which use DTLS or combined TLS/DTLS need to + override :cpp:func:`Policy::acceptable_protocol_version`. + +* The TLS channels now accept a new parameter specifying how many + bytes to preallocate for the record handling buffers, which allows + an application some control over how much memory is used at runtime + for a particular connection. + +* Applications can now send arbitrary TLS alert messages using + :cpp:func:`TLS::Channel::send_alert` + +* A new TLS policy :cpp:class:`NSA_Suite_B_128` is available, which + will negotiate only the 128-bit security NSA Suite B. See + :rfc:`6460` for more information about Suite B. + * Adds a new interface for benchmarking, :cpp:func:`time_algorithm_ops`, which returns a map of operations to operations per second. For instance now both encrypt and decrypt speed of a block cipher can be checked, as well as the key schedule of all keyed algorithms. It additionally supports AEAD modes. -* A new TLS policy :cpp:class:`NSA_Suite_B_128` is available, which - will negotiate only the 128-bit security NSA Suite B. See - :rfc:`6460` for more information about Suite B. - * Rename ARC4 to RC4 diff --git a/doc/relnotes/index.rst b/doc/relnotes/index.rst index 633ac79bb..c905796ba 100644 --- a/doc/relnotes/index.rst +++ b/doc/relnotes/index.rst @@ -8,6 +8,7 @@ Series 1.11 .. toctree:: :maxdepth: 1 + 1_11_4 1_11_3 1_11_2 1_11_1 diff --git a/doc/tls.rst b/doc/tls.rst index df08c088a..93955d31c 100644 --- a/doc/tls.rst +++ b/doc/tls.rst @@ -113,6 +113,11 @@ available: A close notification is sent to the counterparty, and the internal state is cleared. + .. cpp:function void send_alert(const Alert& alert) + + Some other alert is sent to the counterparty. If the alert is + fatal, the internal state is cleared. + .. cpp:function:: bool is_active() Returns true if and only if a handshake has been completed on @@ -181,7 +186,8 @@ TLS Clients RandomNumberGenerator& rng, \ const Server_Information& server_info, \ const Protocol_Version offer_version, \ - std::function<std::string, std::vector<std::string> > next_protocol) + std::function<std::string, std::vector<std::string> > next_protocol, \ + size_t reserved_io_buffer_size) Initialize a new TLS client. The constructor will immediately initiate a new session. @@ -249,6 +255,12 @@ TLS Clients server advertises, and the client can select from them or return an unadvertised protocol. + The optional *reserved_io_buffer_size* specifies how many bytes to + pre-allocate in the I/O buffers. Use this if you want to control + how much memory the channel uses initially (the buffers will be + resized as needed to process inputs). Otherwise some reasonable + default is used. + A simple TLS client example: .. literalinclude:: examples/tls_client.cpp @@ -266,11 +278,13 @@ TLS Servers Credentials_Manager& creds, \ const TLS::Policy& policy, \ RandomNumberGenerator& rng, \ - const std::vector<std::string>& protocols) + const std::vector<std::string>& protocols, \ + bool reserved_io_buffer_size) -The first 7 arguments are treated similiarly to the :ref:`client -<tls_client>`. The final (optional) argument, protocols, specifies -the protocols the server is willing to advertise it supports. +The first 7 arguments as well as the final argument +*reserved_io_buffer_size*, are treated similiarly to the :ref:`client +<tls_client>`. The (optional) argument, *protocols*, specifies the +protocols the server is willing to advertise it supports. .. cpp:function:: std::string TLS::Server::next_protocol() const @@ -544,7 +558,9 @@ be negotiated during a handshake. Return true if this version of the protocol is one that we are willing to negotiate. - Default: True for all known protocol versions + Default: True if a known TLS version. DTLS is not accepted by default; + to enable DTLS (or combined TLS/DTLS) in your application, override this + function. .. cpp:function:: bool server_uses_own_ciphersuite_preferences() const diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index 51e0c11e5..20d882a40 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -23,15 +23,25 @@ Channel::Channel(std::function<void (const byte[], size_t)> output_fn, std::function<void (const byte[], size_t, Alert)> proc_fn, std::function<bool (const Session&)> handshake_complete, Session_Manager& session_manager, - RandomNumberGenerator& rng) : + RandomNumberGenerator& rng, + size_t reserved_io_buffer_size) : m_handshake_fn(handshake_complete), m_proc_fn(proc_fn), m_output_fn(output_fn), m_rng(rng), m_session_manager(session_manager) { - m_writebuf.reserve(16*1024); - m_readbuf.reserve(16*1024); + m_writebuf.reserve(reserved_io_buffer_size); + m_readbuf.reserve(reserved_io_buffer_size); + } + +void Channel::reset_state() + { + m_active_state.reset(); + m_pending_state.reset(); + m_readbuf.clear(); + m_write_cipher_states.clear(); + m_read_cipher_states.clear(); } Channel::~Channel() @@ -379,9 +389,7 @@ size_t Channel::received_data(const byte input[], size_t input_size) if(alert_msg.type() == Alert::CLOSE_NOTIFY || alert_msg.is_fatal()) { - m_active_state.reset(); - m_pending_state.reset(); - + reset_state(); return 0; } } @@ -530,10 +538,7 @@ void Channel::send_alert(const Alert& alert) m_session_manager.remove_entry(active->server_hello()->session_id()); if(alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal()) - { - m_active_state.reset(); - m_pending_state.reset(); - } + reset_state(); } void Channel::secure_renegotiation_check(const Client_Hello* client_hello) diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h index be3ef3e6d..2dd810c84 100644 --- a/src/tls/tls_channel.h +++ b/src/tls/tls_channel.h @@ -50,6 +50,23 @@ class BOTAN_DLL Channel void send(const std::string& string); /** + * Send a TLS alert message. If the alert is fatal, the internal + * state (keys, etc) will be reset. + * @param alert the Alert to send + */ + void send_alert(const Alert& alert); + + /** + * Send a warning alert + */ + void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); } + + /** + * Send a fatal alert + */ + void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); } + + /** * Send a close notification alert */ void close() { send_warning_alert(Alert::CLOSE_NOTIFY); } @@ -119,7 +136,8 @@ class BOTAN_DLL Channel std::function<void (const byte[], size_t, Alert)> proc_fn, std::function<bool (const Session&)> handshake_complete, Session_Manager& session_manager, - RandomNumberGenerator& rng); + RandomNumberGenerator& rng, + size_t reserved_io_buffer_size); Channel(const Channel&) = delete; @@ -143,23 +161,6 @@ class BOTAN_DLL Channel Handshake_State& create_handshake_state(Protocol_Version version); - /** - * Send a TLS alert message. If the alert is fatal, the internal - * state (keys, etc) will be reset. - * @param alert the Alert to send - */ - void send_alert(const Alert& alert); - - /** - * Send a warning alert - */ - void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); } - - /** - * Send a fatal alert - */ - void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); } - void activate_session(); void change_cipher_spec_reader(Connection_Side side); @@ -200,6 +201,8 @@ class BOTAN_DLL Channel std::shared_ptr<Connection_Cipher_State> write_cipher_state_epoch(u16bit epoch) const; + void reset_state(); + const Handshake_State* active_state() const { return m_active_state.get(); } const Handshake_State* pending_state() const { return m_pending_state.get(); } diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index e24e9739b..a6093e474 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -56,8 +56,9 @@ Client::Client(std::function<void (const byte[], size_t)> output_fn, RandomNumberGenerator& rng, const Server_Information& info, const Protocol_Version offer_version, - std::function<std::string (std::vector<std::string>)> next_protocol) : - Channel(output_fn, proc_fn, handshake_fn, session_manager, rng), + std::function<std::string (std::vector<std::string>)> next_protocol, + size_t io_buf_sz) : + Channel(output_fn, proc_fn, handshake_fn, session_manager, rng, io_buf_sz), m_policy(policy), m_creds(creds), m_info(info) @@ -253,9 +254,12 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { // new session - BOTAN_ASSERT_EQUAL(state.client_hello()->version().is_datagram_protocol(), - state.server_hello()->version().is_datagram_protocol(), - "Server replied with same protocol type client offered"); + if(state.client_hello()->version().is_datagram_protocol() != + state.server_hello()->version().is_datagram_protocol()) + { + throw TLS_Exception(Alert::PROTOCOL_VERSION, + "Server replied with different protocol type than we offered"); + } if(state.version() > state.client_hello()->version()) { diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h index b40896e94..c8c2edd4e 100644 --- a/src/tls/tls_client.h +++ b/src/tls/tls_client.h @@ -52,6 +52,10 @@ class BOTAN_DLL Client : public Channel * and if the server supports NPN the function will be * called with the list of protocols the server advertised; * the client should return the protocol it would like to use. + * + * @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. */ Client(std::function<void (const byte[], size_t)> socket_output_fn, std::function<void (const byte[], size_t, Alert)> proc_fn, @@ -63,7 +67,9 @@ class BOTAN_DLL Client : public Channel const Server_Information& server_info = Server_Information(), const Protocol_Version offer_version = Protocol_Version::latest_tls_version(), std::function<std::string (std::vector<std::string>)> next_protocol = - std::function<std::string (std::vector<std::string>)>()); + std::function<std::string (std::vector<std::string>)>(), + size_t reserved_io_buffer_size = 16*1024 + ); private: std::vector<X509_Certificate> get_peer_cert_chain(const Handshake_State& state) const override; diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp index 5a6cca2f6..12c761f98 100644 --- a/src/tls/tls_policy.cpp +++ b/src/tls/tls_policy.cpp @@ -134,10 +134,11 @@ u32bit Policy::session_ticket_lifetime() const bool Policy::acceptable_protocol_version(Protocol_Version version) const { - return version.known_version(); // accept any version we know about + if(!version.known_version()) + return false; - // maybe someday... - //return version >= Protocol_Version::TLS_V11; + // By default require TLS to minimize surprise + return !version.is_datagram_protocol(); } namespace { diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h index f80bffb71..6cc41fc50 100644 --- a/src/tls/tls_policy.h +++ b/src/tls/tls_policy.h @@ -122,6 +122,8 @@ class BOTAN_DLL Policy /** * @return true if and only if we are willing to accept this version + * Default accepts only TLS, so override if you want to enable DTLS + * in your application. */ virtual bool acceptable_protocol_version(Protocol_Version version) const; diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 6f4aaf4c3..1e87af483 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -215,8 +215,9 @@ Server::Server(std::function<void (const byte[], size_t)> output_fn, Credentials_Manager& creds, const Policy& policy, RandomNumberGenerator& rng, - const std::vector<std::string>& next_protocols) : - Channel(output_fn, proc_fn, handshake_fn, session_manager, rng), + const std::vector<std::string>& next_protocols, + size_t io_buf_sz) : + Channel(output_fn, proc_fn, handshake_fn, session_manager, rng, io_buf_sz), m_policy(policy), m_creds(creds), m_possible_protocols(next_protocols) diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h index 25c5b6506..f32636777 100644 --- a/src/tls/tls_server.h +++ b/src/tls/tls_server.h @@ -32,8 +32,9 @@ class BOTAN_DLL Server : public Channel Credentials_Manager& creds, const Policy& policy, RandomNumberGenerator& rng, - const std::vector<std::string>& protocols = - std::vector<std::string>()); + const std::vector<std::string>& protocols = std::vector<std::string>(), + size_t reserved_io_buffer_size = 16*1024 + ); /** * Return the protocol notification set by the client (using the |