From eb6b59f2aef6a4999be244c7d90ace3f6bbcac5d Mon Sep 17 00:00:00 2001 From: lloyd Date: Wed, 28 Dec 2011 22:39:18 +0000 Subject: Don't buffer in the record writer at all - we immediately process and send out inputs as they are available. Thus, flushing is never required, and we avoid some unnecessary copying. If we are using a CBC mode cipher in SSLv3/TLSv1.0, send a 1-byte fragment to start to prevent the adaptive plaintext attack. --- src/tls/hello.cpp | 1 - src/tls/rec_wri.cpp | 76 +++++++++++++++++-------------------------------- src/tls/tls_channel.cpp | 2 -- src/tls/tls_client.cpp | 1 - src/tls/tls_record.h | 12 +++----- src/tls/tls_server.cpp | 2 -- 6 files changed, 30 insertions(+), 64 deletions(-) (limited to 'src/tls') diff --git a/src/tls/hello.cpp b/src/tls/hello.cpp index 45eedbd76..510aabb3a 100644 --- a/src/tls/hello.cpp +++ b/src/tls/hello.cpp @@ -32,7 +32,6 @@ void HandshakeMessage::send(Record_Writer& writer, TLS_Handshake_Hash& hash) con hash.update(send_buf); writer.send(HANDSHAKE, &send_buf[0], send_buf.size()); - writer.flush(); } /* diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp index ade2bd2d6..336c18ab4 100644 --- a/src/tls/rec_wri.cpp +++ b/src/tls/rec_wri.cpp @@ -22,7 +22,7 @@ namespace Botan { Record_Writer::Record_Writer(std::tr1::function out, size_t max_fragment) : output_fn(out), - buffer(max_fragment ? max_fragment : static_cast(MAX_PLAINTEXT_SIZE)) + max_fragment(clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE)) { mac = 0; reset(); @@ -38,10 +38,7 @@ void Record_Writer::reset() delete mac; mac = 0; - zeroise(buffer); - buf_pos = 0; - - major = minor = buf_type = 0; + major = minor = 0; block_size = 0; mac_size = 0; iv_size = 0; @@ -134,51 +131,35 @@ void Record_Writer::set_keys(const CipherSuite& suite, */ void Record_Writer::send(byte type, const byte input[], size_t length) { - if(type != buf_type) - flush(); - - const size_t BUFFER_SIZE = buffer.size(); - buf_type = type; - - // FIXME: compression right here - - buffer.copy(buf_pos, input, length); - if(buf_pos + length >= BUFFER_SIZE) + if(length == 0) + return; + + /* + * If using CBC mode in SSLv3/TLS1.0, send a single byte of + * plaintext to randomize the (implicit) IV of the following main + * block. If using a stream cipher, or TLS v1.1, this isn't + * necessary. + * + * An empty record also works but apparently some implementations do + * not like this. + * + * See http://www.openssl.org/~bodo/tls-cbc.txt for background. + */ + if((block_size > 0) && (iv_size == 0)) { - send_record(buf_type, &buffer[0], length); - input += (BUFFER_SIZE - buf_pos); - length -= (BUFFER_SIZE - buf_pos); - while(length >= BUFFER_SIZE) - { - send_record(buf_type, input, BUFFER_SIZE); - input += BUFFER_SIZE; - length -= BUFFER_SIZE; - } - buffer.copy(input, length); - buf_pos = 0; + send_record(type, &input[0], 1); + input += 1; + length -= 1; } - buf_pos += length; - } -/* -* Split buffer into records, and send them all -*/ -void Record_Writer::flush() - { - const byte* buf_ptr = &buffer[0]; - size_t offset = 0; - - while(offset != buf_pos) + while(length) { - size_t record_size = buf_pos - offset; - if(record_size > MAX_PLAINTEXT_SIZE) - record_size = MAX_PLAINTEXT_SIZE; + const size_t sending = std::min(length, max_fragment); + send_record(type, &input[0], sending); - send_record(buf_type, buf_ptr + offset, record_size); - offset += record_size; + input += sending; + length -= sending; } - buf_type = 0; - buf_pos = 0; } /* @@ -186,16 +167,12 @@ void Record_Writer::flush() */ void Record_Writer::send_record(byte type, const byte input[], size_t length) { - if(length >= MAX_COMPRESSED_SIZE) + if(length >= MAX_PLAINTEXT_SIZE) throw TLS_Exception(INTERNAL_ERROR, "Record_Writer: Compressed packet is too big"); if(mac_size == 0) { - if(length >= MAX_CIPHERTEXT_SIZE) - throw TLS_Exception(INTERNAL_ERROR, - "Record_Writer: Record is too big"); - const byte header[5] = { type, major, @@ -285,7 +262,6 @@ void Record_Writer::alert(Alert_Level level, Alert_Type type) { byte alert[2] = { level, type }; send(ALERT, alert, sizeof(alert)); - flush(); } } diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index 553f65836..96d08a5f4 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -166,7 +166,6 @@ void TLS_Channel::queue_for_sending(const byte buf[], size_t buf_size) } writer.send(APPLICATION_DATA, buf, buf_size); - writer.flush(); } else pre_handshake_write_queue.write(buf, buf_size); @@ -179,7 +178,6 @@ void TLS_Channel::alert(Alert_Level alert_level, Alert_Type alert_code) try { writer.alert(alert_level, alert_code); - writer.flush(); } catch(...) { /* swallow it */ } } diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index 5dbcadaea..b58a6766f 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -236,7 +236,6 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, state->server_hello->random()); writer.send(CHANGE_CIPHER_SPEC, 1); - writer.flush(); writer.set_keys(state->suite, state->keys, CLIENT); diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h index d2dbdf596..51a7cd310 100644 --- a/src/tls/tls_record.h +++ b/src/tls/tls_record.h @@ -43,8 +43,6 @@ class BOTAN_DLL Record_Writer void send(byte type, const byte input[], size_t length); void send(byte type, byte val) { send(type, &val, 1); } - void flush(); - void alert(Alert_Level level, Alert_Type type); void set_keys(const CipherSuite& suite, @@ -56,23 +54,21 @@ class BOTAN_DLL Record_Writer void reset(); Record_Writer(std::tr1::function output_fn, - size_t max_fragment = 0); + size_t max_fragment = MAX_PLAINTEXT_SIZE); ~Record_Writer() { delete mac; } private: void send_record(byte type, const byte input[], size_t length); std::tr1::function output_fn; + Pipe cipher; MessageAuthenticationCode* mac; - SecureVector buffer; - size_t buf_pos; - - size_t block_size, mac_size, iv_size; + size_t block_size, mac_size, iv_size, max_fragment; u64bit seq_no; - byte major, minor, buf_type; + byte major, minor; }; /** diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index a22e6854e..16bf554d3 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -184,7 +184,6 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, true); writer.send(CHANGE_CIPHER_SPEC, 1); - writer.flush(); writer.set_keys(state->suite, state->keys, SERVER); @@ -337,7 +336,6 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->hash.update(type, contents); writer.send(CHANGE_CIPHER_SPEC, 1); - writer.flush(); writer.set_keys(state->suite, state->keys, SERVER); -- cgit v1.2.3