aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/tls_handshake_io.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-10-25 22:25:40 -0400
committerJack Lloyd <[email protected]>2015-10-25 22:25:40 -0400
commitb2da74ca508745f00bb3d6b35cbe34d5031e27e7 (patch)
tree032fafd34f178af3b66877d52897f2e14359adaf /src/lib/tls/tls_handshake_io.cpp
parent2d078053b1ac7c1e2316892d8634c386288ee159 (diff)
TLS improvements
Use constant time operations when checking CBC padding in TLS decryption Fix a bug in decoding ClientHellos that prevented DTLS rehandshakes from working: on decode the session id and hello cookie would be swapped, causing confusion between client and server. Various changes in the service of finding the above DTLS bug that should have been done before now anyway - better control of handshake timeouts (via TLS::Policy), better reporting of handshake state in the case of an error, and finally expose the facility for per-message application callbacks.
Diffstat (limited to 'src/lib/tls/tls_handshake_io.cpp')
-rw-r--r--src/lib/tls/tls_handshake_io.cpp97
1 files changed, 47 insertions, 50 deletions
diff --git a/src/lib/tls/tls_handshake_io.cpp b/src/lib/tls/tls_handshake_io.cpp
index 6286eab08..f39c9f84e 100644
--- a/src/lib/tls/tls_handshake_io.cpp
+++ b/src/lib/tls/tls_handshake_io.cpp
@@ -1,6 +1,6 @@
/*
* TLS Handshake IO
-* (C) 2012,2014 Jack Lloyd
+* (C) 2012,2014,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -33,6 +33,24 @@ void store_be24(byte out[3], size_t val)
out[2] = get_byte<u32bit>(3, val);
}
+u64bit steady_clock_ms()
+ {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count();
+ }
+
+size_t split_for_mtu(size_t mtu, size_t msg_size)
+ {
+ const size_t DTLS_HEADERS_SIZE = 25; // DTLS record+handshake headers
+
+ const size_t parts = (msg_size + mtu) / mtu;
+
+ if(parts + DTLS_HEADERS_SIZE > mtu)
+ return parts + 1;
+
+ return parts;
+ }
+
}
Protocol_Version Stream_Handshake_IO::initial_record_version() const
@@ -123,41 +141,15 @@ Protocol_Version Datagram_Handshake_IO::initial_record_version() const
return Protocol_Version::DTLS_V10;
}
-namespace {
-
-// 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1
-const u64bit INITIAL_TIMEOUT = 1*1000;
-const u64bit MAXIMUM_TIMEOUT = 60*1000;
-
-u64bit steady_clock_ms()
+void Datagram_Handshake_IO::retransmit_last_flight()
{
- return std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::steady_clock::now().time_since_epoch()).count();
+ const size_t flight_idx = (m_flights.size() == 1) ? 0 : (m_flights.size() - 2);
+ retransmit_flight(flight_idx);
}
-}
-
-bool Datagram_Handshake_IO::timeout_check()
+void Datagram_Handshake_IO::retransmit_flight(size_t flight_idx)
{
- if(m_last_write == 0 || (m_flights.size() > 1 && !m_flights.rbegin()->empty()))
- {
- /*
- If we haven't written anything yet obviously no timeout.
- Also no timeout possible if we are mid-flight,
- */
- return false;
- }
-
- const u64bit ms_since_write = steady_clock_ms() - m_last_write;
-
- if(ms_since_write < m_next_timeout)
- return false;
-
- std::vector<u16bit> flight;
- if(m_flights.size() == 1)
- flight = m_flights.at(0); // lost initial client hello
- else
- flight = m_flights.at(m_flights.size() - 2);
+ const std::vector<u16bit>& flight = m_flights.at(flight_idx);
BOTAN_ASSERT(flight.size() > 0, "Nonempty flight to retransmit");
@@ -177,8 +169,27 @@ bool Datagram_Handshake_IO::timeout_check()
send_message(msg_seq, msg.epoch, msg.msg_type, msg.msg_bits);
epoch = msg.epoch;
}
+ }
+
+bool Datagram_Handshake_IO::timeout_check()
+ {
+ if(m_last_write == 0 || (m_flights.size() > 1 && !m_flights.rbegin()->empty()))
+ {
+ /*
+ If we haven't written anything yet obviously no timeout.
+ Also no timeout possible if we are mid-flight,
+ */
+ return false;
+ }
+
+ const u64bit ms_since_write = steady_clock_ms() - m_last_write;
+
+ if(ms_since_write < m_next_timeout)
+ return false;
- m_next_timeout = std::min(2 * m_next_timeout, MAXIMUM_TIMEOUT);
+ retransmit_last_flight();
+
+ m_next_timeout = std::min(2 * m_next_timeout, m_max_timeout);
return true;
}
@@ -251,7 +262,6 @@ Datagram_Handshake_IO::get_next_record(bool expecting_ccs)
if(m_ccs_epochs.count(current_epoch))
return std::make_pair(HANDSHAKE_CCS, std::vector<byte>());
}
-
return std::make_pair(HANDSHAKE_NONE, std::vector<byte>());
}
@@ -376,21 +386,6 @@ Datagram_Handshake_IO::format(const std::vector<byte>& msg,
return format_w_seq(msg, type, m_in_message_seq - 1);
}
-namespace {
-
-size_t split_for_mtu(size_t mtu, size_t msg_size)
- {
- const size_t DTLS_HEADERS_SIZE = 25; // DTLS record+handshake headers
-
- const size_t parts = (msg_size + mtu) / mtu;
-
- if(parts + DTLS_HEADERS_SIZE > mtu)
- return parts + 1;
-
- return parts;
- }
-
-}
std::vector<byte>
Datagram_Handshake_IO::send(const Handshake_Message& msg)
@@ -411,7 +406,7 @@ Datagram_Handshake_IO::send(const Handshake_Message& msg)
m_out_message_seq += 1;
m_last_write = steady_clock_ms();
- m_next_timeout = INITIAL_TIMEOUT;
+ m_next_timeout = m_initial_timeout;
return send_message(m_out_message_seq - 1, epoch, msg_type, msg_bits);
}
@@ -425,7 +420,9 @@ std::vector<byte> Datagram_Handshake_IO::send_message(u16bit msg_seq,
format_w_seq(msg_bits, msg_type, msg_seq);
if(no_fragment.size() + DTLS_HEADER_SIZE <= m_mtu)
+ {
m_send_hs(epoch, HANDSHAKE, no_fragment);
+ }
else
{
const size_t parts = split_for_mtu(m_mtu, msg_bits.size());