aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/relnotes/1_11_4.rst23
-rw-r--r--doc/relnotes/index.rst1
-rw-r--r--doc/tls.rst28
-rw-r--r--src/tls/tls_channel.cpp25
-rw-r--r--src/tls/tls_channel.h39
-rw-r--r--src/tls/tls_client.cpp14
-rw-r--r--src/tls/tls_client.h8
-rw-r--r--src/tls/tls_policy.cpp7
-rw-r--r--src/tls/tls_policy.h2
-rw-r--r--src/tls/tls_server.cpp5
-rw-r--r--src/tls/tls_server.h5
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